使用短路评估的好处

时间:2008-09-18 01:19:51

标签: architecture pipeline

boolean a = false, b = true;
if ( a && b ) { ... };

在大多数语言中,b不会被评估,因为a为false,因此a && b不能为真。我的问题是,在架构方面,短路会不会更慢?在管道中,您是否只是在等待获得a的结果时停止以确定是否应该评估b?改为使用嵌套ifs会更好吗?这有帮助吗?

另外,有谁知道通常会调用什么短路评估?这个问题出现之后我发现我的编程朋友从未听说过短路评估,并表示它不常见,也没有在许多语言中找到,并且管道效率低下。我不确定最后一个,所以问你大家!

好吧,我想一个不同的例子或许可以解释我的朋友可能来自哪里。他认为,自从评估如下的声明以来:

(a) if ( ( a != null ) && ( a.equals(b) ) ) { ... }

会使系统崩溃,一个没有短路的架构(从而不允许像上面这样的语句)在处理这样的语句时会更快:

(b) if ( ( a == 4 ) && ( b == 5 ) )

因为如果它不能并行地做(a),它就不能并行地做(b)。在这种情况下,允许短路的语言比没有短路的语言慢。

我不知道这是不是真的。

由于

15 个答案:

答案 0 :(得分:12)

如果语句(分支基本上是goto),短路评估将以相同的方式转换为汇编语言中的分支,这意味着它不会比if语句慢。

分支通常不会停止管道,但处理器会猜测分支是否被占用,如果处理器出错,它将必须清除所有发生的事情,因为它从管道做出了错误的猜测。

短路评估也是最常见的名称,并且在大多数语言中以某种形式存在。

答案 1 :(得分:9)

短路布尔表达式与某些嵌套ifs集完全等效,因此效果与此相同。

如果b没有副作用,它仍然可以与a并行执行(对于任何“并行”值,包括流水线)。

如果b具有CPU架构在分支预测失败时无法取消的副作用,那么可能需要延迟,如果双方都经常被评估,则可能会出现延迟。因此,如果您发现短路运算符在您的代码中造成性能瓶颈,那么可以看一下,但不值得担心。

但短路用于控制流程,以节省不必要的工作。它在我使用的语言中很常见,例如Perl习语:

open($filename) or die("couldn't open file");

shell成语:

do_something || echo "that failed"

或C / C ++ / Java / etc成语:

if ((obj != 0) && (obj->ready)) { do_something; } // not -> in Java of course.

在所有这些情况下,您都需要短路,因此只有在LHS规定应该进行RHS评估时才会对RHS进行评估。在这种情况下,没有必要将性能与替代代码进行比较,这是错误的!

答案 2 :(得分:8)

老实说,我不担心。测试布尔值非常快。当第二个表达式有副作用时,短路只会变得有趣/有用:

if ( ConfirmAction() && DestroyAllData() )
   Reboot();

......或取决于第一次测试:

if ( myDodgyVar != null && myDodgyVar.IsActive() )
   DoSomethingWith(myDodgyVar);

答案 3 :(得分:5)

支持短路的语言:

Ada,Eiffel,ALGOL 68,C1,C ++,C#,Java,R,Erlang,Standard ML,Javascript,MATLAB,Lisp,Lua,Scheme,OCaml,Haskell,Pascal,Perl,Ruby,PHP,Python,Smalltalk ,Visual Basic .NET

取自Short-circuit evaluation

答案 4 :(得分:3)

VB.Net具有不同的语法,具体取决于您是否希望它短路。由于遗留原因,默认行为是不短路。语法如下

非短路

IF A And B THEN
    ...
END IF

短路

IF A AndAlso B THEN
    ...
END IF

如果要短路OR语句,可以使用Or / OrElse。这在以下情况下非常好用

If MyObj IsNot Nothing AndAlso MyObj.Value < SomeValue Then
    ....
End If

