W3CAPI 在线教程 | 菜鸟教程_LOGO
文档目录
文档目录
我的书签
 

PHP

PHP 高性能开发之 OPcache 缓存技术

我们在使用PHP开发的时候,当对基础的语言编写越来越熟悉后,不可避免的需要考虑到它的性能问题了,一个软件产品的开发不仅仅是对功能的实现,作为开发者更应该去关注它的执行效率和性能开销,今天我们来介绍影响PHP行为的扩展技术 OPcache。

jesen
1
2020-04-11 22:05:56

PHP 高性能开发 | OPcache 扩展介绍

OPcache扩展模块 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的加载性能开销,只要开启了OPcache模块后,PHP会自动存储预编译的字节码,不用自己手动去处理。
它带来的最大好处就是 省去了每次加载和解析 PHP 脚本的开销,因为PHP在加载文件和数据的时候,会首先在共享内存中查找该文件是否已经缓存,如果缓存,则直接读取。注意这里对性能的提升只是针对于文件和数据的加载性能,不是执行性能。
PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。 对于 PHP 5.2,5.3 和 5.4 版本可以使用  PECL 扩展中的 OPcache 

PHP 高性能开发 | OPcache 配置详解

   
opcache.revalidate_freq 这个选项用于设置缓存的过期时间(单位是秒),当这个时间达到后,opcache会检查你的代码是否改变,如果改变了PHP会重新编译它,生成新的opcode,并且更新缓存。值为“0”表示每次请求都会检查你的PHP代码是否更新(这意味着会增加很多次stat系统调用,注:stat系统调用是读取文件的状态,这里主要是获取最近修改时间,这个系统调用会发生磁盘I/O,所以必然会消耗一些CPU时间,当然系统调用本身也会消耗一些CPU时间)。可以在开发环境中把它设置为0,生产环境下不用管,因为下面会介绍另外一个设置选项。
opcache.validate_timestamps 当这个选项被启用(设置为1),PHP会在opcache.revalidate_freq设置的时间到达后检测文件的时间戳(timestamp)。

如果这个选项被禁用(设置为0),opcache.revalidate_freq会被忽略,PHP文件永远不会被检查。这意味着如果你修改了你的代码,然后你把它更新到服务器上,再在浏览器上请求更新的代码对应的功能,你会看不到更新的效果,你必须得重新加载你的PHP(使用kill -SIGUSR2强制重新加载)。

强烈建议在生产环境中使用次配置,因为在更新服务器代码的时候,如果代码较多,更新操作是有些延迟的,在这个延迟的过程中必然出现老代码和新代码混合的情况,这个时候对用户请求的处理必然存在不确定性。
opcache.max_accelerated_files 这个选项用于控制内存中最多可以缓存多少个PHP文件。这个选项必须得设置得足够大,大于你的项目中的所有PHP文件的总和。我的代码库大概有6000个PHP文件,所以我把这个值设置为一个素数7963。

真实的取值是在质数集合 { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 } 中找到的第一个比设置值大的质数。 设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000。
听起来好复杂,但用下面的命令就妥啦

你可以运行 find . -type f -print | grep php | wc -l 这个命令来快速计算你的代码库中的PHP文件数。
opcache.memory_consumption opcache的共享内存大小,这个选项的默认值为64MB,可以通过调用 opcache_get_status() 函数来获取opcache使用的内存的总量,根据内存总理,可以把这个选项设置得更大一些。
opcache.interned_strings_buffer 这是一个很有用的选项,但是似乎完全没有文档说明。PHP使用了一种叫做字符串驻留(string interning)的技术来改善性能。例如,如果你在代码中使用了1000次字符串“foobar”,在PHP内部只会在第一使用这个字符串的时候分配一个不可变的内存区域来存储这个字符串,其他的999次使用都会直接指向这个内存区域。这个选项则会把这个特性提升一个层次——默认情况下这个不可变的内存区域只会存在于单个php-fpm的进程中,如果设置了这个选项,那么它将会在所有的php-fpm进程中共享。在比较大的应用中,这可以非常有效地节约内存,提高应用的性能。

这个选项的值是以兆字节(megabytes)作为单位,如果把它设置为16,则表示16MB,默认是4MB,这是一个比较低的值。
opcache.fast_shutdown 这个配置参数字面上可以理解为“允许更快速关闭”。它的作用是在单个请求结束时提供一种更快速的机制来调用代码中的析构器,从而加快PHP的响应速度和PHP进程资源的回收速度,这样应用程序可以更快速地响应下一个请求。把它设置为1就可以使用这个机制了。
根据参数的详解,我们可以总结一套适用于各种开发状态的最佳配置模板,可以直接根据自己的需要将如下配置复制到php.ini中。

一、开发模式下推荐,直接禁用opcache扩展更好

opcache.revalidate_freq=0
opcache.validate_timestamps=1
opcache.max_accelerated_files=3000
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.fast_shutdown=1

二、多台机器集群模式或者代码更新频繁时推荐,可以兼顾性能,方便代码更新

opcache.revalidate_freq=300
opcache.validate_timestamps=1
opcache.max_accelerated_files=7963
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.fast_shutdown=1

三、稳定项目推荐,性能最好

opcache.revalidate_freq=0
opcache.validate_timestamps=0
opcache.max_accelerated_files=7963
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.fast_shutdown=1

PHP 高性能开发 | OPcache 最佳实践

我们了解了这么多对于OPcache的概念和思想,如果最后都没有亲自去测试一下它给我们带来的好处,或者根本都不知道它到底是否真的能提高性能么?能提高多少?下面我们就来测试一下它在实际开发中的表现吧!
如果要测试或者查看OPcache技术的表现,那么需要编写相应的测试用例,编写一个好的测试用例才能让我们更好的了解和熟悉它的概念和设计理念,让我们根据如下步骤进行:
  1. 创建一个php文件:test.php
    function G($start,$end='',$dec=4)
    {
        static $_info = array();
        if (!empty($end))
        {
            if(!isset($_info[$end])) $_info[$end] = microtime(TRUE);
            $sconds = number_format(($_info[$end]-$_info[$start]), $dec) * 1000;
            echo "{$sconds}ms<br />";
        }
        else
        {
            $_info[$start] = microtime(TRUE);
        }
    }
    
    G("s");
    //ini_set("opcache.enable",false); //这里表示关闭opcache缓存
    $file = __DIR__."/test1.php";
    for ($i=0;$i<100; $i++) {
        require $file;
    }
    G("s","e");
  2. 创建另一个php文件:test1.php 
    $index = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    $index .= "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    //后面重复1000行
  3. 执行test.php
  4. 打开test.php 中注释掉的代码:ini_set("opcache.enable",false);
  5. 再次执行test.php
  6. 循环3,4,5步骤的操作
根据上面的测试步骤我们可以发现,如果打开opcache缓存的情况下执行测试代码用时在10ms ~ 20ms 之间波动,如果关闭opcache缓存后用时在410ms - 420ms 之间波动,由此可见opcache技术对加载性能的优化是很大的
相关提问
敬请期待