- buffer是一個內存地址空間,linux系統默認大小一般為4096(4kb)。主要用于存儲速度不同步的設備或優先級不同的設備之間傳遞數據的區域。
- 通過buffer可以使進程之間的相互等待變少。
例如,當你打開一個文本編輯器,輸入一個字符時,系統并不會立即寫入磁盤。而是存儲在buffer中,當寫滿一個buffer時,才會把buffer的內容寫入磁盤。
當然也可以使用flush強制將buffer的數據寫入磁盤。
在php中,例如 echo,print,輸出并不會立即通過tcp傳遞給瀏覽器輸出。而是將數據寫入php buffer。當一個php buffer寫滿,才會通過tcp傳遞給瀏覽器。
> echo /print -> php output_buffer -> tcp buffer -> browser
> php output_buffering
- 默認情況下,php buffer是開啟的,默認值是4096(4kb)。可以在php.ini中找到output_buffering 配置。直到buffer寫滿,才會發送到瀏覽器。
- 也可以設置ob_start(),這樣即使超過默認值(4kb)也不會立即發送到瀏覽器,只到腳本運行完成,或者調用了ob_end_flush方法,才會輸出到瀏覽器。
1. output_buffering=4096,輸出較少的數據(少于一個buffer)
~~~
<?php
for($i=0; $i<10; $i++){
echo $i.'<br>';
sleep(2);
}
?>
~~~
運行結果:等所有腳本全部運行完成后,才輸出,因為數據未滿一個buffer的大小。
2. output_buffering=4096,輸出較少的數據(少于一個buffer),關閉output_buffering,修改php.ini的output_buffering=0
~~~
<?php
for($i=0; $i<10; $i++){
echo $i.str_repeat(" ",500).'<br>'; // 當接受到的256(甚至更多)個字節以后才開始顯示該頁面,所以必須發送一些額外的空格來讓這些瀏覽器顯示頁面內容。
flush();
sleep(1);
}
?>
~~~
運行結果:因為禁用了php buffering,不需要等到腳本運行完畢就可以輸出,數據沒有在php buffer停留,可以看到斷斷續續間歇性輸出。echo -> tcp buffer ->browser
3. 當output\_buffering=4096,輸出較大數據(大于一個buffer),不使用ob\_start()
~~~
<?php
for($i=0; $i<10; $i++){
echo file_get_contents('f.txt').$i.'<br>';
sleep(1);
}
?>
~~~
運行結果:f.txt為一個大于4kb的文件,因為大于buffer默認值,buffer空間不夠用,每當滿一個buffer就會輸出,所以可以看到間歇性輸出。
4. 當output\_buffering=4096,輸出較大數據(大于一個buffer),使用ob\_start()
~~~
<?php
ob_start();
for($i=0; $i<10; $i++){
echo file_get_contents('f.txt').$i.'<br>';
sleep(1);
}
?>
~~~
運行結果:因為使用了ob\_start(),會為buffer設置足夠大的空間,因此會保存到腳本執行完畢后才會輸出。
## :-: **output\_buffering 方法**
1.ob\_start
激活output\_buffering機制,一旦激活,腳本不再直接輸出到瀏覽器,而是暫時寫入php buffering區域。直到腳本運行完畢后,才發送。
2.ob\_get\_contents
獲取php buffering中的數據,注意:要在ob\_end\_clean()前調用,否則只會得到空字符。
3.ob\_end\_flush 和 ob\_end\_clean
ob\_end\_flush 會輸出php buffering 中的數據,但不會清空。
ob\_end\_clean 不會輸出,只會清空php buffering中的數據。
>[warning]注意:
ob\_flush / flush在手冊中的描述, 都是刷新輸出緩沖區, 并且還需要配套使用, 所以會導致很多人迷惑…
其實, 他們倆的操作對象不同, 有些情況下, flush根本不做什么事情..
ob\_\*系列函數, 是操作PHP本身的輸出緩沖區.
所以, ob\_flush是刷新PHP自身的緩沖區.
而flush, 嚴格來講, 這個只有在PHP做為apache的Module(handler或者filter)安裝的時候, 才有實際作用. 它是刷新WebServer(可以認為特指apache)的緩沖區.
在apache module的sapi下, flush會通過調用sapi\_module的flush成員函數指針, 間接的調用apache的api: ap\_rflush刷新apache的輸出緩沖區, 當然手冊中也說了, 有一些apache的其他模塊, 可能會改變這個動作的結果..
有些Apache的模塊,比如mod\_gzip,可能自己進行輸出緩存,這將導致flush()函數產生的結果不會立即被發送到客戶端瀏覽器。
甚至瀏覽器也會在顯示之前,緩存接收到的內容。例如 Netscape瀏覽器會在接受到換行或 html 標記的開頭之前緩存內容,并且在接受到 標記之前,不會顯示出整個表格。
一些版本的 Microsoft Internet Explorer 只有當接受到的256個字節以后才開始顯示該頁面,所以必須發送一些額外的空格來讓這些瀏覽器顯示頁面內容。
所以, 正確使用倆者的順序是。 先ob\_flush, 然后flush。
當然, 在其他sapi下,,不調用flush也可以, 只不過為了保證你代碼的可移植性, 建議配套使用。
## :-: **我們要說一下php中的緩存大概有哪些!**
在PHP中,我們可以粗略的將緩存分為客戶端緩存(Browser緩存),服務器端緩存(Server緩存)。由于PHP是基于B/S架構的,所以,我們可以理解為瀏覽器端的緩存,服務器端緩存。
在服務器端PHP自帶的緩存中,主要可以分為兩大類緩存!程序緩存和OB緩存!這也是我們學習服務器端緩存的主要內容!
在PHP中緩存的輸出順序為:
打開了php輸出緩存: echo,print -> php output_buffering -> server buffering -> browser buffering -> browser display
未打開php輸出緩存: echo,print -> server buffering -> browser buffering -> browser display
瀏覽器的輸出緩存:IE為256Bytes, Chrome與FireFox為1000Bytes,只有輸出數據達到了這個長度或者腳本結束瀏覽器才會將數據輸出在頁面上。
## :-: **OB緩存的幾個重要規則**
- 在服務中,如果我們開啟了ob緩存,則echo數據首先放入到OB中
- 如何開啟OB , 有兩個方法
- 在php.ini 配置 ;output_buffering = 4096 這里去掉;號即可
- 在php頁面中使用 ob_start();
>[info]通過php.ini 打開的,則作用于所有的php頁面 。 使用ob_start()打開則只作用于該頁面
- 當PHP頁面執行到最后,則會把ob緩存的數據(如果有的話), 強制刷新到程序緩存,然后通過apache對數據封裝成http響應包,返 回給瀏覽器
- 如果沒有ob,所有的數據直接放入程序緩存
- header信息不管你是否開啟ob,總是放入到程序緩存
## :-: **常用方法**
1.ob_start
激活output_buffering機制,一旦激活,腳本不再直接輸出到瀏覽器,而是暫時寫入php buffering區域。直到腳本運行完畢后,才發送。
2.ob_get_contents
獲取php buffering中的數據,注意:要在ob_end_clean()前調用,否則只會得到空字符。
3.ob_end_flush 和 ob_end_clean
ob_end_flush 會輸出php buffering 中的數據,但不會清空。
ob_end_clean 不會輸出,只會清空php buffering中的數據。
4.ob_flush 、flush、ob_implicit_flush
ob_flush 會刷新php buffering 中的數據到程序緩存
flush 則會刷新程序緩存到瀏覽器緩存中
ob_implicit_flush 將打開或關閉絕對(隱式)刷送。絕對(隱式)刷送將導致在每次輸出調用后有一次刷送操作,以便不再需要對 flush() 的顯式調用
## :-: **OB緩存的作用!**
OB緩存在各個方面都有應用,但是,本人知道的主要是在兩個方面!
a、當網站準備做網站靜態化的時候,選擇OB緩存是一個不錯的選擇!
b、解決Warning: Cannot modify header information - headers already sent by的錯誤!
究其發生錯誤的原因:是因為響應頭和相應主體位置錯位導致的!正常情況下,服務器返回給瀏覽器的相應內容,應該是:響應頭+響應主體!
但是,如果我們開啟了OB緩存,那么相應頭信息(一般也就是header()函數進行設置的信息),會被放入到程序緩存中!
而其他的輸出內容,如:echo print_r var_dump 等,都會先被放入OB緩存中!
等程序結束的時候,或者OB緩存關閉的實話,將OB緩存的內容在放入程序緩存中!從而保證響應頭信息,始終在響應主體內容之前!
- 雜談
- 開發 & 維護的工作流程
- 新手如何看php手冊 和 框架手冊
- 開發 & 維護的不同點
- 從0到1,搭建新項目的工作流程
- 從1到N,維護的工作流程
- 優化流程
- 生成錯誤日志和慢日志的方法
- 查錯思路
- 怎么快速接手一個項目
- 前端常用知識點
- javascript
- 自己封裝的函數
- 處理數字
- 功能代碼
- 動態添加圖片
- 判斷是手機端還是pc端
- javascript:;是什么意思?怎么用呢
- html & h5
- a標簽中target設置為blank和_blank有什么區別?
- 亂碼
- 提交方式:button標簽 和 input
- 塊元素
- 內聯元素
- h5特有屬性
- h5的localStorage【增、刪、改、查】
- jquery
- 常用方法
- 功能代碼
- 動態刪除圖片
- 一個按鈕,切換2種狀態
- 換膚
- 深入理解(function(){... })();
- json & xml
- json
- 語法速記
- json對象取值
- 字符串、對象、數組的區別
- xml
- [CDATA[%s]]的作用是什么
- 轉義字符
- CDATA 想被xml解析的文本數據
- CDATA 不想被xml解析的文本數據
- 微信小程序
- 其他
- websocket
- 跨域
- css
- 行內 & 內連 & 外連 寫法
- 優先級
- 更加精準的匹配
- 使用百分比如何生效
- php在html、js、jq中的的原生寫法
- *php在html中的語法
- php在js中的語法
- php在jq中的語法
- 正則表達式
- php常用基礎知識(思想為主)
- php為什么是“邊編譯邊運行”
- 冒號、endif、endwhile、endfor使用
- 遞歸思想(速記法)
- cookie和session的理解
- php常用內置(系統)函數
- 常量
- 字符串
- 數組
- 日期時間
- 文件 & 目錄
- 數學
- 程序執行
- 判斷
- 選項和信息(修改配置文件的)
- 錯誤處理 & 日志記錄
- 編碼格式
- session
- IP相關
- 類 & 對象
- 性能
- 其他函數
- 魔術方法
- $_SERVER
- 變量處理
- php自己封裝的一些函數
- 導入、導出、生成文件
- 數組
- 數字
- 字符串
- 其他
- 獲取linux硬件信息
- 常見插件/類庫使用
- 前端-框架/插件
- bootstrap 學習筆記
- layer 學習筆記
- layDate 學習筆記
- 百度ueditor1.4.4.3富文本編輯器
- quill富文本編輯器
- 百度ECharts圖形報表
- webuploader上傳圖片
- 后端類庫
- workerman 聊天室
- QRCODE 二維碼
- redis
- seaslog 日志
- phpspider 爬蟲
- Mailer 發送郵件
- simple_html_dom
- phpstorm使用
- 快捷鍵
- 連接mysql數據庫
- 斷點 + debug調試
- 運行內存不夠
- wamp環境
- yii、laravel、tp、開發自己的php框架
- 看框架源碼的思路
- tp5框架的使用
- 1、助手函數原理解析
- 開發自己的php框架
- 常用的開發思路 和 小功能實現代碼
- 爬蟲思路
- 功能點思路
- tp5判斷是不是異地登錄(簡單版)
- 微信開發,反向代理
- 微信開發,關閉當前頁面
- 消息隊列的實現
- 頁面靜態化
- session串號
- 站內信設計思路
- web在線管理器
- 語言相關(開發有關)
- 接收json(text/xml)格式數據
- 原生文件上傳(狀態碼)
- openssl擴展
- 打印對象 和 遍歷對象
- 使用OB緩存的幾個原則
- CLI模式執行php文件
- foreach時,添加元素 或 修改元素的值
- 功能點 代碼實現
- 生成url目錄樹(沒有pid)
- 多圖上傳(vue傳base64)
- 下載文件,耗時算法
- 生成商品二維碼
- 導出excel
- 搜索
- 阿里大魚發短信
- 使用阿里云oss
- location.href跳轉后,丟失用戶的session
- “\r ” “\r\n” “\t”的區別
- php的配置文件詳解
- 開啟錯誤日志
- 開啟慢日志
- 開啟短標簽
- 分析php-fpm.conf中的request_terminate_timeout參數