就我个人而言,虽然我知道短路可以加快速度,但从查看代码来看,这绝对不是明显的。我可以看到一个没有经验的开发人员对这种行为感到困惑。它甚至可能发生或不会发生,取决于编译器标志的优化级别。我喜欢VB对于你真正想要实现的行为的详细说明。

答案 5 :(得分:2)

首先,你的朋友错了。大多数语言都提供短路评估(也称为最小评估),并且优于并行语言的嵌套ifs(在这种情况下,返回的第一个条件将导致执行继续)

在任何情况下,即使是一种简单的非并行语言,我也看不到嵌套ifs如何更快,因为执行会阻塞,直到第一个条件被评估。

答案 6 :(得分:1)

如果不停止,嵌套如何?实际上,如果a和b都是变量而不是带副作用的表达式,它们可以由一个好的编译器并行加载。除了增加行数之外,使用更多ifs没有任何好处。实际上,这将是第二次猜测编译器的最糟糕的一种。

这称为短路评估。

答案 7 :(得分:1)

我使用的有用短路是这样的:

if (a != null && a.equals(somevalue)) {
    ... do something.
}

在我看来,这是非常易读的,并且运行良好。一般来说,我也试图避免多次嵌套,因为它会导致丑陋的代码。

尽我所能。

答案 8 :(得分:1)

大多数语言都会对布尔表达式进行短路评估。我一直听说它被称为短路评估。

问题中的示例是一个非常简单的示例,它并没有真正提供很多性能优势。当表达式评估复杂时,性能优势就出现了。

作为一个很好的例子,可以想象一个类似于以下内容的游戏程序:

if (someObject.isActive() && someOtherObject.isActive() && CollisionDetection.collides(someObject, someOtherObject) {
  doSomething();
}

在这种情况下,碰撞检测比活动检查要昂贵得多。如果系统中存在大量非活动对象,则会显着提升性能。

答案 9 :(得分:1)

短路或最小评估只是嵌套ifs的语法糖。 假设效率低下或导致失速是过早优化的情况。 此时,大多数编译器都足够智能,可以正确地解释和优化这些语句。使用这些语句可以大大减少嵌套,从而提高代码可读性,这应该是您的首要目标。

答案 10 :(得分:1)

关于短路是否有效,流水线技术不太可能对性能产生太大影响。在可能产生影响的情况下,只要这些测试没有副作用,就没有什么能阻止编译器并行测试多个条件。此外,现代CPU有几种机制可用于提高分支代码的流水线性能。

嵌套ifs与短路&amp;&amp;。

具有相同的效果

'短路评估'是最常见的名称,而你的朋友对它的不常见是错误的;这很常见。

答案 11 :(得分:0)

根据具体情况,它也可以称为“守卫”。

而且我已经在几乎我所使用的每种语言中看到过它 - 它推动了近十几种语言。

答案 12 :(得分:0)

我对流水线技术一无所知,但短路评估是许多语言的共同特征(这也是我所知道的名称)。在C,&amp;&amp;而其他运营商定义sequence point就像;运算符确实如此,所以我看不出短路评估的效率如何低于仅仅使用多个语句。

答案 13 :(得分:0)

我只是听说它是短路的。在一个管道中,下一个进入的操作取决于if语句的结果?如果是这种情况,这将更加优化,因此每次都不必测试两个值。

答案 14 :(得分:0)

单个线程是顺序的,所以如果你有两个ifs,第一个当然会在第二个之前进行评估,所以我看不出有什么区别。我使用条件AND运算符(这是&amp;&amp;&amp;被称为afaik)比嵌套ifs更多。如果我想检查一些可能需要一段时间来评估的东西,我会先进行更简单的测试,然后再进行更有条理的测试。

a = obj.somethingQuickToTest() && obj.somethingSlowToTest();

似乎没有任何不同

a = false;
if(obj.somethingQuickToTest())
   a = obj.somethingSlowToTest();