typescriptperformancetsconfig

Performance implications of iterating over set with --downlevelIteration - is a new array always created?


For example with

for (const el of mySet) {

}

when compiling with --downLevelIteration (for a target that requires --downLevelIteration to work), does this always result in a new array being created (and garbage-collected) under the hood?

If so, does this incur a drastic performance hit in modern browsers, when iterating over the same set thousands of times (for example inside a second for loop)?


Solution

  • Why not compare the compiled outputs to make a determination?

    When given your example code as an input with downlevelIteration enabled:

    declare const mySet: Iterable<unknown>;
    
    for (const el of mySet) {}
    

    The compiled JavaScript produced for the target set to "ES2015" is:

    Playground

    "use strict";
    for (const el of mySet) { }
    

    In comparison: setting the target to "ES5" produces:

    Playground

    "use strict";
    var __values = (this && this.__values) || function(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };
    var e_1, _a;
    try {
        for (var mySet_1 = __values(mySet), mySet_1_1 = mySet_1.next(); !mySet_1_1.done; mySet_1_1 = mySet_1.next()) {
            var el = mySet_1_1.value;
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (mySet_1_1 && !mySet_1_1.done && (_a = mySet_1.return)) _a.call(mySet_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    

    does this always result in a new array being created?

    A new array is not created in either case.

    When selecting a target equal to or newer than ES2015, there is no generated compatibility code. Currently maintained browsers should all provide an environment with coverage support of much newer ECMAScript standards than ES2015, so I don't think you should have any concern unless you're targeting an obscure/ancient/unsupported browser.