【问题标题】:Is there any performance difference between the following two cases?以下两种情况是否有性能差异?
【发布时间】:2011-09-25 03:00:16
【问题描述】:

以下两种情况是否存在性能差异:
第一:

int test_some_condition(void);

if( some_variable == 2 && test_some_condition())
{
    //body
}

第二:

int test_some_condition(void);

if( some_variable == 2 )
{
    if(test_some_condition())
    {
        //body
    }
}

更新:我知道如何创建测试并测量每个案例的性能或查看为每个案例生成的程序集,但我确信我不是第一个遇到这个问题的人,如果已经测试过的人可以是我一个简单的是/否答案。

【问题讨论】:

  • 设身处地为编译器编写者着想。你将如何实现&&
  • 将每个测试运行几百万次并测量时间以找出答案。编译两者并使用objdump查看生成的汇编程序@
  • 多一层缩进通常不值得提高性能,即使存在差异。

标签: c performance if-statement micro-optimization short-circuiting


【解决方案1】:

有什么区别?

可读性?是的,有区别。第一个更清晰,更好地表达了您的意图。而且它在编辑器中占用的行数也更少,这本身并不一定是一个优势,但它确实使代码更容易阅读和理解,任何落后并想要编辑它的人一目了然。

性能/“速度”?不。我愿意用实际的钱打赌,一旦您通过打开优化的编译器运行这两个 sn-ps 代码,绝对没有明显的区别。即使优化禁用,也无需花费太多时间来说服我押注相同的案例。

为什么?因为在 C(以及我所知道的所有 C 派生语言)中,&& 运算符执行 短路评估,这意味着如果第一个条件评估为假,那么它不会'甚至懒得去评估第二个条件,因为整个陈述不可能永远是真的。

And 运算符不执行短路评估时,嵌套if 语句是VB 6 糟糕的旧时代常见的“优化”技巧。我无法想象在 C 代码中使用它的目的,除非它增强了可读性。老实说,如果您遇到的编译器渲染这两个代码 sn-ps 在性能方面完全等效,那么是时候扔掉该编译器并停止使用它了。这是最基础的优化,是编译器编写者的“唾手可得的果实”。如果他们做不到这一点,我不会信任他们处理你的其余代码。

但是,总的来说,担心这类事情(肯定属于“微优化”的范畴)并不能帮助您编写更好的代码或成为更好的程序员。这只会让您浪费大量时间在 Stack Overflow 上提问,并为像我这样每周对 2 到 3 个类似问题发布相同答案的用户的声誉做出贡献。那是您花费在编写代码和以切实的方式提高技能的时候了。

【讨论】:

    【解决方案2】:

    任何人都可以通过现代编译器真正分辨的唯一方法是查看机器代码。

    【讨论】:

      【解决方案3】:

      应该没有区别。 如果存在差异,则可能无法衡量(即使您这样做了数百万次,也不会得到确凿的结果)。

      【讨论】:

        【解决方案4】:

        在运行 10.000.000 次的循环中测试这两个示例给出:

        $ time ./test1
        
        real    0m0.045s
        user    0m0.044s
        sys     0m0.001s
        
        $ time ./test2
        
        real    0m0.045s
        user    0m0.043s
        sys     0m0.003s
        

        另外,请记住,如果表达式的第一部分失败,则永远不会计算第二个表达式。这在第一个示例中可能不太清楚。

        此外,在第一个求值表达式返回 false 的情况下:

        $ time ./test1_1
        
        real    0m0.035s
        user    0m0.034s
        sys     0m0.001s
        $ time ./test2_1
        
        real    0m0.035s
        user    0m0.034s
        sys     0m0.000s
        

        【讨论】:

        • 所以,等价的。小心不要让像这样的合成“基准”产生误导。请原谅我的无知,但什么是“真实”、“用户”和“系统”?
        • 基准测试并不意味着什么,只是一个指标,如果一种方法比另一种更快。 file 有一个手册页。 Real 是经过的秒数,user 是在用户模式下花费的时间,sys 是在内核模式下花费的时间
        【解决方案5】:

        如果你在想第一个版本是否总是调用test_some_condition 但第二个版本只有在第一个条件为真时才调用它,那么答案是两个版本是等价的,因为 AND 运算符是惰性的,将如果第一个参数已经为假,则不评估它的第二个参数。

        标准保证了这种行为。这使得这样说是合法的:

        if (array_size > n && my_array[n] == 1) { ... }
        

        如果没有惰性保证,这将是损坏的代码。

        【讨论】:

          【解决方案6】:

          这两个样本在逻辑上是等价的,前提是复合条件是惰性求值的,这意味着在a && b 中,当a 已知为假时,b 不会被求值。因此,即使存在差异,我也不会在意,因为这可能是您正在使用的编译器的人工制品(或错误),并且可能会随着下一个版本或错误修复而改变。

          【讨论】:

            猜你喜欢
            • 2023-01-25
            • 2011-12-03
            • 1970-01-01
            • 2021-09-27
            • 2020-09-15
            • 2014-12-22
            • 2013-07-05
            • 1970-01-01
            • 2023-03-16
            相关资源
            最近更新 更多