什么时候PHP 5.5+ Opcache确实根据revalidate_freq设置检查文件时间戳

时间:2014-09-03 16:32:21

标签: php opcache

在此之前/其他地方已经提出道歉,但我找不到答案。

我们在部署后的一分钟内遇到了一些问题,我们认为它们与Opcache有关。在我们的实时设置中,我们有以下Opcache设置:

opcache.revalidate_freq=60
opcache.validate_timestamps=1

PHP做了以下哪些操作?

  1. 当PHP需要一个文件时,在那一点检查它是否自上次生成文件的新缓存以来已经过60秒,如果它已经更多,那么为此请求生成一个新缓存? / p>

  2. 或者它是否在某种形式的计时器(或其他)上运行,其中60秒与上次需要文件无关?

  3. 我期待选项1,但这不能解释我们60秒左右的问题,因为文件的文件路径不同,因为我们每次都部署到交替的A或B目录。

    我希望这有道理吗?谢谢你的帮助。

2 个答案:

答案 0 :(得分:3)

根据我对PHP源代码的分析,会发生与选项1类似的事情。当PHP需要文件时,它检查自上次编译或重新验证文件以来是否opcache.revalidate_freq秒。如果没有,它将跳过重新验证(时间戳检查)。

换句话说,opcache.revalidate_freq设置指定时间戳检查的最大频率。 文件直到被请求后才会重新验证,即使距上次重新验证已经一年了。

来源

这是ZendAccelerator.c中的C function,用于处理缓存验证:

int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
{
    if (persistent_script->timestamp == 0) {
        return SUCCESS; /* Don't check timestamps of preloaded scripts */
    } else if (ZCG(accel_directives).revalidate_freq &&
        persistent_script->dynamic_members.revalidate >= ZCG(request_time)) {
        return SUCCESS;
    } else if (do_validate_timestamps(persistent_script, file_handle) == FAILURE) {
        return FAILURE;
    } else {
        persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
        return SUCCESS;
    }
}

成功重新验证脚本后-也就是说,当PHP检查文件的时间戳,并发现自将文件放入缓存以来,该文件没有更改时,它将为另一个{{ 1}}秒(opcache.revalidate_freq属性)。这样可以避免在该时间段内进行进一步的时间戳检查(PHP将假定文件是最新的)。

如果重新验证不成功–即时间戳比缓存中的时间戳新,则将导致重新编译,这还将设置相同的.revalidate属性(以上代码中未显示),再次免除重新验证同一时间段的文件。

似乎仅从persistent_compile_file()调用了上述函数,该函数在执行脚本时都会被调用。我找不到任何其他引用,表明使用了另一个触发器,例如计时器。

答案 1 :(得分:1)

所以,来自PHP manual

  

检查脚本时间戳的更新频率,以秒为单位。 0将导致OPcache检查每个请求的更新。

所以正在发生的是你正在更新文件,但是你的指令说你在更新文件和opcache构建新操作码之间的时间长达60秒。

validate_timestamps 有答案。因为您想手动重新验证文件,所以可以执行此操作

  

禁用此指令时,必须通过opcache_reset(),opcache_invalidate()手动重置OPcache,或者重新启动Web服务器以使文件系统的更改生效。