Javascript:为什么我的优化循环比更幼稚的循环慢

Javascript:为什么我的优化循环比更幼稚的循环慢,javascript,arrays,performance,loops,Javascript,Arrays,Performance,Loops,如果您喜欢jsperf的格式,请链接到jsperf: 我尝试了一个旧的jsperf循环vs过滤器,我试图通过预先分配数组(如果大小正确)和避免重新计算项目长度来优化循环。问题是它在我的Chrome 60上没有运行得更快 代码如下: var items = []; var names = ['george', 'nick', 'jack', 'herodotus', 'joanne']; for (var i = 0; i < 2000; i++) { var obj = {

如果您喜欢jsperf的格式,请链接到jsperf:

我尝试了一个旧的jsperf循环vs过滤器,我试图通过预先分配数组(如果大小正确)和避免重新计算项目长度来优化循环。问题是它在我的Chrome 60上没有运行得更快

代码如下:

var items = [];
var names = ['george', 'nick', 'jack', 'herodotus', 'joanne'];
for (var i = 0; i < 2000; i++) {
    var obj = {
        name: names[i % 5] + '-' + i,
        age: i % 10 + 15
    };
    items.push(obj);
}

function filter_callback(item) {
    return (item.age == '18');
}

function test_filter() {
    var aged_18_filter = items.filter(filter_callback);
}

function test_loop() {
    var aged_18_loop = [];
    for (var i = 0; i < items.length; i++) {
        if (items[i].age == '18') aged_18_loop.push(items[i]);
    }
}

function test_loop_optimized() {
    var length=items.length
    var aged_18_loop = new Array(length);
    for (var i = 0; i < length; i++) {
        if (items[i].age == '18') aged_18_loop[i]=items[i];
    }
}
编辑:正常循环的结果约为39281次/秒,优化循环的结果约为37389次/秒。在i7 3610QM上

我试图通过预先分配数组(如果大小正确)来优化循环

但是你失败了。过滤结果通常与输入大小不同。通过不使用push在数组末尾追加并分配给索引i always,您甚至创建了一个稀疏数组。考虑到你的样本很小,至少没有太大的影响

正确的方法可能是

function test_loop_optimized() {
    var length = items.length;
    // let's guess that the result will have about a fifth of the size
    var result = new Array(Math.round(length / 5));
    var i = 0;
    var j = 0;
    while (i < length) {
        var item = items[i++];
        if (item.age == '18')
            result[j++] = item;
    }
    result.length = j; // just in case we guessed too high
    return result;
}
…并避免重新计算项目长度

这是一个微不足道的优化,JS引擎确实能够自行实现。访问。实际上,长度并不是很慢。除非有什么奇怪的事情发生,否则你将无法从解释中获益

我试图通过预先分配数组(如果大小正确)来优化循环

但是你失败了。过滤结果通常与输入大小不同。通过不使用push在数组末尾追加并分配给索引i always,您甚至创建了一个稀疏数组。考虑到你的样本很小,至少没有太大的影响

正确的方法可能是

function test_loop_optimized() {
    var length = items.length;
    // let's guess that the result will have about a fifth of the size
    var result = new Array(Math.round(length / 5));
    var i = 0;
    var j = 0;
    while (i < length) {
        var item = items[i++];
        if (item.age == '18')
            result[j++] = item;
    }
    result.length = j; // just in case we guessed too high
    return result;
}
…并避免重新计算项目长度


这是一个微不足道的优化,JS引擎确实能够自行实现。访问。实际上,长度并不是很慢。除非有什么奇怪的事情发生,否则你将无法从解释中获益。

我不明白你的优化是什么。提示:如果你试图过滤,新的Arraylength的大小是错误的,通过将其分配给老化的_18_循环[I],而不是数组的末端,你甚至可以创建一个带有孔的稀疏数组。我不认为那是你想要的。你得到了什么结果,你能把它们贴出来吗?我手边没有Chrome 60。谢谢,我现在完全明白了。正常环路的结果约为39281次/秒,优化环路的结果约为37389次/秒。在i7 3610QM上@swailem95我的上一个函数预先分配了循环,并使用var length而不是循环条件中的items.length。我不明白您的优化是什么。提示:如果您尝试进行筛选,则新Arraylength的大小错误,并且通过分配给老化的_18_循环[I]而不是数组的末尾,您甚至创建了一个带有孔的稀疏数组。我不认为那是你想要的。你得到了什么结果,你能把它们贴出来吗?我手边没有Chrome 60。谢谢,我现在完全明白了。正常环路的结果约为39281次/秒,优化环路的结果约为37389次/秒。在i7 3610QM上@swailem95我的上一个函数预先分配了循环,并在循环条件中使用了var length而不是items.length。