if(var == true)是否比if(var!= false)更快?

Blo*_*ust 21 c# optimization conditional if-statement boolean

非常简单的问题.我知道这可能是一个很小的优化,但最终你会使用足够的if语句来解决它.

编辑:谢谢那些提供答案的人.

对于那些觉得需要打击我的人,要知道好奇心和对知识的渴望并不能转化为愚蠢.

非常感谢所有提出建设性批评的人.直到现在我才知道if(var)的能力.我确定我现在会用它.;)

Eri*_*ert 69

首先:回答性能问题的唯一方法是测量它.亲自尝试,你会发现.

至于编译器的作用:我提醒你"if"只是一个条件goto.当你有

if (x)
   Y();
else
   Z();
Q();
Run Code Online (Sandbox Code Playgroud)

编译器将其生成为:

evaluate x
branch to LABEL1 if result was false
call Y
branch to LABEL2
LABEL1:
call Z
LABEL2:
call Q
Run Code Online (Sandbox Code Playgroud)

要么

evaluate !x
branch to LABEL1 if result was true
Run Code Online (Sandbox Code Playgroud)

取决于是否更容易生成代码以引出"x"恰好是"正常"或"反转"结果.例如,如果你有if (a<=b)它可能更容易生成它(if !(a>b)).或相反亦然; 这取决于正在编译的确切代码的细节.

无论如何,我怀疑你有更大的鱼要炸.如果您关心性能,请使用分析器找到最慢的东西,然后解决它.当你可能在程序中的其他地方浪费整整毫秒时,毫无意义地担心纳秒优化.

  • "使用分析器" - 如此真实.我无法计算我已经"知道"了多少次性能问题,只是因为运行的配置文件显示错误. (13认同)
  • @Theo:"科学"什么时候变成"不做任何测量或观察,只是在脑海中推理并希望得到正确答案?" 这就是亚里士多德写"物理学"时的科学,亚里士多德认为女性的牙齿少于男性.不是因为他通过测量来发现它,而是因为*逻辑上*女性的牙齿必须少于男性.我不明白你在科学和工程学之间所做的区别,但我向你保证,如果不测量它,你就无法确定哪两件事情更快. (10认同)
  • 我不仅怀疑,我会说它接近数学上的确定性,你有更大的鱼要炸. (3认同)

Jon*_*nna 42

您是否知道在x86处理器上x ^= x,x比32位整数更有效率x = 0呢?这是真的,当然也有相同的结果.因此,任何人都可以x = 0在代码中看到,可以用代替它x ^= x并获得效率.

现在,你见过x ^= x很多代码吗?

你没有的原因不仅仅是因为效率增益很小,而是因为这正是编译器(如果编译为本机代码)或抖动(如果编译IL或类似代码)会产生的那种变化.反汇编一些x86代码,看到程序集等效的并不罕见x ^= x,虽然为此编译的代码几乎肯定有x = 0或者可能更复杂的代码,x = 4 >> 6或者x = 32 - y代码分析显示此时y总是包含的代码32,以及等等.

出于这个原因,即使x ^= x已知效率更高,但它在绝大多数情况下的唯一影响是使代码的可读性降低(唯一的例外x ^= y是在使用的算法中需要做的事情和我们碰巧做了一个案例,在这里xy在这里相同,在这种情况下x ^= x会使该算法的使用更加清晰而x = 0隐藏它).

在99.999999%的案例中,同样适用于您的示例.在剩余的0.000001%的情况下,它应该存在但是在某些奇怪的运算符覆盖之间存在效率差异,并且编译器无法将其中一个解析为另一个.事实上,0.000001%是夸大案件,刚才提到因为我很确定如果我努力了,我可以写一些效率低于另一个的东西.通常人们并不努力这样做.

如果您在反射器中查看自己的代码,您可能会发现一些与您编写的代码看起来非常不同的情况.这样做的原因是,它是反向工程代码的IL,而不是你的代码本身,确实有一件事你会经常发现是类似的东西if(var == true)或者if(var != false)正在变成if(var)甚至到if(!var)ifelse块反转.

