php的Opcache已经release好多年了,现在基本都是php的标配。最近看到了php创始人Rasmus Lerdorf的一篇talk,于是有了使用php的opcache发布代码的想法。

Opcache

Opcache也叫Zend OPcache,其前身是Zend公司开发的闭源PHP优化加速组件Optimizer+。于2013年3月中旬改名为Opcache,并开源。

在2013年6月发布的php5.5.0版本中,整合了Opcache

pecl上的Opcache扩展,于2015-01-12转正。

OPcache通过将 PHP 脚本预编译的字节码存储到共享内存(或者文件)中来提升 PHP 的性能, 存储预编译字节码的好处就是 省去了每次加载和解析 PHP 脚本的开销。不过OPcache 没有象 APC 那样的 user cache 功能。

Opcache使用

php5.5及以上版本已经整合了Opcache,只需要在编译php时添加

--enable-opcache --enable-opcache-file

即可为php添加opcache扩展,然后修改php.ini,主动开启Opcache

zend_extension="/path/opcache.so"
[opcache]
opcache.enable=1
opcache.enable_cli=1

之后运行php程序时,会生成Opcache,下次运行时可以直接加载,免去了词法分析,语法分析,以及解析php脚本花费的时间。

Opcache默认存储在php进程的共享内存中,不过也可以存储到本地文件中。性能的差异大致如下:

看完这张图,突然有种脑洞大开的感觉。

发布php时,预先生成opcache-file,只发布opcache,是否可行呢?

使用Opcache发布php

开启Opcache后,可以使用opcache_compile_file生成php的opcache-file。涉及php.ini中的如下配置参数

opcache.max_accelerated_files=20000
opcache.file_cache=/data/php/opcache
opcache.file_cache_only=0
opcache.validate_timestamps=0
opcache.save_comments=0
1
2
3
4
5
6
7
8
9
10
11
12
13

function opcache_compile_files($dir) {
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $v) {
if(!$v->isDir() && preg_match('%\.php$%', $v->getRealPath())) {
$file = $v->getRealPath();
opcache_compile_file($file);
file_put_contents($file, '');
echo $file . "\n";
}
}
}

opcache_compile_files('/path/project/foo');

在命令行下执行上述脚本,即可遍历整个项目,生成对应php的opcache-file,同时会清空原php文件的内容。

如:

ls /data/php/opcache/4d400aec8fadf667fabe41a87f30f7cc

/data/php/opcache/4d400aec8fadf667fabe41a87f30f7cc/path/project/app/Utility.php.bin
1
2
1. 生成opcache-file时,需要设置opcache.file_cache_only=0
2. 需要保持原有项目的目录结构和文件 -- 内容可以清空,使opcache-file生效