PHP 7 - assert(string) 有时很慢



我最近将一个站点复制到运行PHP 7的新服务器上。 代码严重依赖于 assert() 调用。 为了使断言在新服务器上运行,我们必须将 zend.assertions 设置为 1。 断言现在可以工作,但大约一半的时间,某些页面的加载速度会非常慢(60+ 秒)。

我有调试函数,可以让我看到每个代码块需要多长时间。 他们告诉我,有时调用 assert() 需要不到一毫秒的时间,但有时它的成本约为 60 毫秒。

当我将以下 [伪代码] 添加到我观察到速度变慢的代码区域时,我发现了这一点:

  1. 输出时间
  2. 调用断言(真)100 次
  3. 输出时间
  4. 调用断言('true') 100 次
  5. 输出时间

这让我看到了"assert()"调用的成本有多高,无论是将表达式作为参数[assert(true)调用],还是将字符串表达式作为参数[assert('true')调用]。

有时,当我刷新页面时,两个循环总共花费不到 1 毫秒的时间。

然而,其他时候,通过这些循环的前几次传递可能很快,但突然间 assert('true') 循环需要超过 6 秒,这意味着每个 assert('true') 调用大约需要 60 毫秒。 但是,断言(true)调用仍然很快。

这意味着有时当我们使用字符串参数调用 assert() 时,该字符串的计算速度非常慢。

不过,这很不稳定。 就像我说的,我刷新页面的一半时间,断言('true')一直都很快......但其他时候断言('true')统计数据每次调用花费大约 60 毫秒。

当 zend.assertions 设置为 -1 时,assert('true') 调用显然永远不会被评估,并且永远不会有任何缓慢。

我以前从未遇到过这种缓慢,过去我在几台服务器上使用过断言。 不过,永远不要使用 PHP 7。

一个快速的"解决方案"可能是停止使用断言,或者停止将字符串作为参数传递给 assert() 函数。 但是我有成百上千个函数,所有这些函数都使用带有字符串参数的 assert()! 很久以前,我养成了将 assert() 与字符串一起使用的习惯,当时它被认为是最佳实践(这样当失败的表达式在生产环境中发生时,您可以记录或通过电子邮件发送它们)。

所以,我需要的是找到一种方法来防止 PHP 7 偶尔导致 assert(string) 花费 60 毫秒。

知道如何解决这个问题吗?

谢谢!

系统管理员/PHP 导出能够找到问题。 这是opcache模块和断言之间的兼容性错误。

基本上,在 PHP 7.0(至少我们的版本)中,如果启用了 opcache(在 PHP 中默认如此)并且zend.assertions=1,那么随着时间的推移,opcache 逻辑和 zend 断言逻辑开始相互干扰,导致 assert(string) 调用的执行速度非常慢。

所以,这是一个非常奇怪的错误,唯一会遇到它的人是我们这些使用 PHP 7.0 的人,他们有很多断言(字符串)调用(并且 opcache 处于启用状态)。

快速解决方法是通过 php 或.ini在 PHP 开始时调用 opcache_reset() 来禁用 opcache。

我已经测试了两个修复程序,它们都可以工作。 我更喜欢 php.ini 修复,因为 opcache_reset() 不适用于 PHP 的所有安装;当我尝试在另一台服务器上调用该函数时,我遇到了一个未定义的函数错误。

当然,最好的长期解决方案是有人修复opcache和/或断言库,这样它们就不会冲突。

相关内容

  • 没有找到相关文章

最新更新