php正常的一個輸出過高需要經(jīng)歷的階段:
echo/print -> php buffer -> tcp buffer -> browser
一,buffer ---- flush()
buffer是一個內(nèi)存地址空間,Linux系統(tǒng)默認(rèn)大小一般為4096(1kb),即一個內(nèi)存頁乞巧。主要用于存儲速度不同步的設(shè)備或者優(yōu)先級不同的 設(shè)備之間傳辦理數(shù)據(jù)的區(qū)域。通過buffer摊鸡,可以使進程這間的相互等待變少绽媒。這里說一個通俗一點的例子,你打開文本編輯器編輯一個文件的時候免猾,你每輸入 一個字符是辕,操作系統(tǒng)并不會立即把這個字符直接寫入到磁盤,而是先寫入到buffer猎提,當(dāng)寫滿了一個buffer的時候获三,才會把buffer中的數(shù)據(jù)寫入磁 盤,當(dāng)然當(dāng)調(diào)用內(nèi)核函數(shù)flush()的時候,強制要求把buffer中的臟數(shù)據(jù)寫回磁盤疙教。
同樣的道理棺聊,當(dāng)執(zhí)行echo,print的時候,輸出并沒有立即通過tcp傳給客戶端瀏覽器顯示, 而是將數(shù)據(jù)寫入php buffer贞谓。php output_buffering機制限佩,意味在tcp buffer之前,建立了一新的隊列裸弦,數(shù)據(jù)必須經(jīng)過該隊列祟同。當(dāng)一個php buffer寫滿的時候,腳本進程會將php buffer中的輸出數(shù)據(jù)交給系統(tǒng)內(nèi)核交由tcp傳給瀏覽器顯示烁兰。
二耐亏,php output_buffering --- ob_flush()
默認(rèn)情況下,php buffer是開啟的沪斟,而且該buffer默認(rèn)值是4096广辰,即1kb。你可以通過在php.ini配置文件中找到output_buffering配置.當(dāng)echo,print等輸出用戶數(shù)據(jù)的時候主之,輸出數(shù)據(jù)都會寫入到php output_buffering中择吊,直到output_buffering寫滿,會將這些數(shù)據(jù)通過tcp傳送給瀏覽器顯示槽奕。你也可以通過 ob_start()手動激活php output_buffering機制几睛,使得即便輸出超過了1kb數(shù)據(jù),也不真的把數(shù)據(jù)交給tcp傳給瀏覽器粤攒,因為ob_start()將php buffer空間設(shè)置到了足夠大 所森。只有直到腳本結(jié)束,或者調(diào)用ob_end_flush函數(shù)夯接,才會把數(shù)據(jù)發(fā)送給客戶端瀏覽器焕济。
這兩個函數(shù)的使用怕是很多人最迷惑的一個問題,手冊上對兩個函數(shù)的解釋也語焉不詳盔几,沒有明確的指出它們的區(qū)別晴弃,似乎二者的功能都是刷新輸出緩存。但在我們文章一開始的代碼中如果講fush()替換成ob_flush()逊拍,程序就再不能正確執(zhí)行了上鞠。顯然,它們是有區(qū)別的芯丧,否則也手冊中直接說明其中一個是另外一個函數(shù)的別名即可了芍阎,沒必要分別說明。那么它們的區(qū)別到底是什么呢缨恒?
在沒有開啟緩存時谴咸,腳本輸出的內(nèi)容都在服務(wù)器端處于等待輸出的狀態(tài) 度硝,flush()可以將等待輸出的內(nèi)容立即發(fā)送到客戶端。
開啟緩存后寿冕,腳本輸出的內(nèi)容存入了輸出緩存中 ,這時沒有處于等待輸出狀態(tài)的內(nèi)容椒袍,你直接使用flush()不會向客戶端發(fā)出任何內(nèi)容驼唱。而 ob_flush()的作用就是將本來存在輸出緩存中的內(nèi)容取出來,設(shè)置為等待輸出狀態(tài)驹暑,但不會直接發(fā)送到客戶端 玫恳,這時你就需要先使用 ob_flush()再使用flush(),客戶端才能立即獲得腳本的輸出优俘。
三京办,測試
3.1,output_buffering=4096帆焕,輸出較少的數(shù)據(jù)(少于一個buffer)
<?php
for($i=0; $i<10; $i++){
echo $i.'<br>';
sleep(1);
}
運行結(jié)果:等所有腳本全部運行完成后惭婿,才輸出,因為數(shù)據(jù)未滿一個buffer的大小叶雹。
3.2.output_buffering=4096财饥,輸出較少的數(shù)據(jù)(少于一個buffer),關(guān)閉output_buffering折晦,修改php.ini的output_buffering=0
<?php
for($i=0; $i<10; $i++){
echo $i.str_repeat(" ",1000).'<br>'; // 為了瀏覽器能夠顯示
flush();
sleep(1);
}
運行結(jié)果:因為禁用了php buffering钥星,不需要等到腳本運行完畢就可以輸出,數(shù)據(jù)沒有在php buffer停留满着,可以看到斷斷續(xù)續(xù)間歇性輸出谦炒。echo -> tcp buffer ->browser
參考博文:
https://blog.csdn.net/fdipzone/article/details/10367837
http://www.laruence.com/2010/04/15/1414.html
https://www.cnblogs.com/zhangyuhang3/p/6873502.html
http://niliu.me/articles/605.html#comment-2983