简体   繁体   中英

Javascript: Why is my optimized loop slower than the more naive one

Link to jsperf if you prefer its formatting : https://jsperf.com/test-array-vs-loop-vs-loop-optimized

I was trying an old jsperf loop vs filter, and I tried to optimize the loop by preallocating the array if a correct size and avoiding item length recalculation. Issue is it didn't run faster on my Chrome 60.

Here is the code :

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];
    }
}

Edit : The results were about 39,281 ops/sec for normal loop, and 37,389 ops/sec for "optimized" loop. On i7 3610QM.

I tried to optimize the loop by preallocating the array if a correct size

But you failed at that. The filter result usually doesn't have the same size as the input. By not appending to the array at its end (using push ) and assigning to the index i always, you even were creating a sparse array. (Given your very small sample, it didn't have a large impact at least).

A correct approach might be

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;
}

…and avoiding item length recalculation

That's a trivial optimisation that the JS engine does figure out to apply by itself. Accessing .length isn't really slow actually. Unless there's something weird going on, you won't benefit from spelling this out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM