L2O class or functions

JavaScript performance comparison

Test case created by Matthew Podwysocki

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Class based
var inherits = function(child, parent) {
    function __() {
      this.constructor = child;
    }
    __.prototype = parent.prototype;
    child.prototype = new __();
    };

var Enumerator = (function() {
  function Enumerator() {
    this.current = null;
    this.done = false;
  }

  Enumerator.prototype.moveNext = function() {
    if (this.done) {
      return false;
    }
    var result = this._moveNext();
    if (!result) {
      this.done = true;
      this.dispose();
    }
    return result;
  };

  Enumerator.prototype.getCurrent = function() {
    return this.current;
  };

  Enumerator.prototype.dispose = function() {
    if (!this.done) {
      this._dispose();
      this.done = true;
    }
  };

  Enumerator.prototype._dispose = function() {}

  return Enumerator;
}());

var Enumerable = (function() {
  function Enumerable() {}

  Enumerable.prototype.filter = function(predicate, thisArg) {
    return new FilterEnumerable(this, predicate, thisArg);
  };

  Enumerable.prototype.forEach = function(action, thisArg) {
    var i = 0,
        e = this.getEnumerator();
    try {
      while (e.moveNext()) {
        action.call(thisArg, e.getCurrent(), i++, this);
      }
    } catch (ex) {
      throw ex;
    } finally {
      e.dispose();
    }
  };

  Enumerable.prototype.map = function(selector, thisArg) {
    return new MapEnumerable(this, selector, thisArg);
  };

  Enumerable.range = function(start, count) {
    return new RangeEnumerable(start, count);
  };

  return Enumerable;
}());

/* Map */

var MapEnumerable = (function(super_) {
  inherits(MapEnumerable, super_);

  function MapEnumerable(parent, selector, thisArg) {
    this.parent = parent;
    this.selector = selector;
    this.thisArg = thisArg;
  }

  MapEnumerable.prototype.getEnumerator = function() {
    return new MapEnumerator(this.parent, this.selector, this.thisArg);
  };

  return MapEnumerable;

}(Enumerable));

var MapEnumerator = (function(super_) {
  inherits(MapEnumerator, super_);

  function MapEnumerator(parent, selector, thisArg) {
    this.e = parent.getEnumerator();
    this.selector = selector;
    this.thisArg = thisArg;
    this.index = 0;
  }

  MapEnumerator.prototype._moveNext = function() {
    if (!this.e.moveNext()) {
      return false;
    }
    this.current = this.selector.call(this.thisArg, this.e.getCurrent(), this.index++, this.parent);
    return true;
  };

  MapEnumerator.prototype._dispose = function() {
    this.e.dispose();
  };

  return MapEnumerator;
}(Enumerator));

/* Filter */

var FilterEnumerable = (function(super_) {
  inherits(FilterEnumerable, super_);

  function FilterEnumerable(parent, predicate, thisArg) {
    this.parent = parent;
    this.predicate = predicate;
    this.thisArg = thisArg;
  }

  FilterEnumerable.prototype.getEnumerator = function() {
    return new FilterEnumerator(this.parent, this.predicate, this.thisArg);
  };

  return FilterEnumerable;

}(Enumerable));

var FilterEnumerator = (function(super_) {
  inherits(FilterEnumerator, super_);

  function FilterEnumerator(parent, predicate, thisArg) {
    this.e = parent.getEnumerator();
    this.predicate = predicate;
    this.thisArg = thisArg;
    this.index = 0;
  }

  FilterEnumerator.prototype._moveNext = function() {
    while (true) {
      if (!this.e.moveNext()) {
        return false;
      }
      var c = this.e.getCurrent();
      if (this.predicate.call(this.thisArg, c, this.index++, this.parent)) {
        this.current = c;
        return true;
      }
    }
  };

  FilterEnumerator.prototype._dispose = function() {
    this.e.dispose();
  };

  return FilterEnumerator;
}(Enumerator));

/* Range */

