for vs iterators vs generators

JavaScript performance comparison

Revision 2 of this test case created by Andy Wingo

Info

Tests how well current JS engines do with iterators, like those in the proposed ES6 and those in Dart. The "closure" tests are designed to simulate the costs of generators, but don't do a very good job.

ITERATIONS is set to 1e6, so the Ops/sec measurements below correspond to millions of iterations per second. In theory a 2.5 GHz processor should be able to do about 1000 Ops/sec.

Preparation code

 
<script>
Benchmark.prototype.setup = function() {
    function integers_from(n) {
      function next() {
        return this.n++;
      }
      return { n: n, next: next };
    }
   
    function closure_integers_from(n) {
      function next() {
        return n++;
      }
      return { next: next };
    }
   
    function StopIteration() {}
    function isStopIteration(x) { return x === StopIteration; }
   
    function take_n(iter, max) {
      function next() {
        if (this.n++ < max)
          return iter.next();
        else
          throw StopIteration;
      }
      return { n: 0, next: next };
    }
   
    function closure_take_n(iter, max) {
      var n = 0;
      function next() {
        if (n++ < max)
          return iter.next();
        else
          throw StopIteration;
      }
      return { next: next };
    }
   
    function fold(f, iter, seed) {
      var elt;
      while (1) {
        try {
          elt = iter.next();
        } catch (e) {
          if (isStopIteration (e))
            break;
          else
            throw e;
        }
        seed = f(elt, seed);
      }
      return seed;
    }
   
    function dart_integers_from(n) {
      function moveNext() {
        this.current++;
        return true;
      }
      return { current: n-1, moveNext: moveNext };
    }
   
    function dart_take_n(iter, max) {
      function moveNext() {
        if (this.n++ < max && iter.moveNext()) {
          this.current = iter.current;
          return true;
        }
        else
          return false;
      }
      return {
        n: 0,
        current: undefined,
        moveNext: moveNext
      };
    }
   
    function dart_fold(f, iter, seed) {
      while (iter.moveNext())
        seed = f(iter.current, seed);
    }
   
    function sum(a, b) { return a + b; }
   
    var _ = 0;
    var ITERATIONS = 1000000
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
loop sum (baseline)
_ = 0;
var i;
var n = 0;
for (i = 0; i < ITERATIONS; i++)
  _ += n++;
 
pending…
loop sum with es6-style iterators
_ = 0;
var iter = take_n(integers_from(0), ITERATIONS);
var elt;
while (1) {
  try {
    elt = iter.next();
  } catch (e) {
    if (isStopIteration(e))
      break;
    else
      throw e;
  }
  _ += elt;
}
 
pending…
loop sum with dart-style iterators
_ = 0;
var iter = dart_take_n(dart_integers_from(0), ITERATIONS);
while (iter.moveNext())
  _ += iter.current;
 
pending…
loop sum with closure iterators (approximation of generators)
_ = 0;
var iter = closure_take_n(closure_integers_from(0), ITERATIONS);
var elt;
while (1) {
  try {
    elt = iter.next();
  } catch (e) {
    if (isStopIteration(e))
      break;
    else
      throw e;
  }
  _ += elt;
}
pending…
fold sum with es6-style iterators
_ = fold(sum, take_n(integers_from(0), ITERATIONS), 0);
 
pending…
fold sum with dart-style iterators
_ = dart_fold(sum, dart_take_n(dart_integers_from(0), ITERATIONS), 0);
 
pending…
fold sum with closures
_ = fold(sum, closure_take_n(closure_integers_from(0), ITERATIONS), 0);
 
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment