[PHP]php缓冲 output_buffering的使用详解
buffer
buffer是一个内存地址空间,Linux系统默认大小一般为4096(4kb),即一个内存页。主要用于存储速度不同步的设备或者优先级不同的设备之间传办理数据的区域。通过buffer,可以使进程这间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁盘,当然当调用内核函数flush()的时候,强制要求把buffer中的脏数据写回磁盘。
同样的道理,当执行echo,print的时候,输出并没有立即通过tcp传给客户端浏览器显示,
而是将数据写入php buffer。php output_buffering机制,意味在tcp
buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php
buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方:echo/print
-> php buffer -> tcp buffer -> browser
php output_buffering
默认情况下,php
buffer是开启的,而且该buffer默认值是4096,即4kb。你可以通过在php.ini配置文件中找到output_buffering配置.当echo,print等输出用户数据的时候,输出数据都会写入到php
output_buffering中,直到output_buffering写满,会将这些数据通过tcp传送给浏览器显示。你也可以通过ob_start()手动激活php
output_buffering机制,使得即便输出超过了4kb数据,也不真的把数据交给tcp传给浏览器,因为ob_start()将php
buffer空间设置到了足够大。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。
1.当output_buffering=4096,并且输出较少数据(少于一个buffer)
for ($i = 0; $i < 10; $i++) {
echo $i . '<br/>';
sleep($i + 1); //
}
?>
现象:不是每隔几秒就会有间断性输出,而是直到响应结束,才能看一次性看到输出,在等待服务器脚本处理结束之前,浏览器界面一直保持空白。这是因为,数据量太小,php
output_buffering没有写满。写数据的顺序,依次是echo->php buffer->tcp
buffer->browser
2.当output_buffering=0,并且输出较少数据(少于一个buffer)
//通过ini_set('output_buffering', 0)并不生效
//应该编辑/etc/php.ini,设置output_buffering=0禁用output buffering机制
//ini_set('output_buffering', 0); //彻底禁用output buffering功能
for ($i = 0; $i < 10; $i++) {
echo $i . '<br/>';
flush(); //通知操作系统底层,尽快把数据给客户端浏览器
sleep($i + 1); //
}
?>
现象:与刚才显示并不一致,禁用了php
buffering机制之后,在浏览器可以断断续续看到间断性输出,不必等到脚本执行完毕才看到输出。这是因为,数据没有在php
output_buffering中停留。写数据的顺序依次是echo->tcp buffer->browser
3.当output_buffering=4096.,输出数据大于一个buffer,不调用ob_start()
$dd if=/dev/zero of=f4096 bs=4096 count=1
<?php
for ($i = 0; $i < 10; $i++) {
echo file_get_contents('./f4096') . $i . '<br/>';
sleep($i +1);
}
?>
现象:响应还没结束(http连接没有关闭),断断续续可以看到间断性输出,浏览器界面不会一直保持空白。尽管启用了php
output_buffering机制,但依然会间断性输出,而不是一次性输出,是因为output_buffering空间不够用。每写满一个php
buffering,数据就会发送到客户端浏览器。
4.当output_buffering=4096, 输出数据大于一个tcp buffer, 调用ob_start()
ob_start(); //开启php buffer
for ($i = 0; $i < 10; $i++) {
echo file_get_contents('./f4096') . $i . '<br/>';
sleep($i + 1);
}
ob_end_flush();
?>
现象:直到服务端脚本处理完成,响应结束,才看到完整输,输出间隔时间很短,以至你感受不到停顿。在输出之前,浏览器一直保持着空白界面,等待服务端数据。这是因为,php一旦调用了ob_start()函数,它会将php
buffer扩展到足够大,直到ob_end_flush函数调用或者脚本运行结速才发送php buffer中的数据到客户端浏览器。
output buffering函数
1.ob_get_level
返回输出缓冲机制的嵌套级别,可以防止模板重复嵌套自己。
1.ob_start
激活output_buffering机制。一旦激活,脚本输出不再直接出给浏览器,而是先暂时写入php buffer内存区域。
php默认开启output_buffering机制,只不过,通过调用ob_start()函数据output_buffering值扩展到足够大。也可以指定$chunk_size来指定output_buffering的值。$chunk_size默认值是0,表示直到脚本运行结束,php
buffer中的数据才会发送到浏览器。如果你设置了$chunk_size的大小,则表示只要buffer中数据长度达到了该值,就会将buffer中的数据发送给浏览器。
当然,你可以通过指定$ouput_callback,来处理buffer中的数据。比如函数ob_gzhandler,将buffer中的数据压缩后再传送给浏览器。
2.ob_get_contents
获取一份php buffer中的数据拷贝。值得注意的是,你应该在ob_end_clean()函数调用之前调用该函数,否则ob_get_contents()返回一个空字符中。
3.ob_end_flush与ob_end_clean
这二个函数有点相似,都会关闭ouptu_buffering机制。但不同的是,ob_end_flush只是把php
buffer中的数据冲(flush/send)到客户端浏览器,而ob_clean_clean将php
bufeer中的数据清空(erase),但不发送给客户端浏览器。ob_end_flush调用之后,php
buffer中的数据依然存在,ob_get_contents()依然可以获取php
buffer中的数据拷贝。而ob_end_clean()调用之后ob_get_contents()取到的是空字符串,同时浏览器也接收不到输出,即没有任何输出。
惯用案例
常常在一些模板引擎和页面文件缓存中看到ob_start()使用。下面湿CI中加载模板的程序代码:
<SPAN style="WHITE-SPACE: pre"> </SPAN>/*
* Buffer the output
*
* We buffer the output for two reasons:
* 1. Speed. You get a significant speed boost.
* 2. So that the final rendered template can be
* post-processed by the output class. Why do we
* need post processing? For one thing, in order to
* show the elapsed page load time. Unless we
* can intercept the content right before it's sent to
* the browser and then stop the timer it won't be accurate.
*/
ob_start();
// If the PHP installation does not support short tags we'll
// do a little string replacement, changing the short tags
// to standard PHP echo statements.
if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
{
//替换短标记<?=***>
echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>",
str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
}
else
{
include($_ci_path); // include() vs include_once() allows for multiple views with the same name
}
//记录调试信息
log_message('debug', 'File loaded: '.$_ci_path);
// Return the file data if requested
if ($_ci_return === TRUE)
{
$buffer = ob_get_contents();
@ob_end_clean();
return $buffer;
}
/*
* Flush the buffer... or buff the flusher?
*
* In order to permit views to be nested within
* other views, we need to flush the content back out whenever
* we are beyond the first level of output buffering so that
* it can be seen and included properly by the first included
* template and any subsequent ones. Oy!
*
*/
if (ob_get_level() > $this->_ci_ob_level + 1)
{
ob_end_flush();
}
else
{
//将模板内容添加到输出流中
$_ci_CI->output->append_output(ob_get_contents());
//清除buffer
@ob_end_clean();
}
[PHP]php缓冲 output_buffering的使用详解的更多相关文章
- C# 控件双缓冲控制 ControlStyles 枚举详解
ControlStyles 枚举 .NET Framework 4 指定控件的样式和行为. 此枚举有一个 FlagsAttribute 特性,通过该特性可使其成员值按位组合. 命名空间: Sy ...
- PHP输出缓冲控制- Output Control 函数应用详解
说到输出缓冲,首先要说的是一个叫做缓冲器(buffer)的东西.举个简单的例子说明他的作用:我们在编辑一篇文档时,在我们没有保存之前,系统是不会向磁盘写入的,而是写到buffer中,当buffer写满 ...
- PHP中刷新输出缓冲详解[转载]
PHP中刷新输出缓冲详解 分类: PHP Web开发2011-07-23 17:42 1795人阅读 评论(0) 收藏 举报 phpbuffer浏览器outputapache模块脚本 buffer是一 ...
- PHP输出缓冲控制 - Output Control 函 应用详解
简介 说到输出缓冲,首先要说的是一个叫做缓冲器(buffer)的东西.举个简单的例子说明他的作用:我们在编辑一篇文档时,在我们没有保存之前,系统是不会向磁盘写入的,而是写到buffer中,当buffe ...
- Oracle内存详解之 Library cache 库缓冲
Oracle内存详解之 Library cache 库缓冲 2017年11月09日 11:38:39 阅读数:410更多 个人分类: 体系结构 Library cache是Shared pool的一部 ...
- PHP_php.ini_说明详解
这个文件必须命名为''php.ini''并放置在httpd.conf中的PHPIniDir指令指定的目录中.最新版本的php.ini可以在下面两个位置查看:http://cvs.php.net/vie ...
- php.ini – 配置文件详解
详见: https://my.oschina.net/miaowang/blog/299546 这个文件必须命名为''php.ini''并放置在httpd.conf中的PHPIniDir指令指定的目录 ...
- PHP输出缓存ob系列函数详解
PHP输出缓存ob系列函数详解 ob,输出缓冲区,是output buffering的简称,而不是output cache.ob用对了,是能对速度有一定的帮助,但是盲目的加上ob函数,只会增加CPU额 ...
- php.ini 配置详解
这个文件必须命名为''php.ini''并放置在httpd.conf中的PHPIniDir指令指定的目录中.最新版本的php.ini可以在下面两个位置查看:http://cvs.php.net/vie ...
随机推荐
- Linux下的解压命令
Linux下常见的压缩包格式有5种:zip tar.gz tar.bz2 tar.xz tar.Z 其中tar是种打包格式,gz和bz2等后缀才是指代压缩方式:gzip和bzip2 filename. ...
- C# 绘图时使用抗锯齿会多出一个像素
如下图,使用局部绘图覆盖后的效果. 减去像素后效果
- 12个实用的 JavaScript 框架分享给前端开发者
JavaScript库是预先编写的 JavaScript 工具代码,让开发者可以更容易开发 JavaScript 应用.这个列表我们列出了2017年1月份功能丰富的 JavaScript 库,可以帮助 ...
- Listener 快速开始
[SessionListener] @WebListenerpublic class SessionListener implements HttpSessionListener,HttpSessio ...
- 唯一约束(UNIQUE_KEY)
唯一约束可以保证记录的唯一性 唯一约束的字段可以为空值(NULL) 每张数据表可以存在多个唯一约束(主键只有一个) mysql> CREATE TABLE tb7( -> id SMALL ...
- DNN网络(二)反向传播算法
本文摘自: https://www.cnblogs.com/pinard/p/6422831.html http://www.cnblogs.com/charlotte77/p/5629865.htm ...
- DateTime时间格式转换为Unix时间戳格式
/// <summary> /// 将DateTime时间格式转换为Unix时间戳格式 /// </summary> /// <param name="date ...
- [C++]动态规划系列之币值最大化
/** * * @author Zen Johnny * @date 2018年3月31日 下午10:04:48 * */ package freeTest.dynamicProgramming; i ...
- Coursera, Deep Learning 4, Convolutional Neural Networks - week1
CNN 主要解决 computer vision 问题,同时解决input X 维度太大的问题. Edge detection 下面演示了convolution 的概念 下图的 vertical ed ...
- TensorFlow从入门到理解(四):你的第一个循环神经网络RNN(分类例子)
运行代码: import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # set rando ...