10

例如,如果我实现一些简单的对象缓存,哪种方法更快?

1. return isset($cache[$cls]) ? $cache[$cls] : $cache[$cls] = new $cls;

2. return @$cache[$cls] ?: $cache[$cls] = new $cls;

我在某处读到@需要大量时间来执行(我想知道为什么),尤其是在实际发出和禁止警告/通知时。isset()另一方面意味着额外的哈希查找。那么哪个更好,为什么?

我确实希望在全球范围内保持 E_NOTICE 处于开发和生产服务器上。

4

5 回答 5

8

我不会担心哪种方法更快。那是一个微优化。我会更担心哪个代码更具可读性和更好的编码实践。

我当然更喜欢您的第一个选项而不是第二个选项,因为您的意图更加清晰。此外,最好通过始终明确地测试变量来避免边缘条件问题,以确保您得到预期的结果。例如,如果存储的类$cache[$cls]不是 type$cls怎么办?

就个人而言,如果我通常不希望 $cache 上的索引未设置,那么我也会将错误处理放在那里而不是使用三元操作。如果我可以合理地期望该索引会定期取消设置,那么我会让类$cls表现为单例并让您的代码类似于

return $cls::get_instance();
于 2012-10-04T18:44:08.110 回答
8

isset()方法更好。它是明确声明索引可能未定义的代码。抑制错误是草率的编码。

根据这篇文章10 Performance Tips to Speed Up PHP,警告需要额外的执行时间,并且还声称@操作符“昂贵”。

事先清理警告和错误也可以让你避免使用@错误抑制,这很昂贵。

此外,@不会抑制与自定义错误处理程序有关的错误:

http://www.php.net/manual/en/language.operators.errorcontrol.php

如果您使用 set_error_handler() 设置了自定义错误处理函数,那么它仍然会被调用,但是这个自定义错误处理程序可以(并且应该)调用 error_reporting() 当触发错误的调用前面有 @ 时,它将返回 0 .

如果启用了 track_errors 功能,则表达式生成的任何错误消息都将保存在变量 $php_errormsg 中。这个变量将在每个错误上被覆盖,所以如果你想使用它,请尽早检查。

于 2012-10-04T18:46:00.697 回答
7

@暂时改变error_reporting状态,这就是为什么说它需要时间。

如果您期望某个值,验证它的第一件事是检查它是否已定义。如果你有通知,那可能是因为你遗漏了一些东西。isset()在我看来,使用是一种很好的做法。

于 2012-10-04T18:44:44.820 回答
3

我对这两种情况都进行了计时测试,使用各种长度的哈希键,还使用哈希表的各种命中/未命中率,以及使用和不使用E_NOTICE.

结果是:与error_reporting(E_ALL)isset()体相比,速度快了@20-30%。使用的平台:OS X 10.8 上的命令行 PHP 5.4.7。

但是,error_reporting(E_ALL & ~E_NOTICE)短哈希键的差异在 1-2% 以内,而长哈希键(16 个字符)的差异在 10% 以内。

请注意,第一个变体执行 2 次哈希表查找,而 with 的变体@只执行一次查找。

因此,@在所有情况下都较差,我想知道是否有任何优化它的计划。

于 2012-10-04T22:53:02.550 回答
1

我认为您的优先事项在这里有些混乱。

首先,如果您想获得更快的真实世界测试 - 对其进行负载测试。如前所述,尽管压制可能会更慢。

这里的问题是,如果您对常规代码有性能问题,您应该升级您的硬件,或者优化您的代码的大逻辑,而不是阻止正确执行和错误检查。

从长远来看,抑制错误以窃取最微小的速度增益对您没有任何好处。特别是如果您认为此错误可能会一次又一次地发生,并导致您的应用程序运行速度比捕获并修复错误时更慢。

于 2012-10-04T19:14:13.643 回答