zoukankan      html  css  js  c++  java
  • PHP缓存机制Output Control详解

    开启OB缓存的方式有如下两种:

    1. php.ini中开启 output_buffering = 4096

    启用了此指令,那么每个PHP脚本都相当于一开始就调用了ob_start()函数,PHP5.5默认已开启output_buffering = 4096

    Xee:我的php是5.4.33默认开启了output_buffering = 4096,在浏览器中是显示很正常,但是在php cli下,就会显示,”failed to flush buffer. No buffer to flush“的提示!

    打开php.ini,搜索output_buffering,我们会看到类似这样的设置 output_buffering = 4096。正如它的名字output_buffering一样,这个设置的作用就是把输出缓冲一下,缓冲大小为4096bytes.
    在我们的第一段代码里,之所以没有按预期的输出,正是因为这个output_buffering把那些输出都缓冲了。没达到4096bytes或者脚本结束,输出是不会被发送出去的。

    ob_* 系列函数是操作PHP本身的输出缓冲区,所以,ob_flush只刷新PHP自身的缓冲区。而flush是刷新apache的缓冲区。所以,正确使用俩者的顺序是:先ob_flush,然后flush。ob_flush是把数据从PHP的缓冲中释放出来,flush是把缓冲内/外的数据全部发送到浏览器。

    不要误认为用了ob_start()后,脚本的echo/print等输出就永远不会显示在浏览器上了。因为PHP脚本运行结束后,会自动刷新缓冲区并输出内容。

    你也可以通过 ob_start()手动激活php output_buffering机制,使得即便输出超过了1kb数据,也不真的把数据交给tcp传给浏览器,因为ob_start()将php buffer空间设置到了足够大 。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。

    服务端的缓存是堆叠起来的,也就是说你在开启了ob_start()后,关闭之前,在其内部还可以开启另外一个缓存ob_start()。

    当你把output_buffering设为0的时候,连ob_flush()和ob_end_clean()都不需要了

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

    2. 直接在程序中使用 ob_start();

    打开输出缓冲。当输出缓冲激活后,脚本将不会输出内容(除http标头外),相反需要输出的内容被存储在内部缓冲区中。

    内部缓冲区的内容可以用 ob_get_contents() 函数复制到一个字符串变量中。 想要输出存储在内部缓冲区中的内容,可以使用 ob_end_flush() 函数。另外, 使用 ob_end_clean() 函数会静默丢弃掉缓冲区的内容。

    /**
     * output_buffering = off 情况下测试
     */
    ob_start();  //开启ob缓存
    echo 'hello1'; //存入ob缓存
    header('content-type:text/html;charset=utf-8');//存入程序缓存
    //ob_end_clean(); //清空ob缓存,并关闭ob缓存
    echo 'hello2'; //存入ob缓存
    $str = ob_get_contents(); //返回ob缓存的数据(不清除缓冲内容)
    file_put_contents('ob.txt', $str); //把$str保存到文件
    //ob_clean(); //清空ob缓存
    echo 'hello3'; //存入ob缓存
    echo 'hello4'; //存入ob缓存
    /* 此脚本将生成ob.txt文件,存入hello1hello2,浏览器输出hello1hello2hello3hello4 */
    /* 若ob_clean()注释打开,那么生成的ob.txt文件中将没有内容,浏览器输出hello3hello4 */
    /* 若ob_end_clean()注释打开,那么ob.txt中依然没有内容,因为关闭了ob缓存,浏览器输出hello2hello3hello4 */

    ob_flush() 与 ob_end_flush() 例子:

    ob_start();
    echo 'abc';//存入ob缓存
    header('content-type:text/html;charset=utf-8'); //存入程序缓存
    echo 'hello'; //存入ob缓存
    ob_flush();//将ob缓存中的内容输出到程序缓存,清空ob缓存,不关闭ob缓存
    //ob_end_flush() //将ob缓存中的内容输出到程序缓存,清空ob缓存,关闭ob缓存
    echo 'aa'; //存入ob缓存
    echo ob_get_contents();
    /* 最后输出abchelloaaaa */
    /* 注释ob_flush,打开ob_end_flush,最后输出abchelloaa */

    注意:
    在output_buffering = 4096开启的情况下,ob_end_clean()只关闭一次ob缓存(即ob_start开启的),系统的并未关闭。
    ob_end_flush()同理。

    OB缓存的运行原理/原则:

    1. ob缓存打开,echo的数据首先放入ob缓存
    2. 如果是header信息,直接放在apache程序缓存
    3. 当页面执行到最后,会把ob缓存的数据放到apache程序缓存,然后一次返回给浏览器

    最后还有一个flush(); 强制刷新PHP程序缓存到浏览器缓存。

    特性:一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。

    Xee:PHP CLI(命令行模式)下,使用flush(),sleep()是每秒显示一下数据的;浏览器下,即使是使用了flush(),浏览器是过了总共的时间,所有输出才全部显示的!

    Xee:参考http://my.oschina.net/whrlmc/blog/85782[有必要讲一下,这篇文章的例子,我的配置默认开启缓冲区设置,由于ob_start()的再次开启,导致了缓冲输出区的堆叠,注意!去掉这个ob_start()即可,显示效果!] & PHP 输出缓存

    echo str_pad('',4096); 
    for ($i = 0; $i < 10; $i++) { 
        echo $i; 
        ob_flush(); 
        flush(); 
        sleep(1); 
    }

    就像上面的代码,在服务器端运行,客户端浏览器是每秒显示一下数据的!gif右上角一直显示loading,等了大约10.2s才算真正的加载完成…

    <参考:http://www.jb51.net/article/52119.htm>

    没有人告诉你,生活会是这样:你工作无趣,你袋里没钱,你的爱情总是昙花一现;妈妈警告过你,会有这样的日子但她没有告诉你,世界将让你屈服。但是,别怕,有我在你身边,谁让我们是friends呢……
  • 相关阅读:
    MySQL和B树的那些事
    记一次临时抱佛脚的性能压测经历
    zookeeper api
    zookeeper笔记
    Mysql优化系列(1)--Innodb重要参数优化
    搞懂MySQL InnoDB B+树索引
    我以为我对Mysql索引很了解,直到我遇到了阿里的面试官
    HDFS原理概念扫盲
    设计原则
    设计模式 6大则
  • 原文地址:https://www.cnblogs.com/ChandlerVer5/p/4231068.html
Copyright © 2011-2022 走看看