PHP flush sleep 输出缓存控制详解

1 2 3 4 5 6
ob_start,flush,ob_flush for($i=0;$i<</SPAN>10;$i++) { echo $i.‘‘; flush(); sleep(1); }

有了解过PHP缓存输出控制函数的朋友肯定对上面这段代码很熟悉,它想实现的效果是每个1秒输出1个数字,完成全部输出需要10秒,不过实际执行中你会发现奇怪的现象,有些人或者有些时候它的表现如你所愿,而有些人或者有些时候却是10秒后才会一次性输出10个数字。我曾经为此抓狂不已,有朋友留言说这个情况往往是因为IE的缓存必须达到256个字符才会输出,可实际上我之前也考虑到IE的情况,可依旧会有时灵时不灵的情况。今天仔细读过手册才明白,这些不可预料的现象是有它的理由的。

原来php.ini中有两个关键参数会影响到php的缓存输出控制:

参数1:output_buffering :on/off 或者整数。设置为on时,将在所有脚本中使用输出缓存控制,不限制缓存的大小。而设置为整数时,如output_buffering=4096,当缓存数据达到4096字节时会自动输出刷新缓存。而这个参数的不同正是导致以上代码在不同时候执行结果不同的原因。当output_buffering关闭时,脚本所有的输出(echo)都会即时发送到客户端,执行上面代码时就是每秒输出一个数字。而开启output_buffering后,输出内容就会先缓存在服务端,直到脚本结束时才一起发送给客户端。

参数2:implicit_flush:on/off。设定ON意味着,当脚本有输出时,自动立即发送到客户端。相当于在echo后自动加flush()。

php缓存输出控制的相关函数:

ob_start()

第一个参数:回调函数,可选。在缓存输出前可以对其进行过滤或其他处理。最常见的用法是ob_start(‘ob_gzhandler’),即对缓存的数据进行gzip压缩后再发送给客户端。
第二个参数:缓存块的大小,可选。如果被缓存的内容达到或操作缓存块的大小,缓存会自动输出。默认值是0,指不限定大小,缓存到结束为止。还有个特殊值1,代表chunk_size=4096。
第三个参数:是否擦除缓存,可选,默认是true,如果设置为false,则在脚本执行结束前,缓存都不会被清除。

可以使用ob_get_contents()以字符串形式获取服务端缓存的数据,使用ob_end_flush()则会输出被缓存起来的数据,并关闭缓存。
而使用ob_end_clean()则会静默的清除服务端缓存的数据,而不会有任何数据或其他行为。
服务端的缓存是堆叠起来的,也就是说你在开启了ob_start()后,关闭之前,在其内部还可以开启另外一个缓存ob_start()。不过你也要务必保证关闭缓存的操作和开启缓存的操作数量一样多。

ob_start()可以指定一个回调函数来处理缓存数据,如果一个ob_start()内部嵌套了另一个
ob_start(),我们假定,外层的ob_start(),编号是A,内层的ob_start() 编号是B,它们各自制定了一个回调函数分别是functionA和functionB,那么在缓存B中的数据输出时,它会先辈funcitonB回调函数处理,再交给外层的functionA回调函数处理,之后才能输出到客户端。

另外,手册说,对于某些web服务器,比如apache,在使用回调函数有可能会改变程序当前的工作目录,解决方法是在回调函数中自行手动把工作目录修改回来,用chdir函数,这点似乎不常遇到,遇到的时候记得去查手册吧。

flush()和ob_flush()

这两个函数的使用怕是很多人最迷惑的一个问题,手册上对两个函数的解释也语焉不详,没有明确的指出它们的区别,似乎二者的功能都是刷新输出缓存。但在我们文章一开始的代码中如果讲fush()替换成ob_flush(),程序就再不能正确执行了。显然,它们是有区别的,否则也手册中直接说明其中一个是另外一个函数的别名即可了,没必要分别说明。那么它们的区别到底是什么呢?

反复研究了手册的说明,参考了手册中一些人的留言,自己琢磨应该是这样的:
在没有开启缓存时,脚本输出的内容都在服务器端处于等待输出的状态,flush()可以将等待输出的内容立即发送到客户端。
开启缓存后,脚本输出的内容存入了输出缓存中,这时没有处于等待输出状态的内容,你直接使用flush()不会向客户端发出任何内容。而ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端,这时你就需要先使用ob_flush()再使用flush(),客户端才能立即获得脚本的输出。

也就是说本文开头的脚本,可以根据缓存开启与否,有如下几种不同的写法:

注:以下代码都未考虑IE缓存必须大于256字节才输出的问题,如在IE下测试,请在代码开始加一句:“echo str_repeat(‘ ‘,256)”

写法1:

1 2 3 4 5 6 7 8
output_buffering = off implicit_flush=off for($i=0;$i<</SPAN>10;$i++) { echo $i.‘‘; flush(); sleep(1); }

写法2:

1 2 3 4 5 6 7 8 9
output_buffering = on implicit_flush=off for($i=0;$i<</SPAN>10;$i++) { echo $i.‘‘; ob_flush(); flush(); sleep(1); }

写法3:

1 2 3 4 5 6 7 8 9 10
output_buffering = off implicit_flush=off ob_start(); for($i=0;$i<</SPAN>10;$i++) {echo $i.‘‘; ob_flush(); flush(); sleep(1); }

写法4:

1 2 3 4 5 6 7 8 9
output_buffering = on implicit_flush=off ob_end_flush(); for($i=0;$i<</SPAN>10;$i++) {echo $i.‘‘; flush(); sleep(1); }

写法5:

1 2 3 4 5 6 7 8 9
output_buffering = on implicit_flush=off ob_end_clean(); for($i=0;$i<</SPAN>10;$i++) {echo $i.‘‘; flush(); sleep(1); }

写法6:

1 2 3 4 5 6 7 8 9
output_buffering = on; implicit_flush=on ob_end_clean(); // 或者ob_end_flush();for($i=0;$i<</SPAN>10;$i++) { echo $i.‘‘; sleep(1); }

写法7:

1 2 3 4 5 6 7 8 9 10
output_buffering = on; implicit_flush=on ob_end_clean(); // 或者ob_end_flush();for($i=0;$i<</SPAN>10;$i++) { echo $i.‘‘; flush(); sleep(1); }

写法8:

1 2 3 4 5 6 7
output_buffering = off implicit_flush=on for($i=0;$i<</SPAN>10;$i++) { echo $i.‘‘; sleep(1); }
时间: 2024-11-03 01:27:44

PHP flush sleep 输出缓存控制详解的相关文章

浏览器缓存机制详解

对于浏览器缓存,相信很多开发者对它真的是又爱又恨.一方面极大地提升了用户体验,而另一方面有时会因为读取了缓存而展示了"错误"的东西,而在开发过程中千方百计地想把缓存禁掉.那么浏览器缓存究竟是个什么样的神奇玩意呢? 什么是浏览器缓存: 简单来说,浏览器缓存就是把一个已经请求过的Web资源(如html页面,图片,js,数据等)拷贝一份副本储存在浏览器中.缓存会根据进来的请求保存输出内容的副本.当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是

Hibernate 所有缓存机制详解

Hibernate 所有缓存机制详解 hibernate提供的一级缓存 hibernate是一个线程对应一个session,一个线程可以看成一个用户.也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了. hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存.如果tb事务提交或回滚了,我们称session就关闭了,生命周期结束了. 缓存和连接池的区别:缓存和池都是放在内存里,实现是一样的

Redis for Windows(C#缓存)配置文件详解

Redis for Windows(C#缓存)配置文件详解 前言 在上一篇文章中主要介绍了Redis在Windows平台下的下载安装和简单使用http://www.cnblogs.com/aehyok/p/3478282.html.当然我也在上一篇中指定过配置文件,并且修改其中的端口port.本文将主要来探讨redis强大的配置文件. 我现在使用的redis版本为2.6.首先奉上配置文件的源文件. # Redis configuration file example # Note on unit

浏览器 HTTP 协议缓存机制详解

1.缓存的分类 2.浏览器缓存机制详解 2.1 HTML Meta标签控制缓存 2.2 HTTP头信息控制缓存 2.2.1 浏览器请求流程 2.2.2 几个重要概念解释 3.用户行为与缓存 4.Refer: https://www.cnblogs.com/520yang/articles/4807408.html 最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control.为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里

《深入理解mybatis原理6》 MyBatis的一级缓存实现详解 及使用注意事项

<深入理解mybatis原理> MyBatis的一级缓存实现详解 及使用注意事项 0.写在前面   MyBatis是一个简单,小巧但功能非常强大的ORM开源框架,它的功能强大也体现在它的缓存机制上.MyBatis提供了一级缓存.二级缓存 这两个缓存机制,能够很好地处理和维护缓存,以提高系统的性能.本文的目的则是向读者详细介绍MyBatis的一级缓存,深入源码,解析MyBatis一级缓存的实现原理,并且针对一级缓存的特点提出了在实际使用过程中应该注意的事项. 读完本文,你将会学到: 1.什么是一

Android 开源框架Universal-Image-Loader完全解析(二)--- 图片缓存策略详解

本篇文章继续为大家介绍Universal-Image-Loader这个开源的图片加载框架,介绍的是图片缓存策略方面的,如果大家对这个开源框架的使用还不了解,大家可以看看我之前写的一篇文章Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用,我们一般去加载大量的图片的时候,都会做缓存策略,缓存又分为内存缓存和硬盘缓存,我之前也写了几篇异步加载大量图片的文章,使用的内存缓存是LruCache这个类,LRU是Least Recently Used 近

php输出缓存控制

一.为什么学习php 输出缓存控制(Output Control)? 答:当然是php 输出缓存控制可以帮我们完成想完成的事情了.那就要从什么是输出缓存控制开始来了解了? 二.什么是php 输出缓存控制(Output Control) 答:由于输出php类似echo输出的时候,首先输出到php buffer里面的.所以我们可以控制这个缓存里面的数据了.当我们echo输出到浏览器的时候,要经历四个步骤:php buffer ----> web server buffer ---->browser

unity中camera摄像头控制详解

目录 1. 缘起 2. 开发 2.1. 建立项目 2.2. 旋转 2.2.1. 四元数 2.3. 移动 2.3.1. 向量操作 2.4. 镜头拉伸 2.5. 复位 2.6. 优化 1 缘起 我们的产品是使用unity开发水利BIM(水利建筑信息模型),项目中需要控制摄像 头对模型进行360度查看,请注意所有操作都是移动摄像头,不是移动模型.摄 像头能进行移动.旋转.改变焦距操作,类似于SketchUp的控制操作: 摄像头移动时,根据当前旋转方向(Rotation)进行移动 摄像头距离模型越远,摄

最详细的PHP flush()与ob_flush()的区别详解

buffer ---- flush()buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区域.通过buffer,可以使进程这间的相互等待变少.这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入 一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁 盘,当然当调用内核函数flus