• OPCache使用示例


    OPcache 有什么用?

    OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能, 存储预编译字节码的好处就是 省去了每次加载和解析 PHP 脚本的开销。

    OPcache如何开启?

    参考手册:http://php.net/manual/zh/opcache.installation.php

    OPcache相关设置?(本文主要针对windows上的配置)

           

    关于配置的说明和更多的配置项参考:http://php.net/manual/zh/opcache.configuration.php

    OPcache使用(OPcache函数

        1、 opcache_get_configuration ()   获取缓存的配置信息

              opcache_get_status ()            获取缓存的状态信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    <?php
        echo '<pre>';
        //  获取缓存的配置信息
        var_dump(opcache_get_configuration());
        echo '<hr/>';
        //  获取缓存的状态信息
        var_dump(opcache_get_status());
        echo '</pre>';
     
        /**
         * opcache_get_configuration和opcache_get_status返回的都是一组有关缓存配置信息
         * 类似于上面的输出
    array(3) {
      ["directives"]=>
      array(24) {
        ["opcache.enable"]=>
        bool(true)
        ["opcache.enable_cli"]=>
        bool(true)
        ["opcache.use_cwd"]=>
        bool(true)
        ["opcache.validate_timestamps"]=>
        bool(true)
        ["opcache.inherited_hack"]=>
        bool(true)
        ["opcache.dups_fix"]=>
        bool(false)
        ["opcache.revalidate_path"]=>
        bool(false)
        ["opcache.log_verbosity_level"]=>
        int(1)
        ["opcache.memory_consumption"]=>
        int(134217728)
        ["opcache.max_accelerated_files"]=>
        int(4000)
        ["opcache.max_wasted_percentage"]=>
        float(0.05)
        ["opcache.consistency_checks"]=>
        int(0)
        ["opcache.force_restart_timeout"]=>
        int(180)
        ["opcache.revalidate_freq"]=>
        int(60)
        ["opcache.preferred_memory_model"]=>
        string(0) ""
        ["opcache.blacklist_filename"]=>
        string(0) ""
        ["opcache.max_file_size"]=>
        int(0)
        ["opcache.error_log"]=>
        string(0) ""
        ["opcache.protect_memory"]=>
        bool(false)
        ["opcache.save_comments"]=>
        bool(true)
        ["opcache.load_comments"]=>
        bool(true)
        ["opcache.fast_shutdown"]=>
        bool(true)
        ["opcache.enable_file_override"]=>
        bool(false)
        ["opcache.optimization_level"]=>
        int(2147483647)
      }
      ["version"]=>
      array(2) {
        ["version"]=>
        string(5) "7.0.3"
        ["opcache_product_name"]=>
        string(12) "Zend OPcache"
      }
      ["blacklist"]=>
      array(0) {
      }
    }
    array(7) {
      ["opcache_enabled"]=>
      bool(true)
      ["cache_full"]=>
      bool(false)
      ["restart_pending"]=>
      bool(false)
      ["restart_in_progress"]=>
      bool(false)
      ["memory_usage"]=>
      array(4) {
        ["used_memory"]=>
        int(231368)
        ["free_memory"]=>
        int(133986360)
        ["wasted_memory"]=>
        int(0)
        ["current_wasted_percentage"]=>
        float(0)
      }
      ["opcache_statistics"]=>
      array(13) {
        ["num_cached_scripts"]=>
        int(2)
        ["num_cached_keys"]=>
        int(4)
        ["max_cached_keys"]=>
        int(7963)
        ["hits"]=>
        int(0)
        ["start_time"]=>
        int(1429153705)
        ["last_restart_time"]=>
        int(1429161635)
        ["oom_restarts"]=>
        int(0)
        ["hash_restarts"]=>
        int(0)
        ["manual_restarts"]=>
        int(81)
        ["misses"]=>
        int(2)
        ["blacklist_misses"]=>
        int(0)
        ["blacklist_miss_ratio"]=>
        float(0)
        ["opcache_hit_rate"]=>
        float(0)
      }
      ["scripts"]=>
      array(2) {
        ["D:WWWphp-codeopcacheoptest.php"]=>
        array(6) {
          ["full_path"]=>
          string(34) "D:WWWphp-codeopcacheoptest.php"
          ["hits"]=>
          int(0)
          ["memory_consumption"]=>
          int(4656)
          ["last_used"]=>
          string(24) "Thu Apr 16 13:20:35 2015"
          ["last_used_timestamp"]=>
          int(1429161635)
          ["timestamp"]=>
          int(1429161630)
        }
        ["D:WWWphp-codeopcacheopcache_config.php"]=>
        array(6) {
          ["full_path"]=>
          string(42) "D:WWWphp-codeopcacheopcache_config.php"
          ["hits"]=>
          int(0)
          ["memory_consumption"]=>
          int(2080)
          ["last_used"]=>
          string(24) "Thu Apr 16 14:28:32 2015"
          ["last_used_timestamp"]=>
          int(1429165712)
          ["timestamp"]=>
          int(1429150438)
        }
      }
    }
         */

    2、下面我们将进行一些练习示例,注意所有的这一切都需要你确定你已经开启了php的OPcache扩展

          去掉php.ini文件中的OPcache前面的分号

         完成后重启Apache服务。

         现在你将会发现:当我们像平时一样修改php代码以后刷新页面,页面并不会立即显示出我们的变化,好了来段代码说明:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?php
        $stime = microtime();
        try{
                // 这里我们简单的写了一个PDO连接数据库的测试程序
                $dsn = "mysql:host=localhost;dbname=test";
                $pdo = new PDO($dsn, 'root', 'root');
                $sql = "SELECT * FROM account";
                $stmt = $pdo->prepare($sql);
                $stmt->execute();
                // 假设第一次我们只输出了有多少行
                echo $stmt->rowCount();
                 
        }catch(PDOExecption $e){
            $e->getMessage();
        }

        这里显示有 6 条数据,

        如果我们此时想打印这 6 条数据,我们像平时那样,简单修改一下代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php
        $stime = microtime();
        try{
                // 这里我们简单的写了一个PDO连接数据库的测试程序
                $dsn = "mysql:host=localhost;dbname=test";
                $pdo = new PDO($dsn, 'root', 'root');
                $sql = "SELECT * FROM account";
                $stmt = $pdo->prepare($sql);
                $stmt->execute();
                // 假设第一次我们只输出了有多少行
                echo $stmt->rowCount();
                echo '<hr/>';
                // 我们想要打印查询出的所有数据
                print_r($stmt->fetchAll());
        }catch(PDOExecption $e){
            $e->getMessage();
        }

        我们现在刷新页面发现,

        

        咦? 怎么没有变化,难道是我们写错了吗? 如果你确定自己的代码没有问题,那么问题来了?这是为什么?是Apache疯了还是php疯了,还是我自己疯了?

        其实如果你对自己的代码有信心也有耐心,多刷新几次,就会发现,结果出来了

        

        好奇怪?有木有,其实不是这样了,由于我们上面修改php.ini文件已经开启OPcache,当我们第一次运行这个脚本的时候,php会检查->翻译->运行 我们写的这个脚本,和以前是一样的,但是我们开启了OPcache,这次php会将翻译好的php中间代码:字节码opcode加载到内存中,当再次修改我们的脚本运行时,其实运行的是内存中的php中间代码opcode,我们修改过的脚本并没有运行

        那为什么过一会,又显示正确了呢?

        还是我们上面 OPcache 的设置 

        看看解释:

    1
    2
    opcache.revalidate_freq integer
    检查脚本时间戳是否有更新的周期,以秒为单位。 设置为 0 会导致针对每个请求, OPcache 都会检查脚本更新。

        所以就是每60秒php会检查我们的脚本是否被修改过,如果修改过那就重新执行正常的那一套:检查->翻译->运行,然后把中间代码加载到内存中,

       所以在上面 我们的修改不会跟往常一样刷新页面就行,需要等待一会。这样是不是对缓存很有感受啊:我们修改了文件,却跟没有修改一样 ,页面没有显示任何变化 0.0 !

    3、opcache_reset()   重置字节码缓存的内容

          对于我们上面出现的这种情况,如果我们不想每次都等待60秒,我们就可以使用这个方法,这个方法的定义是:在调用 opcache_reset() 之后,所有的脚本将会重新载入并且在下次被点击的时候重新解析。  

         注意一旦调用这个方法,所有的脚本都会被重新解析,然后再次载入到内存,记住是所有脚本,如果我们只是针对某个脚本的话,我们可以考虑使用:opcache_invalidate — 废除脚本缓存 (下面再说这个)

         下面我们新建两个文件:opecho.php和opreset.php,简单的几行代码做个示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
        /*
         * filename: opecho.php
         * author  : wangxb
         * create  : 2015_04_17 02:44:16
         * update  : @update
         */
     

    echo "这是第一次修改,这个脚本会和以前一样去解释执行,然后将翻译好的中间代码opcode载入到内存中,<br>当我们在一分钟之内再次修改文件输出是没有变化的";

     

         然后假设我们此时,又想echo一些内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
        /*
         * filename: opecho.php
         * author  : wangxb
         * create  : 2015_04_17 02:44:16
         * update  : @update
         */
     
    echo "这是第一次修改,这个脚本会和以前一样去解释执行,然后将翻译好的中间代码opcode载入到内存中,<br>当我们在一分钟之内再次修改文件输出是没有变化的";
     
    // 假设此时我们想在输出一些内容
    echo "<hr/>";
    echo "这是第二次输出";

         我们发现,修改代码后没有变化

         

        然后我们执行 opreset.php

        opreset.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
        /*
         * filename: opreset.php
         * author  : wangxb
         * create  : 2015_04_17 02:44:25
         * update  : @update
         */

    // 当我们在调用这个文件中 opcache_reset() 方法之后,我们不用等待 60秒,此时 所有脚本会重新走一次php标准的流程,

    也就相当于我们修改后的脚本重新解释执行 然后将修改后的脚本的中间代码 字节码 opcode加载到内存中,我们就可以看到我们的修改效果了

        echo opcache_reset() ? '成功重置缓存内容' : '重置失败';

         

        刷新我们刚才的页面

         

        修改出现了,如果你觉得你在60内完不成这么多操作,无法出现按我说的这样的情景,可以把 opcache.revalidate_freq 这个参数设置大一些 比如 180 秒,这样的话 会每隔三分钟才去坚持一次文件是否更新过

    4、opcache_invalidate ()

         现在我们再新建一个opinvalidate.php 文件,再新建一个opecho1.php文件,利用我们上面的opecho.php文件,这次我们只想重新解释执行opecho1.php中的修改,

    1
    2
    3
    4
    5
    6
    7
    8
    <?php
        /*
         * filename: opecho1.php
         * author  : wangxb
         * create  : 2015_04_17 10:44:20
         * update  : @update
         */
        echo '我们将使用php中的opcache_invalidate()方法,让这个文件的字节码opcode手动失效';

         此时我们执行文件页面

         

        此时我们同时修改opecho.php和opecho1.php这两个文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?php
        /*
         * filename: opecho.php
         * author  : wangxb
         * create  : 2015_04_17 02:44:16
         * update  : @update
         */
     
    echo "这是第一次修改,这个脚本会和以前一样去解释执行,然后将翻译好的中间代码opcode载入到内存中,<br>当我们在一分钟之内再次修改文件输出是没有变化的";
     
    // 假设此时我们想在输出一些内容
    echo "<hr/>";
    echo "这是第二次输出";
     
    echo '<hr/>修改了opecho1.php文件';
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
        /*
         * filename: opecho1.php
         * author  : wangxb
         * create  : 2015_04_17 10:44:20
         * update  : @update
         */
        echo '我们将使用php中的opcache_invalidate()方法,让这个文件的字节码opcode手动失效';
     
        echo '<hr/>修改了opecho1.php文件';

           然后刷新页面,页面没有变化:

           

          

         当我们执行opinvalidate.php

    1
    2
    3
    4
    5
    <?php
        // opcache_invalidate() 方法中有两个参数:
        // args: 1、 缓存需要被作废对应的脚本路径
        //       2、 布尔型,true表示 强制作废, false或者缺省值,表示文件更新后才失效
        echo opcache_invalidate('./opecho1.php', TRUE) ? '操作成功' : '操作失败';

          

          我们就会看到:刷新 opecho1.php 页面

          

          我们的修改出现了,再来看看opecho.php页面

          

          没有变化,明白?  我们运行opinvalidate.php页面时,opecho1.php 脚本在缓存中的opcode被废弃了,php会重新执行一次opecho1.php这个脚本,所以我们看到了 我们的修改

    5、opcache_compile_file() 方法:无需运行,即可编译并缓存 PHP 脚本

         我们新建两个脚本:opcompile.php和compileScript.php,我们在opcompile.php中执行OPcache_compile_file方法缓存compileScript.php脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
        /*
         * filename: opcomplie.php
         * author  : wangxb
         * create  : 2015_04_17 11:53:30
         * update  : @update
         */
     
     
        // opcache_compile_file() 方法要求传入待缓存文件的路径,此时不需要运行这个带缓存文件,只需要执行这个方法即可在内存中缓存
        echo opcache_compile_file('./compileScript.php') ? '脚本成功缓存' : '脚本缓存失败';
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
        /*
         * filename: compileScript.php
         * author  : wangxb
         * create  : 2015_04_17 12:44:16
         * update  : @update
         */
     
        echo '这是脚本compileScript.php';

        现在执行 compile.php文件,让他去把compileScript.php脚本加入到缓存中

        

        然后我们修改:compileScript.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
        /*
         * filename: compileScript.php
         * author  : wangxb
         * create  : 2015_04_17 12:44:16
         * update  : @update
         */
     
        echo '这是脚本compileScript.php';
     
        echo '我们第一次修改compileScript.php文件';

         现在来在浏览器中看看这个脚本:

         

        没有变化,那是因为,这次运行的时候,执行的是我们上面执行compile.php文件时在内存中生成的第一次的compileScript.php的中间代码

        

    6、opcache_is_script_cached() 

         这个方法看名字估计都能猜出他是什么意思了:检查一个脚本是否在OPcache缓存中

        我们也来一个示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
        /*
         * filename: opisscriptcache.php
         * author  : wangxb
         * create  : 2015_04_17 13:14:16
         * update  : @update
         */
     
        //  我们就以前面已经在加载到内存中的opecho.php文件作为测试对象
        echo opcache_is_script_cached('./opecho.php') ? 'opecho.php脚本中间代码已经缓存' : 'opecho.php没有缓存中间代码opcode在内存中';

         很不幸,出了一个很严重的错误,

          

        没有这个方法,难道是我们错了吗?

        其实不是了,是因为这个方法要求:

          

       看看我们的PHPinfo

         

       所以用不了,其他的为什么都好着? 其他的方法要求进步都是v7.0.0、v7.0.2  我们这个满足,所以其他方法都可以使用,既然这样,这个方法也就这么说说算了,很简单的一个方法,平时也就是测试使用

       切记:最后如果你测试完了,还是应该关闭OPcache,这样才不至于被OPcache捣乱我们平时的开发工作

      结语

        好了,关于php缓存 OPcache的使用就介绍到这里,php还有一个扩张APC也是针对缓存的,我们下一篇再做说明,只用缓存来说,这个面就很大了,不光是这里说的php的缓存,数据库数据缓存、页面缓存等等。所以目前打算先把php中间OPcache层面的缓存弄清楚

       如果你不知道什么是opcode字节码、中间代码,给你推荐一篇博客:http://blog.linuxeye.com/361.html

       OK、就先这样吧,这段时间被换工作的事情搞得有点烦,上周面试了一家公司,不是专门做开发的公司,估计是那种做做页面一两个人维护的简单网站或者写一些简单的微信开发什么的,其实我不是开不起这样的公司,这家公司给我还不错的待遇,可是我是过不了心里那一道坎:幻想能找到一个技术氛围好的开发公司,自己能够见识到更多、更深、更广。自己也能在技术上有更大的提高,可是心里又告诉自己,难道一辈子要当个程序员吗?应该为以后想想,不一定要技术成长,工资待遇可以就行了。可是自己还是过不了心里那颗技术的梦,还是放不下在技术道路上狂奔的想法。哎、纠结,只能写写博客缓解一下这么纠结的心情了,让自己静静

       上面的代码在本人的GitHub上: https://github.com/wxb/php-code/tree/master/opcache



  • 相关阅读:
    BUAA2020软工作业(三)——个人项目
    BUAA2020软工作业(二)——对软件工程的初步理解
    BUAA2020软工作业(一)——谈谈我和计算机的缘分
    OO第四单元总结与课程总结
    OO第三单元总结——JML
    面向对象第二单元总结——魔鬼电梯
    面向对象设计与构造——第一单元总结
    提问回顾与个人总结
    【技术博客】Flutter—使用网络请求的页面搭建流程、State生命周期、一些组件的应用
    软件案例分析
  • 原文地址:https://www.cnblogs.com/wxb0328/p/opcache.html
Copyright © 2020-2023  润新知