PHP的ob_flush()與flush()區別
說明:純屬個人實踐中的理解以及一些總結,理解有誤或有疑問之處,請告知,共同進步。
一、首先說一下buffer。
buffer是指記憶體地址空間。
1、Linux系統預設大小一般為4096(4kb)。
其主要用是儲存速度不同步或者優先順序不同的裝置之間傳處理資料的區域,可以使程式之間的相互等待變少。例如,當你開啟一個編輯器,輸入字元,作業系統並不會立即把這個字元直接寫入到磁碟,而是先寫入到buffer,當寫滿了一個buffer的時候,才會把buffer中的資料寫入磁碟,當呼叫核心函式flush()(這裡指的是linux核心函式)的時候,強制要求把buffer中的資料寫回磁碟。
2、PHP也有自己的buffer機制。
預設是開啟的,大小預設4096(4kb),在php.ini配置檔案中由output_buffering配置。當執行php執行echo,print的時候,是先將資料寫入php的buffer,當一個php buffer寫滿的時候,指令碼程式會將php 的buffer資料傳送給系統核心交由tcp傳給瀏覽器顯示。
3、瀏覽器buffer。
目前瀏覽器普遍為8000Bytes(可能使用者可以設定,未親測),測試 Chrome與360極速模式為8000Bytes,只有輸出資料達到了這個長度或者指令碼結束瀏覽器才會將資料輸出在頁面上。
4、資料流程。
echo/pring -> php buffer -> tcp buffer (伺服器系統buffer)-> 瀏覽器 buffer ->瀏覽器展示
二、ob_flush()與flush()及周邊函式
ob_flush():把資料從PHP的緩衝(buffer)中釋放出來。
flush():把不在緩衝(buffer)中的或者說是被釋放出來的資料傳送到瀏覽器。
程式碼示例1:程式碼效果,每隔一秒輸出一個數字。
for($j = 1; $j <= 5; $j++) {
echo str_repeat($i,1).'<br>'; //str_repeat()是將一個字串重複n次
ob_flush(); //將資料從php的buffer中釋放出來
flush(); //將釋放出來的資料傳送給瀏覽器
sleep(1); //一秒鐘後繼續執行
}
遇到問題:按理解,在最新的谷歌瀏覽器以及360瀏覽器效果都是每隔一秒輸出數字是正常的,但是在一個非常老的谷歌版本中(版本 28.0.1500.72)測試是四秒之後直接全部輸出,當str_repeat()函式的第二個引數設定成1020及以上數字的時候,又是一秒展示一個數字。在360相容模式下無法輸出。
程式碼示例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);
}
遇到問題:按理解,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);
}
說明:當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);
}
說明:該程式碼只是為了測試瀏覽器的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中的資料清空,但不傳送給客戶端瀏覽器。
還有更多周邊函式,不在這裡一一贅述了。
相關文章
- PHP7 ?? 與 ?: 的作用和區別PHP
- PHP abstract與interface之間的區別PHP
- PHP中explode與split的區別分析PHP
- CGI,FastCGI,PHP-CGI與PHP-FPM的區別ASTPHP
- 深入剖析PHP輸入流php://input(與POST/GET的區別)PHP
- PHP isset()與empty()的使用區別詳解PHP
- php中explode與split的區別介紹PHP
- PHP版本的區別PHP
- PHP中isset()與empty()的使用區別詳解PHP
- hibernate學習(六) flush()和clean()區別和使用
- CGI,FastCGI,PHP-CGI與PHP-FPM區別詳解ASTPHP
- PHP 中的 -> 和 :: 的區別PHP
- java與php區別或異同(整理、整合)JavaPHP
- ??與?:的區別
- PHP中new static()與new self()的區別異同分析PHP
- [php]require&require_once&include&include_once的用法與區別PHPUI
- PHP 設計模式答疑-物件池與依賴注入的區別PHP設計模式物件依賴注入
- 【PHP】PHP基礎知識與C++、Java等C家族的重點區別PHPC++Java
- php中TCP和UDP的區別PHPTCPUDP
- php定義常量方法的區別PHP
- Apache、Nginx、Tomcat、PHP的區別ApacheNginxTomcatPHP
- ***PHP中empty()和isset()的區別PHP
- MySQL的@與@@區別MySql
- mybatis #與$的區別MyBatis
- Null 與 “” 的區別Null
- &與&&, |與||區別
- 什麼是python?與PHP有什麼區別?PythonPHP
- in與exist , not in與not exist 的區別
- PHP的執行緒安全與非執行緒安全版本的區別PHP執行緒
- PHP new self()和new static()的區別PHP
- PHP, Python和Java的區別分享PHPPythonJava
- PHP中session和cookie的區別薦PHPSessionCookie
- 解析php中die(),exit(),return的區別PHP
- CentOS 與 Ubuntu 的區別CentOSUbuntu
- artice與section的區別
- GET 與 POST 的區別
- WebSocket 與 Socket 的區別Web
- Postgresql與MySQL的區別MySql