var RangeEnumerable = (function(super_) {
  inherits(RangeEnumerable, super_);

  function RangeEnumerable(start, count) {
    this.start = start;
    this.count = count;
  }

  RangeEnumerable.prototype.getEnumerator = function() {
    return new RangeEnumerator(this.start, this.count);
  };

  return RangeEnumerable;

}(Enumerable));

var RangeEnumerator = (function(super_) {
  inherits(RangeEnumerator, super_);

  function RangeEnumerator(start, count) {
    this.current = start - 1;
    this.end = start + count - 1;
  }

  RangeEnumerator.prototype._moveNext = function() {
    if (this.current < this.end) {
      this.current = this.current + 1;
      return true;
    } else {
      return false;
    }
  };

  return RangeEnumerator;
}(Enumerator));

var e1 = Enumerable.range(0, 100).map(function(x, i) {
  return x * x + i;
}).filter(function(x) {
  return x % 2 === 0;
}).forEach(function(x, i) {
  console.log(x, i);
});

var e1 = Enumerable.range(0, 1000).map(function(x, i) {
  return x * x + i;
}).filter(function(x) {
  return x % 2 === 0;
}).forEach(function(x, i) {
  console.log(x, i);
});
pending…
Function based
function noop() {}

var Enumerator = function(moveNext, getCurrent, dispose) {
    this.moveNext = moveNext;
    this.getCurrent = getCurrent;
    this.dispose = dispose;
    };

var enumeratorCreate = Enumerator.create = function(moveNext, getCurrent, dispose) {
    var done = false;
    dispose || (dispose = noop);
    return new Enumerator(function() {
      if (done) {
        return false;
      }
      var result = moveNext();
      if (!result) {
        done = true;
        dispose();
      }
      return result;
    }, function() {
      return getCurrent();
    }, function() {
      if (!done) {
        dispose();
        done = true;
      }
    });
    };

function Enumerable(getEnumerator) {
  this.getEnumerator = getEnumerator;
}

Enumerable.prototype.map = function(selector, thisArg) {
  var parent = this;
  return new Enumerable(function() {
    var current, index = 0,
        e;
    return enumeratorCreate(

    function() {
      e || (e = parent.getEnumerator());
      if (!e.moveNext()) {
        return false;
      }
      current = selector.call(thisArg, e.getCurrent(), index++, parent);
      return true;
    }, function() {
      return current;
    }, function() {
      e.dispose();
    });
  });
};

Enumerable.prototype.filter = function(selector, thisArg) {
  var parent = this;
  return new Enumerable(function() {
    var current, index = 0,
        e;
    return enumeratorCreate(

    function() {
      e || (e = parent.getEnumerator());
      while (true) {
        if (!e.moveNext()) {
          return false;
        }
        var c = e.getCurrent();
        if (selector.call(thisArg, c, index++, parent)) {
          current = c;
          return true;
        }
      }
    }, function() {
      return current;
    }, function() {
      e.dispose();
    });
  });
};

Enumerable.prototype.forEach = function(action, thisArg) {
  var e = this.getEnumerator(),
      i = 0;
  try {
    while (e.moveNext()) {
      action.call(thisArg, e.getCurrent(), i++, this);
    }
  } catch (ex) {
    throw ex;
  } finally {
    e.dispose();
  }
};

Enumerable.range = function(start, count) {
  return new Enumerable(function() {
    var current = start - 1,
        end = start + count - 1;
    return enumeratorCreate(

    function() {
      if (current < end) {
        current++;
        return true;
      } else {
        return false;
      }
    }, function() {
      return current;
    });
  });
};

var e1 = Enumerable.range(0, 100).map(function(x, i) {
  return x * x + i;
}).filter(function(x) {
  return x % 2 === 0;
}).forEach(function(x, i) {
  console.log(x, i);
});

var e1 = Enumerable.range(0, 1000).map(function(x, i) {
  return x * x + i;
}).filter(function(x) {
  return x % 2 === 0;
}).forEach(function(x, i) {
  console.log(x, i);
});
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