尝试在PHP中的性能
在php 5中使用try-catch语句时需要考虑什么样的性能影响?
我以前在网上阅读过一些关于这个主题的旧的,看似矛盾的信息。 我目前必须使用的许多框架都是在PHP 4上创build的,缺less很多php 5的优点。所以,我没有太多的经验来使用php的try-catchs。
有一件事要考虑的是,没有抛出exception的try块的代价与实际抛出和捕获exception的代价是不同的。
如果exception只是在失败情况下抛出,那么你几乎肯定不会关心性能,因为每次执行程序都不会失败很多次。 如果你在一个紧密的循环中失败(又名:将你的头撞在砖墙上),那么你的应用程序可能会比缓慢的问题困难得多。 所以不要担心抛出一个exception的代价,除非你不得不使用它们来进行常规控制stream。
有人张贴了一个关于抛出exception的分析代码的回答。 我从来没有自己testing过,但我有把握地预测,这将显示出更大的性能,而不仅仅是进入和退出try块而不会抛出任何东西。
另一件需要考虑的事情就是,在嵌套调用深度很深的地方,单次尝试更快的速度比在每次调用时检查返回值和传播错误的速度更快。
在这种情况的对立面上,如果你发现自己的try … catch块中包含了每一个调用,你的代码就会变慢。 还有丑陋的
我感到无聊,并描述了以下内容(我遗漏了时间码):
function no_except($a, $b) { $a += $b; return $a; } function except($a, $b) { try { $a += $b; } catch (Exception $e) {} return $a; }
使用两个不同的循环:
echo 'no except with no surrounding try'; for ($i = 0; $i < NUM_TESTS; ++$i) { no_except(5, 7); } echo 'no except with surrounding try'; for ($i = 0; $i < NUM_TESTS; ++$i) { try { no_except(5, 7); } catch (Exception $e) {} } echo 'except with no surrounding try'; for ($i = 0; $i < NUM_TESTS; ++$i) { except(5, 7); } echo 'except with surrounding try'; for ($i = 0; $i < NUM_TESTS; ++$i) { try { except(5, 7); } catch (Exception $e) {} }
在我的WinXP框上运行1000000运行apache和PHP 5.2.6:
no except with no surrounding try = 3.3296 no except with surrounding try = 3.4246 except with no surrounding try = 3.2548 except with surrounding try = 3.2913
无论试验顺序如何,这些结果都是一致的,保持相似的比例。
结论:添加代码来处理罕见的exception不会比编写忽略exception的代码慢。
try-catch块不是性能问题 – 真正的性能瓶颈来自创buildexception对象。
testing代码:
function shuffle_assoc($array) { $keys = array_keys($array); shuffle($keys); return array_merge(array_flip($keys), $array); } $c_e = new Exception('n'); function no_try($a, $b) { $a = new stdclass; return $a; } function no_except($a, $b) { try { $a = new Exception('k'); } catch (Exception $e) { return $a + $b; } return $a; } function except($a, $b) { try { throw new Exception('k'); } catch (Exception $e) { return $a + $b; } return $a; } function constant_except($a, $b) { global $c_e; try { throw $c_e; } catch (Exception $e) { return $a + $b; } return $a; } $tests = array( 'no try with no surrounding try'=>function() { no_try(5, 7); }, 'no try with surrounding try'=>function() { try { no_try(5, 7); } catch (Exception $e) {} }, 'no except with no surrounding try'=>function() { no_except(5, 7); }, 'no except with surrounding try'=>function() { try { no_except(5, 7); } catch (Exception $e) {} }, 'except with no surrounding try'=>function() { except(5, 7); }, 'except with surrounding try'=>function() { try { except(5, 7); } catch (Exception $e) {} }, 'constant except with no surrounding try'=>function() { constant_except(5, 7); }, 'constant except with surrounding try'=>function() { try { constant_except(5, 7); } catch (Exception $e) {} }, ); $tests = shuffle_assoc($tests); foreach($tests as $k=>$f) { echo $k; $start = microtime(true); for ($i = 0; $i < 1000000; ++$i) { $f(); } echo ' = '.number_format((microtime(true) - $start), 4)."<br>\n"; }
结果:
no try with no surrounding try = 0.5130 no try with surrounding try = 0.5665 no except with no surrounding try = 3.6469 no except with surrounding try = 3.6979 except with no surrounding try = 3.8729 except with surrounding try = 3.8978 constant except with no surrounding try = 0.5741 constant except with surrounding try = 0.6234
通常,使用exception来防止意外的错误,并且在代码中使用错误检查来对付属于正常程序状态的错误。 为了显示:
-
在数据库 – 有效状态中找不到logging,应该检查查询结果并正确地向用户发送消息。
-
SQL错误,当试图获取logging – 意外的失败,logging可能会或可能不会在那里,但你有一个程序错误 – 这是一个例外的好地方 – 错误日志中的日志错误,电子邮件pipe理员堆栈跟踪,并显示一个礼貌的错误消息给用户,build议他出了点问题,你正在努力。
例外是昂贵的,但除非你使用它们来处理你的整个程序stream程,否则任何性能差异都不应该引起人们注意。
我还没有发现任何关于谷歌的Try / Catch性能,但一个循环投掷错误,而不是一个IF语句简单的testing产生329ms与6ms在5000循环。
对不起,发布到一个非常古老的消息,但我读了评论,我有点不同意,差异可能是最简单的一段代码,或者可以忽略Try / Catch用于代码的特定部分总是可预测的,但我也相信(没有testing)一个简单的:
if(isset($var) && is_array($var)){ foreach($var as $k=>$v){ $var[$k] = $v+1; } }
比…更快
try{ foreach($var as $k=>$v){ $var[$k] = $v+1; } }catch(Exception($e)){ }
我也相信(未经testing)a:
<?php //beginning code try{ //some more code foreach($var as $k=>$v){ $var[$k] = $v+1; } //more code }catch(Exception($e)){ } //output everything ?>
比在代码中使用额外的IF更昂贵
这是一个非常好的问题!
我已经testing了很多次,从来没有看到任何性能问题;-)这是十年前在C + +是真实的,但我认为今天,他们已经改善了很多,因为它非常有用,更清洁。
但是我仍然害怕围绕我的第一个切入点:
try {Controller::run();}catch(...)
我没有testing大量的函数调用和大包括….是否有人已经完全testing它已经?
一般来说,他们是昂贵的,不值得在PHP中。
由于它是一个检查的expression式语言,你必须捕获任何抛出exception的东西。
在处理遗留的代码时,如果不涉及遗漏代码,那么只会导致混淆。
祝你好运!