如果循环内部或外部的语句?
是更好,如果我这样做:如果循环内部或外部的语句?
foreach my $item (@array) {
if ($bool) {
.. code ..
}
else {
.. code ..
}
}
或
if ($bool) {
foreach my $item (@array) {
}
}
else {
foreach my $item (@array) {
}
}
我会把premature optimization放在一旁。
“过早的优化是万恶之根” - 高德纳
你应该去维护第一位的。以更有意义的方式对它们进行分组,将代码的逻辑结构考虑在内(例如将相关的语句组合在一起)。
如果您以后确定性能问题,请尝试使用类似探查器的测量来查看瓶颈位置。机会是,它不在那里。从代码完成2:
巴里贝姆报告说, 20%的程序的程序占用80%的 它的执行时间。在他的 经典论文“关于 Fortran程序的实证研究”中,Donald Knuth发现 ,其中不到百分之四的 程序通常占其运行时间的50%多于 。
因为我们大多数人在猜测代码的慢部分在哪里真的很糟糕,所以我们不应该试图猜测在哪里进行优化。随时进行优化的程序员也花费大约96%的时间优化不需要优化的代码。考虑到另一件事是,代码调整(如本例)认为性能可读性和可维护性之间的权衡: 初始开发期间
着眼于优化从 有损其他实现计划目标。 开发人员将自己沉浸在 算法分析和奥术辩论 那最后不会为用户贡献太多 值。如 正确性,信息隐藏和 可读性的担心成为次要目标,即使性能更容易 改善晚于其他 关注的是。事后性能 工作通常会影响少于五个程序代码的百分之五十 。请问 宁愿退回,并在百分之五的代码或 可读性工作上做性能工作 ?
我不是说不优化,但优化最终唯一的代码,当你有大局和工具的奢侈品你指出正确的方向。
EXTRA:要回答的表演本身的问题,但:
这[ “外提” 代码]有利于节省时间约20%:
Language Straight Time Code-Tuned Time Time Savings
C++ 2.81 2.27 19%
Java 3.97 3.12 21%
Visual Basic 2.78 2.77 <1%
Python 8.14 5.87 28%
不同于这种情况的一个危险是两个回路必须保持平行。 [...]您必须记住在两个地方更改代码,这对您而言是一个烦恼,对于需要使用代码的任何其他人而言,这是一个令人头痛的问题。
该示例还说明了代码优化中的关键挑战:任何特定代码优化的效果都不可预测。代码调优在 四种语言中的三种中产生了重大改进,但在Visual Basic中却没有这种改进。要在此特定版本的Visual Basic中执行此特定的 优化,将产生较少的可维护代码,而不会在性能方面带来任何抵消性增益。一般的教训是,您必须测量每个特定优化的效果以确保其效果 - 没有 例外。
检查this other关于SO的问题。和Code Complete第一版中的this。
我不知道在编写代码时考虑性能影响总是过早的优化。我同意在这种情况下它可能可以忽略不计,但我并不总是同意“不成熟的优化”总括声明。 – 2010-02-11 04:33:23
@Andy:好的,就选择正确的算法等而言,是的,你必须意识到选择哪一个,所以你最终不会认真对待你的程序。但是一般来说,在尽可能以最清晰的方式编写程序(可能做重构以消除任何过早的优化)后,您的分析器将会很好地告诉您需要修复的问题。 – 2010-02-11 04:48:56
思维很好。对性能的思考是很好的。但是如果你的编译器不会为语义相同的结构生成相同的代码,那么现在是时候修复你的编译器了。不要为了解决语言实现错误而微观优化应用程序,这是错误的抽象层次。 – jrockway 2010-02-11 06:48:54
我建议你既时间,看看自己,但我不希望的差异是巨大的。
如果你正在为速度进行优化,第二个(在if分支内的foreach循环)应该更快,因为你不会在每个循环迭代中进行测试。
你应该编写程序并为自己测试。 :-P我所做的时间测试表明差异可以忽略不计。 – 2010-02-11 04:26:33
@Chris Jester-Young:好的,我做到了。我的代码初始化了一个100万个元素的数组,然后循环遍历它将元素写入文件。第二种方法(在if内部循环)始终快速且在.3秒至1.6秒之间变化,平均为0.7秒(每次运行约17秒),平均提高约4%。授予,不大,但是否重要取决于具体情况。 – GreenMatt 2010-02-14 04:32:28
在我的书中,17秒的差距可以忽略不计,但是就像你说的,我认为这取决于上下文。 :-) – 2010-02-14 05:17:03
第二个比较快,因为比较次数少得多。 - 比较是在循环之外而不是内部。
由于比较变量是一个循环不变量,如果它不是更清晰的编码,我会感到惊讶。
实际转速差(挂钟时间)取决于阵列
简单评估布尔变量,你在这里做的大小,这些是大致相当于。但是,如果将变量替换为花费很长时间评估的复杂表达式,则第二个示例会更好,因为它只会被评估一次。
或者您可以将$ bool设置为复杂表达式的值:) – ysth 2010-02-11 04:49:43
确实如此。那是很自然的事情。 – 2010-02-11 05:21:03
每个人似乎都停留在性能问题上。
无需重复代码几乎总是更好。也就是说,多次输入同一个东西对你来说应该是很痛苦的。既然你没有对每个代码都说过什么,我会假设你想在每种情况下做不同的事情。我的偏好是将迭代的细节与特定的处理分开。
my $sub_ref = $bool ? make_true_function() : make_false_function();
foreach my $element (@array) {
$sub_ref->($element);
}
sub make_true_function { sub { ... } }
sub make_false_function { sub { ... } }
这可能会在性能上失去一点点,但由于代码不那么纠结,所以看起来要容易得多。 foreach
不关心任何关于分支或你如何做出决定。当你想拥有更多的分支时,这个效果很好。只要$sub_ref
中出现正确的东西,您就不会更改迭代代码。
$ bool是否被循环中的任何内容所改变? – 2010-02-11 04:58:35
$ bool是一个不变的静态变量。 – Timmy 2010-02-11 05:24:56
不要为'foreach'循环的每次迭代执行'if else'。第二个例子肯定是要走的路。 – JohnB 2010-11-04 23:23:41