在if语句中选择正确的条件

Choosing right condition in if statement

本文关键字:条件 选择 if 语句      更新时间:2023-09-26

假设我有这样的代码:

if (a == 'something') {
  doA();
} else {
  doB();
}

我主要关心的是性能。如果在大多数(几乎99%)情况下,a不等于'something',我需要反转条件和块吗?

if (a != 'something') {
  doB();
} else {
  doA();
}

你有一个条件来决定只有两种可能的结果truefalse。在这种情况下,你什么也做不了。

如果你有一些像下面的场景:

if (a == 'something') {
  doA();
} else if (a == 'something else') {
  doB();
} else if (a == 'something else else') {
  doC();
} else {
  doD();
}

如果你说条件a == 'something else else'在大多数情况下都为真,那么你应该把它移到顶部这个micro optimization是有意义的

但是在现有的例子你有最小的代码需要执行

引擎会比你做得更好。我发现很难相信这就是代码中的瓶颈所在。侧写师是这么说的吗?

有一个"分支预测"的概念,其中引擎决定哪个选项更有可能,并组织机器码,以便代码在更常见的情况下失败,仅在不太常见的情况下使用JMP。

然而,即使在没有这种优化的情况下,假设代码是由引擎优化的,这两种情况下的差异很可能在几十纳秒的水平上,即使代码由于某种原因没有优化,并且正在"解释",差异也将以微秒为单位进行测量。如果每个页面视图包含十个这样的条件语句,那么每天服务器上的额外负载可能是几十秒的CPU时间。

在考虑此问题或进行基准测试时,请注意,根据评估条件所需时间的差异,可能存在差异。例如,!b的计算时间要比b长。如果你能找到一种方法来优化比较——因为字符串比较可能比数值比较更昂贵——这可能会给你带来一些好处。

不,你不需要。if只是一个条件语句,无论如何,代码都需要选择它是真还是假;

没有任何改进,因为您将在任何情况下执行检查条件,并采取各自的分支之一。

如果你有几个if条件,一个(不相关的)建议是这样写:
if ('something' == a) {
  doA();
} else {
  doB();
}

这是因为很容易将a = 'something'设置为相等,并且它将被视为赋值。

下面是如何快速测试的方法。通过使用JSFiddle和Chrome进行快速测试,我有时(但不是始终)发现反转条件节省了一些时间(我最初得到的时间是11.6s对6.7s),但它可能是平台相关的和/或依赖于doSomething函数。

如果这是客户端代码,那么它不太可能对性能产生明显的影响,除非对每个用户运行相同的决策数千或数百万次。

function doSomething() {
    document.getElementById('test').innerHTML = parseInt(Math.random()*10);
}
function doSomethingElse() {
    document.getElementById('test2').innerHTML = parseInt(Math.random() * 10);
}
function normal(x) {
    if (x == true) {
        doSomething();
    } else {
        doSomethingElse();
    }
}
function inverted(x) {
    if (x != true) {
        doSomethingElse();
    } else {
        doSomething();
    }
}
function callFunc(func, repetitions) {
    var p;
    for (var i = 0; i < repetitions; i++) {
        p = Math.random() > .99;
        func(p);
    }
}
var reps = 1000000;
console.time('normal');
callFunc(normal, reps);
console.timeEnd('normal');
console.time('inverted');
callFunc(inverted, reps);
console.timeEnd('inverted');

JSFiddle

大多数答案都有正确的结论和错误的推理。

if (condition) {
   // do X
} else {
   // do something that takes exactly the same amount of time as X
}

condition为真时的性能与当condition为假时的性能完全不同。如何和为什么取决于执行指令的机制,一直到微处理器——这使得我们在谈论一种在网络浏览器中解释的语言时很难进行准确的讨论。

幸运的是不重要。编译器、运行时引擎,甚至微处理器本身都可以精确地处理这种级别的优化,因为(a)人工不可能做到这一点,(b)从长远来看,这样做的尝试很可能适得其反。这个——而不是代码运行的频率——是什么让它成为一个不值得花时间的微优化。