我在js中处理大数组时发现了一些意想不到的结果。在我的测试中,我使用for循环创建了一些类实例的大数组,并且在循环内我将相同的字符串分配给所有对象" x"属性和数组初始化后用这个数组做一些计算。如果构造函数初始化" x" null属性,数组总是处理得更好,即使它做了额外的声明。为什么会这样? 这是我的测试代码。我在chrome上测试过。
function f1() {
var P = function () {
this.value = 1
};
var big_array = new Array(10000000).fill(1).map((x, index)=> {
p = new P();
if (index > 5000000) {
p.x = "some_string";
}
return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0);
}
function f2() {
var P = function () {
this.value = 1;
this.x = null;
};
var big_array = new Array(10000000).fill(1).map((x, index)=> {
p = new P();
if (index > 5000000) {
p.x = "some_string";
}
return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0);
}
(function perform(){
var start = performance.now();
f1();
var duration = performance.now() - start;
console.log('duration of f1 ' + duration);
start = performance.now();
f2();
duration = performance.now() - start;
console.log('duration of f2 ' + duration);
})()
输出:
duration of f1 14099.85
duration of f2 11694.175000000001
答案 0 :(得分:3)
在我的Firefox浏览器中,f2
的运行速度比f1
大约快4倍。原因是Just-in-Time JavaScript编译器试图根据预期的对象结构优化代码。正如mdn
所述:
幸运的是,对象和属性通常是“可预测的”,在这种情况下,它们的底层结构也是可预测的。 JIT可以依靠它来更快地进行可预测的访问。
如果属性在对象构造函数中被“声明”,那么这个预测当然会更好地工作,这是优化器寻找它的神奇之处。
假设一个结构,“后来”仍然添加一个属性会变得更加昂贵。
但是,有不同的引擎,它们有不同的优化器,所以这个结果在不同的浏览器上可能会有很大不同。但是,在构造函数中包含属性的定义似乎是一种好的做法,即使它们的值尚未知晓。
这将为那些从中受益的引擎带来改进,并且不会在其他引擎上带来大部分性能成本。此外,它还可以提高代码的可读性。
我在Windows 10,FF 47.0和Chrome 51.0.2704.106上进行了测试,得到了以下结果:
FireFox Chrome
--------------------------
f1 6,400 11,400
f2 1,700 9,600
这是几次运行的平均值。
答案 1 :(得分:0)
毫不奇怪,我和我之间没有(或很少)性能差异。这是我得到的结果......
duration of f1 11782.384999999951
duration of f2 11347.524999999965
如果你在浏览器控制台中试过它,&只进行过一次测试,f2可能会针对该特定测试稍微调整一下。