jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
<script src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.2.0/lodash.underscore.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js'></script>
<script>var bbEvents = Backbone.Events;</script>
<script>var extend = _.extend; window._ = null;</script>
<script src="https://github.com/paulmillr/exoskeleton/releases/download/0.5.1/exoskeleton.js"></script>
<script>var exosEvents = Exoskeleton.Events;</script>
<script>function dmafevents (context) {
var dictionary = {
names: {}
},
separator = /:/,
currentEvent = "",
doStop;
function dispatch (eventName) {
var oldstop,
listeners,
listener,
ce;
if (eventName || typeof eventName === "string") {
oldstop = doStop;
ce = currentEvent;
currentEvent = eventName;
listeners = getListeners(eventName);
doStop = false;
for (var i = 0, ii = listeners.length; i < ii; i++) {
listener = listeners[i];
listener.apply(this, arguments);
if (doStop) {
break;
}
}
doStop = oldstop;
currentEvent = ce;
}
}
function getListeners (name) {
var names = name.split(separator),
_events = dictionary, //make dictionary local
item,
listeners = [];
for (var i = 0, ii = names.length; i < ii; i++) {
item = _events.names && _events.names[names[i]];
if (item) {
listeners = listeners.concat(item.listeners || []);
_events = _events.names[names[i]]; // stop down in the event heirarchy
} else {
break;
}
}
return listeners;
}
function stop () {
doStop = 1;
}
function addEventListener (eventName, listener) {
var names = eventName.split(separator),
_events = dictionary; // make dictionary local
for (var i = 0, ii = names.length; i < ii; i++) {
_events = _events.names;
if (_events.hasOwnProperty(names[i]) && _events[names[i]] !== void 0) { // here's that void 0 thing again
_events = _events[names[i]]; // step down one level in the event heirarchy
} else {
_events[names[i]] = {
names: {}
}; // create the missing level in the heirarchy
_events = _events[names[i]];
}
}
_events.listeners = _events.listeners || [];
for (i = 0, ii = _events.listeners.length; i < ii; i++) {
if (_events.listeners[i] === listener) { // if the listener already has been added we just return it
return listener;
}
}
_events.listeners.push(listener);
return listener;
}
function once (eventName, listener) {
var volatileListener = function () {
removeEventListener(eventName, volatileListener);
return listener.apply(this, arguments);
};
return addEventListener(eventName, volatileListener);
}
function removeEventListener (eventName, listener) {
var names = eventName.split(separator),
_events,
key,
spliceArguments,
i, ii, j, jj,
currentEvents = [dictionary];
for (i = 0, ii = names.length; i < ii; i++) {
for (j = 0; j < currentEvents.length; j++) {
spliceArguments = [j, 1];
_events = currentEvents[j].names;
if (_events[names[i]]) {
spliceArguments.push(_events[names[i]]);
}
currentEvents.splice.apply(currentEvents, spliceArguments);
}
}
for (i = 0, ii = currentEvents.length; i < ii; i++) { // will this ever be run? Won't currentEvents.length always be 0 at this point?
_events = currentEvents[i];
while (_events.names) {
if (listener) {
if (_events.listeners) {
for (j = 0, jj = _events.listeners.length; j < jj; j++) {
if (_events.listeners[j] === listener) {
_events.listeners.splice(j, 1);
break;
}
}
if (!_events.listeners.length) {
delete _events.listeners;
}
}
for (key in _events.names) {
if (_events.names.hasOwnProperty(key) && _events.names[key].listeners) {
var listeners = _events.names[key].listeners;
for (j = 0, jj = listeners.length; j < jj; j++) {
if (listeners[j] === listener) {
listeners.splice(j, 1);
break;
}
if (!listeners.length) {
delete _events.names[key].listeners;
}
}
}
}
} else {
delete _events.listeners;
for (key in _events.names) {
if (_events.names.hasOwnProperty(key) && _events.names[key].listeners) {
delete _events.names[key].listeners;
}
}
}
_events = _events.names;
}
}
}
function current () {
return currentEvent;
}
context.addEventListener = context.on = addEventListener;
context.removeEventListener = context.off = removeEventListener;
context.getListeners = getListeners;
context.getCurrentEvent = current;
context.stopEvents = stop;
context.once = once;
context.dispatch = dispatch;
context._events = dictionary;
context._newEventSystem = dmafevents;
}</script>
var numEvents = 3;
var numListeners = 100;
var bb = extend({x:0}, bbEvents);
var exos = extend({x:0}, exosEvents);
var dmaf = {x: 0};
dmafevents(dmaf);
[bb, exos, dmaf].forEach(function(obj) {
obj.on('event', function() { obj.x++; });
});
Ready to run.
Test | Ops/sec | |
---|---|---|
Exoskeleton |
| ready |
Backbone |
| ready |
DMAF |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.