静态数组是否存储在opcache中?

时间:2013-12-29 23:26:31

标签: opcache

假设我有一个相当大的 100k 元素的关联数组,如下所示:

$resources = array(
'stone'=>'current_stone.gif',
'stick'=>'uglystick.jpg',
...
);

存储在名为 resources.php 的文件中,永远不会在运行时更改

我想在Zend opcache中使用这些数据,以便在所有进程中共享它(节省内存)并可能加快查找速度。

我目前的假设是,在这种形式下,这个数组不会存储在opcache中,因为它在任何地方都没有被定义为静态结构。

我如何确保这些数据进入opcache?

2 个答案:

答案 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)以避免错误)是迄今为止缓存数据的最有效方法。