?: 运算符与 if 语句的性能比较

33

我一直在尝试优化我的代码,使其更加简洁和易读,并希望这样做不会导致性能下降。我认为我的更改可能会使我的应用程序变慢,但这可能只是我自己的想法。以下两种方式之间有任何性能差异吗:

Command.Parameters["@EMAIL"].Value = email ?? String.Empty;

以及

Command.Parameters["@EMAIL"].Value = (email == null) ? String.Empty: email;

if (email == null)
{
    Command.Parameters["@EMAIL"].Value = String.Empty
}
else
{
    Command.Parameters["@EMAIL"].Value = email
}

从易读性的角度考虑,我更喜欢使用 null 合并运算符,只是我不希望它影响性能。

7个回答

72

你正在尝试进行微观优化,这通常是不可取的。除非您有性能分析显示这是一个问题,否则甚至不值得更改。

对于一般用途,正确的答案是任何易于维护的方法。

然而,空合并运算符的IL代码如下:

L_0001: ldsfld string ConsoleApplication2.Program::myString
L_0006: dup 
L_0007: brtrue.s L_000f
L_0009: pop 
L_000a: ldsfld string [mscorlib]System.String::Empty
L_000f: stloc.0 

而 switch 的 IL 如下:

L_0001: ldsfld string ConsoleApplication2.Program::myString
L_0006: brfalse.s L_000f
L_0008: ldsfld string ConsoleApplication2.Program::myString
L_000d: br.s L_0014
L_000f: ldsfld string [mscorlib]System.String::Empty
L_0014: stloc.0 

对于null coalescing operator,如果该值为null,则执行六个语句,而使用switch则执行四个操作。
在不是null值的情况下,null coalescing operator执行四个操作,而不是五个操作。
当然,这假设所有IL操作所需的时间相同,但事实并非如此。
无论如何,希望您能看到如何在微观层面上进行优化会很快地减少回报。
话虽如此,在大多数情况下,无论哪种方法最容易阅读和维护都是正确的答案。
如果您发现在某些情况下效率低下(这种情况很少见),那么您应该衡量哪种具有更好的性能,然后进行特定的优化。

'L_0006: dup' - 在这里为什么需要dup?展示了我的无知。 - Sean Bright
3
当方法被JIT编译时,它很可能会被内联,对吧? - JoshBerke
@JoshBerke:这取决于情况;我不认为代码内联的条件是绝对的(尽管我确信有一些硬性条件,比如虚拟方法不能或不会被内联),所以我无法确定。 - casperOne
IL代码并不是最终的本地代码,最终会被CPU执行。 - Johan Boulé
@JohanBoule 同意,但在 JIT 接管之前,这是你能得到的最接近的结果。 - casperOne
显示剩余3条评论

69

我认为,应该优化代码的可读性和易懂性-与在运行时获得的性能提升相比,当你在几个月后回到这段代码并试图理解你最初想做什么时,节约的时间可能是微不足道的。


13
当然,要记住许多程序员可以像读普通的if语句一样快速地阅读三目运算符。在某些情况下,使用没有大括号的if / else语句甚至比使用if / else语句更清晰。 - NotMe
1
我同意。这里很多帖子都是关于性能的问题,询问微小的调整(++ 比 +=1 快吗?),但其实并不重要。速度来自于算法复杂度:减少大量的内存拷贝、快速搜索容器、适当地进行哈希。微小的调整不会对性能产生影响。 - abelenky
10
chublogga的观点都是真实、有效且措辞得当的,但它们并没有回答原始问题。OP是成年人,可以自己选择架构/可读性选项,而casperOne的答案则更直接而有趣地回答了关于性能的具体问题。 - nezroy
1
我没有回答原始问题,因为那个问题本来就是错误的。 - PhilChuang
1
难道我们不能安全地假设,如果人类能够看到显而易见的事情,编译器也足够聪明,能够看到并超越这些吗? - Ustaman Sangat
我个人认为合并运算符更快、更容易,但这只是我的看法。三元运算符也是如此。 - chris c

18

我认为我的修改可能会降低应用程序的速度,但这只是我自己的想法。

除非您实际上进行了性能测试,否则一切都只是您的猜测而已。

(不是特别针对您,但看到问题和回答中缺少“ 测量”这个词,关于性能微优化的问题越来越多,真是让人失望。)


7
我怀疑这不会有任何性能差异。
此外,我想知道为什么你会担心在这种情况下偏爱一个语句而不是另一个?我的意思是:如果有任何影响,性能影响将是微不足道的。在我看来,这将是一种微观优化,不值得花费精力。我会选择最易读、最清晰的语句,不用担心性能问题,因为它的影响很小(在这种情况下)。

1
它最初的编写方式是一堆if语句,当我进行更改时,似乎程序的性能有所下降。也许这只是个例外,但这引起了我更大的兴趣。 - Jon

7
在这种情况下,几乎没有显著的性能差异。当性能差异可以忽略不计时,一切都与易读的代码有关。

1
我想更精确地表达:“在没有明显性能差异的情况下,一切都取决于可读性。”有时,确实存在性能差异,而且有时这种差异是显著的,在这种情况下,可读性可能会被搁置。 - phoog
1
那跟我说的有什么不同吗? - Chris Ballance
@chris-ballance 显然不同之处在于人们强调的位置不同。 - Johan Boulé

2

为了讨论...如果/那么/否则语句和三目运算符的速度与单级switch/case语句一样快。

这里是一些使用C#代码进行的性能基准测试。

只有当你开始在case语句中嵌套2-3个级别时,性能才会受到严重影响。也就是说,像这个荒谬的例子:

switch (x % 3)
    {
        case 0:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
        case 1:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
    case 2:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
    default:
        switch (y % 3)
        {
            case 0: total += 3;
                break;
            case 1: total += 2;
                break;
            case 2: total += 1;
                break;
            default: total += 0;
                break;
        }
        break;
    }

1

这是一个关于机器级代码是否高效或人类可读代码的问题。我们让它更易读,这使得机器需要复杂地解释代码,反之亦然...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接