如果循环内部或外部的语句?

问题描述:

是更好,如果我这样做:如果循环内部或外部的语句?

foreach my $item (@array) { 
    if ($bool) { 
    .. code .. 
    } 
    else { 
    .. code .. 
    } 
} 

if ($bool) { 
    foreach my $item (@array) { 
    } 
} 
else { 
    foreach my $item (@array) { 
    } 
} 
+4

$ bool是否被循环中的任何内容所改变? – 2010-02-11 04:58:35

+0

$ bool是一个不变的静态变量。 – Timmy 2010-02-11 05:24:56

+1

不要为'foreach'循环的每次迭代执行'if else'。第二个例子肯定是要走的路。 – JohnB 2010-11-04 23:23:41

我会把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

+7

我不知道在编写代码时考虑性能影响总是过早的优化。我同意在这种情况下它可能可以忽略不计,但我并不总是同意“不成熟的优化”总括声明。 – 2010-02-11 04:33:23

+4

@Andy:好的,就选择正确的算法等而言,是的,你必须意识到选择哪一个,所以你最终不会认真对待你的程序。但是一般来说,在尽可能以最清晰的方式编写程序(可能做重构以消除任何过早的优化)后,您的分析器将会很好地告诉您需要修复的问题。 – 2010-02-11 04:48:56

+4

思维很好。对性能的思考是很好的。但是如果你的编译器不会为语义相同的结构生成相同的代码,那么现在是时候修复你的编译器了。不要为了解决语言实现错误而微观优化应用程序,这是错误的抽象层次。 – jrockway 2010-02-11 06:48:54

我建议你既时间,看看自己,但我不希望的差异是巨大的。

如果你正在为速度进行优化,第二个(在if分支内的foreach循环)应该更快,因为你不会在每个循环迭代中进行测试。

+0

你应该编写程序并为自己测试。 :-P我所做的时间测试表明差异可以忽略不计。 – 2010-02-11 04:26:33

+0

@Chris Jester-Young:好的,我做到了。我的代码初始化了一个100万个元素的数组,然后循环遍历它将元素写入文件。第二种方法(在if内部循环)始终快速且在.3秒至1.6秒之间变化,平均为0.7秒(每次运行约17秒),平均提高约4%。授予,不大,但是否重要取决于具体情况。 – GreenMatt 2010-02-14 04:32:28

+0

在我的书中,17秒的差距可以忽略不计,但是就像你说的,我认为这取决于上下文。 :-) – 2010-02-14 05:17:03

第二个比较快,因为比较次数少得多。 - 比较是在循环之外而不是内部。

由于比较变量是一个循环不变量,如果它不是更清晰的编码,我会感到惊讶。

实际转速差(挂钟时间)取决于阵列

简单评估布尔变量,你在这里做的大小,这些是大致相当于。但是,如果将变量替换为花费很长时间评估的复杂表达式,则第二个示例会更好,因为它只会被评估一次。

+2

或者您可以将$ bool设置为复杂表达式的值:) – ysth 2010-02-11 04:49:43

+0

确实如此。那是很自然的事情。 – 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中出现正确的东西,您就不会更改迭代代码。