PHP的ob_flush()與flush()區別

 

PHP的ob_flush()與flush()區別

標籤: php ob-flush flush buffer
 分類:

說明:純屬我的實踐中的理解以及一些總結,理解有誤或有疑問之處,請告知,共同進步。linux

1、首先說一下buffer。apache

buffer是指內存地址空間。 
一、Linux系統默認大小通常爲4096(4kb)。 
其主要用是存儲速度不一樣步或者優先級不一樣的設備之間傳處理數據的區域,可使進程之間的相互等待變少。例如,當你打開一個編輯器,輸入字符,操做系統並不會當即把這個字符直接寫入到磁盤,而是先寫入到buffer,當寫滿了一個buffer的時候,纔會把buffer中的數據寫入磁盤,當調用內核函數flush()(這裏指的是linux內核函數)的時候,強制要求把buffer中的數據寫回磁盤。 
二、PHP也有本身的buffer機制。 
默認是開啓的,大小默認4096(4kb),在php.ini配置文件中由output_buffering配置。當執行php執行echo,print的時候,是先將數據寫入php的buffer,當一個php buffer寫滿的時候,腳本進程會將php 的buffer數據發送給系統內核交由tcp傳給瀏覽器顯示。 
三、瀏覽器buffer。 
目前瀏覽器廣泛爲8000Bytes(可能用戶能夠設置,未親測),測試 Chrome與360極速模式爲8000Bytes,只有輸出數據達到了這個長度或者腳本結束瀏覽器纔會將數據輸出在頁面上。 
四、數據流程。 
echo/pring -> php buffer -> tcp buffer (服務器系統buffer)-> 瀏覽器 buffer ->瀏覽器展現瀏覽器

2、ob_flush()與flush()及周邊函數ruby

ob_flush():把數據從PHP的緩衝(buffer)中釋放出來。 
flush():把不在緩衝(buffer)中的或者說是被釋放出來的數據發送到瀏覽器。服務器

代碼示例1:代碼效果,每隔一秒輸出一個數字。markdown

for($j = 1; $j <= 5; $j++) { echo str_repeat($i,1).'<br>'; //str_repeat()是將一個字符串重複n次 ob_flush(); //將數據從php的buffer中釋放出來 flush(); //將釋放出來的數據發送給瀏覽器 sleep(1); //一秒鐘後繼續執行 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

遇到問題:按理解,在最新的谷歌瀏覽器以及360瀏覽器效果都是每隔一秒輸出數字是正常的,可是在一個很是老的谷歌版本中(版本 28.0.1500.72)測試是四秒以後直接所有輸出,當str_repeat()函數的第二個參數設置成1020及以上數字的時候,又是一秒展現一個數字。在360兼容模式下沒法輸出。tcp

代碼示例2:關閉php.ini文件的output_buffering配置,重啓apache。編輯器

for($i=1; $i<5; $i++){ echo str_repeat($i,1).'<br>'; //ob_flush();//若開啓這行代碼,會報failed to flush buffer。由於buffer已關閉 flush(); sleep(1); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

遇到問題:按理解,flush()函數是將echo出來的數據發送給瀏覽器,若是瀏覽器的buffer沒有滿,則會等腳本執行完成再展現,可是在最新版本的谷歌以及360瀏覽器中都是隔一秒再輸出的。按這個結果理解,彷佛flush函數直接讓瀏覽器的buffer釋放出來,而後展現。可是在谷歌老版本(版本 28.0.1500.72)中,倒是在4秒以後一次性展現的,當str_repeat()函數的第二個參數設置成1020及以上數字的時候,又是一秒展現一個數字。實在沒法理解。在360兼容模式下沒法輸出。函數

代碼示例3:不關閉output_buffering配置,並設置成4096,重啓apache。

for($i=1; $i<5; $i++){ echo str_repeat($i,4096).'<br>'; //ob_flush(); //flush(); sleep(1); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

說明:當str_repeat()的第二個參數爲3997到7996時,會一秒輸出兩個數字,說明設置有效,而且瀏覽器的buffer是8000(我的理解<br>佔了四個字節)字節。可是當小於3997時,$i<10時,是四個數字輸出一次,這個位置較難理解,實際數據傳輸是這樣的: 
第一次echo的數據在php的buffer -> 
第二次echo的數據與第一次數據相加,大小大於4096,輸出給瀏覽器,但相加小於8000,瀏覽器不輸出 -> 第三次echo數據在php的buffer -> 
第四次echo數據傳送給瀏覽器,瀏覽器的buffer大於8000,展現出來。

代碼示例4:關閉output_buffering配置,重啓apache。

for($i=1; $i<5; $i++){ echo str_repeat($i,7996).'<br>'; //ob_flush(); //flush(); sleep(1); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

說明:該代碼只是爲了測試瀏覽器的buffer大小,最新谷歌瀏覽器以及360瀏覽器設置成7996及以上數字時,會一秒輸出一個數字。

代碼總結:在最新的谷歌瀏覽器以及360瀏覽器中,對flush函數的處理彷佛是將瀏覽器的buffer也拋出直接展現。

周邊函數

ob_start() : 激活php output_buffering機制,在不寫參數狀況下,ob_start()將php buffer空間設置 
到了足夠大 ,只有腳本執行結束,或者調用ob_end_flush函數,纔會把數據發送給客戶端瀏覽器。ob_start()函數內的參數能夠設置output_buffering大小及輸出機制。具體能夠查看手冊。 
ob_end_flush與ob_end_clean:都會關閉ouput_buffering機制。不一樣的是,ob_end_flush只是把php buffer中的數據傳送到瀏覽器,而ob_clean_clean將php bufeer中的數據清空,但不發送給客戶端瀏覽器。 還有更多周邊函數,不在這裏一一贅述了。

相關文章
相關標籤/搜索