【发布时间】:2013-08-01 01:41:06
【问题描述】:
我对 PHP 比较陌生,并且正在慢慢学习特定于该语言的特性。我被很多人讨厌的一件事是我(有人告诉我)使用了太多的函数调用,并且通常被要求做一些事情来解决它们。举两个例子:
// Change this:
} catch (Exception $e) {
print "It seems that error " . $e->getCode() . " occured";
log("Error: " . $e->getCode());
}
// To this:
} catch (Exception $e) {
$code = $e->getCode();
print "It seems that error " . $code . " occured";
log("Error: " . $code);
}
第二个例子
// Change this:
$customer->setProducts($products);
// To this:
if (!empty($products)) {
$customer->setProducts($products);
}
在第一个示例中,我发现将$e->getCode() 分配给$code 会产生轻微的认知开销; “'$code'是什么?啊,这是异常的代码。”而第二个例子增加了圈复杂度。在这两个示例中,我发现优化是以牺牲可读性和可维护性为代价的。
性能提升值得还是这种微优化?
我应该注意到,我们目前还停留在 PHP 5.2 上。
我进行了一些非常粗略的基准测试,发现函数调用性能命中率约为 10% 到 70%,具体取决于基准测试的性质。我承认这很重要。但在那个 catch 块被命中之前,有一个对数据库和 HTTP 端点的调用。在$products 设置在$customer 上之前,$products 数组发生了复杂的排序。 归根结底,这种优化是否证明了使代码更难阅读和维护的成本是合理的? 或者,尽管这些示例是简化的,但是否有人发现第二个示例同样容易或更容易阅读比第一个(我是维也纳人)吗?
谁能引用任何关于这方面的好文章或研究?
编辑:
基准测试示例:
<?php
class Foo {
private $list;
public function setList($list) {
$this->list = $list;
}
}
$foo1 = new Foo();
for($i = 0; $i < 1000000; $i++) {
$a = array();
if (!empty($a))
$foo1->setList($a);
}
?>
使用time 命令运行该文件。在一台特定的机器上,几次运行后平均需要 0.60 秒。注释掉 if (!empty($a)) 会导致它平均需要 3.00 秒才能运行。
澄清:这些是示例。第一个示例演示了可怕的异常处理和可能的 DRY 违规,而牺牲了一个简单的、非特定领域的示例。
【问题讨论】:
-
10% 到 70% 的开销通过调用什么函数?
-
恕我直言,如果需要这种级别的优化,那么 PHP 一开始就不是正确的工具。
-
在您的第一个示例中,您需要调用 $e->getCode() 两次(增加开销),但第二部分是将结果分配给变量并多次使用它。良好的编码习惯。在第二个示例中,您再次进行防御性编程是一种很好的编程习惯。
-
这完全取决于函数的实际作用,以及执行需要多长时间:
$e->getCode();非常简单,并且带有微优化的味道;但是,如果连续多次重复调用,则进行 db 调用以返回 1000 行的函数将非常重要。分析您的代码应该为您提供函数调用的时序图 -
@Anigel,我在问题中添加了一项基准测试。
标签: php optimization php-5.2