我正在做一些基准测试,发现一些荒谬的结果,我似乎无法解释。
const a = undefined;
const b = {};
// add tests
suite
.add('Undefined variable', function () {
if(a > 0){
return true;
}
else{
return false;
}
})
.add('Undefined property', function () {
if(b.a > 0) {
return true;
}
else{
return false;
}
})
测试结果:
Undefined variable x 69,660,401 ops/sec ±2.48% (36 runs sampled)
Undefined property x 994,939,175 ops/sec ±0.85% (40 runs sampled)
Test Results
--------------------------------------------------------------------------
Undefined property : 994939174.67 ops/sec (+1328.27 %)
Undefined variable : 69660400.51 ops/sec ( +0.00 %)
--------------------------------------------------------------------------
有人知道为什么第一种情况Undefined variable
比另一种慢得多吗?我在jsbench测试中发现了类似的性能结果:https://jsbench.me/vdku4ert4l/2
(这里是V8开发人员)
比较undefined > 0
总是具有相同的性能。这里的差别是,在你的情况下,V8可以优化掉比较:像b.a
属性访问,它记得隐藏类的对象(s)(即b
的值);这就是"内联缓存"技术的关键思想。
V8将这个想法更进一步:如果所有遇到的对象都有相同的隐藏类,并且该隐藏类没有a
属性,那么当该函数得到优化时,V8会考虑到这一经验并生成优化的代码,并假设将来仍然会出现这种情况,在这种情况下,它可以不断地减少属性加载和比较。换句话说,它将该函数优化为:
function undefined_property_optimized() {
(if b.__hidden_class__ !== kPreviousHiddenClass) Deoptimize;
return false;
}
其中Deoptimize
的意思是:扔掉这个优化过的代码,回到这个函数的未优化代码(当然,在正确的点恢复执行)。
第一个测试
Undefined variable
被严重减慢
不,它不是被放缓。其他案件"cheating",所以说话。
添加
const b = { a: undefined };
不会改变任何东西
这实际上在很大程度上取决于你如何准确地运行测试。在本地测试,少量修改我力引擎,这要么没有影响,要么使两个函数相等的速度。
经验法则#1:当你运行一个微基准测试时,你看到每秒数亿次的操作,那么优化编译器能够优化掉几乎所有的东西,你正在测试一个空的(或微不足道的)函数。
经验法则#2:微基准测试的结果很难正确解释。您可能认为您在这里测量的是属性负载,或者> 0
比较;这两个假设都是不正确的:在更快的情况下,没有加载属性,也没有执行> 0
比较。为了理解微基准测试,你真的需要研究生成的机器代码(和/或其他引擎内部),以确保它在测试你认为它在测试的东西。
经验法则#4:微基准测试的结果几乎不会影响到现实世界的代码——主要是因为上面的三条规则:-)
边注:当你发现自己在写:
if (some_condition) {
return true;
} else {
return false;
}
那么你可以用return some_condition
替换它。可能不会更快,但使您的代码更短。