### 1. 磁盤高速緩存(Disk Cache)
操作系統中使用磁盤高速緩存技術來提高磁盤的I/O速度,對高速緩存復制的訪問要比原始數據訪問更為高效。例如,正在運行的進程的指令既存儲在磁盤上,也存儲在物理內存上,也被復制到CPU的二級和一級高速緩存中。
不過,磁盤高速緩存技術不同于通常意義下的介于CPU與內存之間的小容量高速存儲器,而是 **指利用內存中的存儲空間來暫存從磁盤中讀出的一系列盤塊中的信息。因此,磁盤高速緩存在邏輯上屬于磁盤,物理上則是駐留在內存中的盤塊。**
高速緩存在內存中分為兩種形式:一種是在內存中開辟一個單獨的存儲空間作為磁速緩存,大小固定;另一種是把未利用的內存空間作為一個緩沖池,供請求分頁系統和磁盤I/O時共享。
### 2. 緩沖區(Buffer)
高速設備(如CPU)和低速設備(如磁盤)的通信都要經過緩存區,高速設備永遠不會直接去訪問低速設備。所以緩沖區是計算機中暫時存放輸出或輸入信息的內存區域。緩和高速部件和低速部件之間通信速度不匹配的矛盾。
### 3. PHP輸出緩沖區
輸出緩沖區顧名思義是輸出信息暫時存放的內存區域,通過ob\_*系列函數來控制輸出緩沖區。
當php腳本執行結束(會自動調用ob\_flush())或強制刷新(手動調用ob\_fush())緩沖區后,才會把數據發送給Nginx fastcgi客戶端。當然PHP還有其他的緩沖區,比如字符串緩沖區[finfo::buffer](http://cn2.php.net/manual/zh/function.finfo-buffer.php)。
PHP的輸出緩沖區默認是開啟,并且大小是4096字節。開啟后對所有php頁面都生效。
另外一種在頁面中單獨開啟緩沖區的辦法是ob_start()函數。
```
// ob_start()有三個參數,$chunk_size是用來設置緩沖區大小,可以設置0-4096,默認是0表示大小不限。
bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
```
**注意:一個ob_start()就是一個新的緩沖區,緩沖區是互相疊加的**

### 4. Nginx緩沖區
Nginx默認不會實時把php-fpm響應的數據返回給客戶端,而是暫存在Nginx緩沖區中。當php腳本執行結束(自動調用flush())或強制刷新(手動flush())緩沖區后,才會把數據發送給客戶端。
### 5. 瀏覽器緩沖區
瀏覽器默認不會實時顯示從Nginx返回的數據,而是把接受到的數據暫存在瀏覽器緩沖區中,當緩沖區滿后,才會開始顯示。不同的瀏覽器緩沖區大小不同。實際測試發現Mac 下chrome和safari都需要輸出1024字節。沒有找到刷新緩沖區的辦法,可以通過發送額外的空格來解決。
或者通過curl來請求,通過–no-buffer來禁用curl buffer。
```
curl 'niliu.me' --no_buffer
```
## 實例篇
### 實時輸出
```php
// ob_get_level() 返回多少個緩沖區(因為緩沖區是疊加的,也可以稱之為多級緩沖區)
var_dump(ob_get_level()); // out: 1, 一級緩沖區
if (ob_get_level() == 0) {
// 如果沒緩沖區,就開啟新的PHP緩沖區
// 默認會有一塊緩沖區,默認的緩沖區其實是很小的,所以不用什么str_pad撐滿
ob_start();
}
for ($i = 0;$i < 10;$i ++) {
echo "Line to show.";
// nginx fastcgi緩沖區大小是4K,需要發送額外4K空格;
// echo str_pad('',4096)."\n";
// php緩存刷入Apache/nginx
ob_flush();
// 從Apache/nginx刷到瀏覽器
flush();
//此時,瀏覽器應該顯示了, 如果瀏覽器不是即時顯示,就輸空格撐滿瀏覽器buffer
// echo str_repeat(" ",1024);
sleep(2);
}
echo "Done.";
ob_end_flush(); // 沖刷出(送出)輸出緩沖區內容并關閉緩沖
var_dump(ob_get_level()); // out: 0, 無緩沖區
```
### 模板渲染
```php
class Template{
/**
* 渲染方法
*
* @access public
* @param obj 信息類
* @param string 模板文件名
*/
public function render($context, $tpl){
$closure = function($tpl){
ob_start();
include $tpl;
return ob_end_flush();
};
// PHP7: $closure->call($context, $tpl);
$closure = $closure->bindTo($context, $context);
$closure($tpl);
}
}
```
### 靜態頁生成
```php
// 開啟緩沖區
ob_start();
// 業務邏輯省略
// .....
$this->assign('模板中的變量分配');
$tpl->display('default_1.tpl');
// 獲取緩沖區中解析變量后的模板
$html = ob_get_contents();
// 清空并關閉緩沖區
ob_end_clean();
// 把html寫入文件
// 業務邏輯省略 ...
```
[1]: http://static.zybuluo.com/a5635268/xid8hjcrd0fkz0dgwclzgdy8/20170125103047647.png
- 現代化PHP特性
- php7常用特性整理
- 反射機制Reflection
- 依賴注入與服務容器
- 抽象類與接口
- 類多繼承的替代方案Traits
- 類的延遲綁定(后期綁定)
- 生成器語法
- 匿名函數和閉包
- 匿名類
- 理解php的output buffer
- 斷言ASSERT
- 魔術方法小結
- Zend Opcache字節碼緩存
- 內置的http服務器
- SPL標準庫
- 【SPL標準庫專題(1)】SPL簡介
- 【SPL標準庫專題(2)】Iterator
- 【SPL標準庫專題(3)】Classes
- 【SPL標準庫專題(4)】Exceptions
- 【SPL標準庫專題(5)】Datastructures:SplDoublyLinkedList
- 【SPL標準庫專題(6)】Datastructures:SplStack & SplQueue
- 【SPL標準庫專題(7)】Datastructures:SplPriorityQueue
- 【SPL標準庫專題(8)】Datastructures:SplHeap & SplMaxHeap & SplMinHeap
- 【SPL標準庫專題(9)】Datastructures:SplFixedArray
- 【SPL標準庫專題(10)】Datastructures:SplObjectStorage
- PHPcomposer使用手札[ing]
- PHP中的多態
- 通過命名空間實現自動加載的框架雛形
- 日期與金額
- PHPstorm使用攻略
- 筆記本