假设我有一个相当大的 100k 元素的关联数组,如下所示:
$resources = array(
'stone'=>'current_stone.gif',
'stick'=>'uglystick.jpg',
...
);
存储在名为 resources.php 的文件中,永远不会在运行时更改。
我想在Zend opcache中使用这些数据,以便在所有进程中共享它(节省内存)并可能加快查找速度。
我目前的假设是,在这种形式下,这个数组不会存储在opcache中,因为它在任何地方都没有被定义为静态结构。
我如何确保这些数据进入opcache?
答案 0 :(得分:2)
不,你不能在OPcache中存储变量,但是类中的静态工作:
class Resource {
static $image = [
'stone'=>'current_stone.gif',
'stick'=>'uglystick.jpg',
...
];
}
...
echo Resource::$image['stone'], "\n";
这保存了初始化数组的所有操作码,但是OPcache仍然会将SMA中编译脚本中的Resource :: $ image版本深度复制到进程空间中相应的类静态属性中,所以你仍然会有在使用资源的每个活动进程中HashTable的副本 - 尽管字符串本身将 interned ,因此在使用此类的所有活动php请求之间共享。
如果您使用的是类自动加载器,要加载您的类,那么除了引用Resoure::$image...
之外,您甚至不需要执行任何操作,自动加载器将为您执行映射。
答案 1 :(得分:2)
以上答案不正确。变量存储在操作码缓存中。
您可以通过创建大量数据,将其存储在PHP文件中并使用opcache_get_status()检查缓存统计信息来对其进行测试。结果包含列出所有缓存文件和已用内存的“脚本”数组。
我写了几个缓存文件,它们只有一个大数组。其中之一是24.1Mb
这是print_r(opcache_get_status())
的转储结果:
Array
(
[opcache_enabled] => 1
...
[scripts] => Array
(
...
[/test/noto.php] => Array
(
[full_path] => /test/noto.php
[hits] => 3
[memory_consumption] => 24591120
[last_used] => Sat Nov 24 21:09:58 2018
[last_used_timestamp] => 1543086598
[timestamp] => 1543086378
)
...
)
)
因此,它肯定与所有数据一起存储在内存中。
为确保如此,我制作了几个文件,这些文件的总大小约为300Mb。如果没有opcache,则全部加载大约需要1.5秒。然后,在初始加载后将其缓存,并花费2毫秒加载所有数据。相差近1000倍。
因此,将缓存存储在将由Zend OPcache缓存的PHP文件中并使用include包括它(使用try..catch(\Throwable $e)
以避免错误)是迄今为止缓存数据的最有效方法。