看得更深,你会发现即使是进一步的改变,也有不止一种方法可以让同一只猫皮肤光滑.特别是,查看switch语句转换为IL的方式很有意思; 有时候它变成了一堆if-else if语句的等价物,有时它变成了一个可以进行跳转的表的查找,这取决于在所讨论的情况下看起来更有效.

查看更深入,并在编译为本机代码时进行其他更改.

我不同意那些谈论"过早优化"的人只是因为你询问两种不同方法之间的性能差异,因为对这种差异的了解是一件好事,它只是过早地使用这种知识是不成熟的(通过定义).但是,即将被编译出来的变化既不是过早的,也不是优化,它只是一个零变化.

  • `你知道在x86处理器上做x ^ = x更有效率,其中x是32位整数.现在不再是这种情况了.`mov ax,0`是一个较小的指令,没有`xor ax,ax`的副作用,甚至那时处理器已经进入了mov命令刚刚更快的阶段. (3认同)
  • 好吧,我不必知道这不再是这个案例支持我的主要观点:) (2认同)

jms*_*era 18

它根本不会有任何区别.使用反射器你可以看到代码:

private static void testVar(bool var)
{
    if (var == true)
    {
        Console.WriteLine("test");
    }

    if (var != false)
    {
        Console.WriteLine("test");
    }

    if (var)
    {
        Console.WriteLine("test");
    }
}
Run Code Online (Sandbox Code Playgroud)

创建IL:

.method private hidebysig static void testVar(bool var) cil managed
{
  .maxstack 8
  L_0000: ldarg.0 
  L_0001: brfalse.s L_000d
  L_0003: ldstr "test"
  L_0008: call void [mscorlib]System.Console::WriteLine(string)
  L_000d: ldarg.0 
  L_000e: brfalse.s L_001a
  L_0010: ldstr "test"
  L_0015: call void [mscorlib]System.Console::WriteLine(string)
  L_001a: ldarg.0 
  L_001b: brfalse.s L_0027
  L_001d: ldstr "test"
  L_0022: call void [mscorlib]System.Console::WriteLine(string)
  L_0027: ret 
}
Run Code Online (Sandbox Code Playgroud)

因此编译器(在.Net 3.5中)将它们全部转换为ldarg.0,brfalse.s指令集.


Mic*_*tta 11

无论您在程序中使用多少次迭代,都不会产生任何可测量的差异.

(if (var)改为使用;您不需要比较的视觉混乱.)

  • @Graphain,我几乎肯定更喜欢`if(var)`假设`var`被明智地命名以立即表明它是一个布尔值,它是什么意思.实际上,如果`if(var == true)`更具可读性,我会说bool的名称有问题. (2认同)

EMP*_*EMP 11

它将使绝对零差异,因为编译器几乎肯定会将两个语句编译为相同的二进制代码.

(伪)程序集将是:

test reg1, reg2
br.true somewhere
; code for false case

somewhere:
; code for true case
Run Code Online (Sandbox Code Playgroud)

要么

test reg1, reg2
br.false somewhere
; code for true case

somewhere:
; code for false case
Run Code Online (Sandbox Code Playgroud)

编译器选择哪一个不取决于你是否写== true!= false.相反,它是编译器根据真假案例代码的大小以及其他一些因素进行的优化.

顺便说一句,在Linux内核代码实际上并尝试使用这些分支,以优化LIKELYUNLIKELY宏的if条件,所以我想这可以手动控制.


jal*_*alf 8

通常有效的经验法则是"如果你知道它们做同样的事情,那么编译器也会知道".

如果编译器知道两个表单产生相同的结果,那么它将选择最快的一个.

因此,假设它们同样快,直到你的探查器告诉你.


Sor*_*gal 5

始终优化以便于理解.就我而言,这是编程的基本规则.知道需要这样做之前,您不应该进行微观优化,甚至根本不进行优化,以及您需要这样做的地方.这是一个非常罕见的情况,挤出每一盎司的性能比可维护性更重要,甚至更难以让你知道在最初编写代码时优化的地方.

此外,这样的事情会以任何体面的语言自动优化.

tl;博士不要打扰