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
<p id="message"></p>
<div id="root"></div>
<style type="text/css">
@-moz-keyframes nodeInserted {
from { clip: rect(1px, auto, auto, auto); }
to { clip: rect(0px, auto, auto, auto); }
}
@-webkit-keyframes nodeInserted {
from { clip: rect(1px, auto, auto, auto); }
to { clip: rect(0px, auto, auto, auto); }
}
@-ms-keyframes nodeInserted {
from { clip: rect(1px, auto, auto, auto); }
to { clip: rect(0px, auto, auto, auto); }
}
@-o-keyframes nodeInserted {
from { clip: rect(1px, auto, auto, auto); }
to { clip: rect(0px, auto, auto, auto); }
}
@keyframes nodeInserted {
from { clip: rect(1px, auto, auto, auto); }
to { clip: rect(0px, auto, auto, auto); }
}
.container > span.added {
-o-animation-duration: 0.001s;
-ms-animation-duration: 0.001s;
-moz-animation-duration: 0.001s;
-webkit-animation-duration: 0.001s;
animation-duration: 0.001s;
-o-animation-name: nodeInserted;
-ms-animation-name: nodeInserted;
-moz-animation-name: nodeInserted;
-webkit-animation-name: nodeInserted;
animation-name: nodeInserted;
}
</style>
<script>
console.log("preparation");
var container, globalDeferred;
var root = document.getElementById("root");
var addTestContainer = function(root) {
var container = document.createElement("div");
container.className = "container";
for (var i = 0; i < 1000; i++) {
var element = document.createElement("span");
element.className = "remove";
container.appendChild(element);
}
root.appendChild(container);
return container;
};
var replaceContentsOf = function(container) {
container.innerHTML = "<span class=\"added\"></span>";
};
var isAdded = function(node) {
return node.nodeName.toUpperCase() === "SPAN" &&
node.classList && node.classList.contains("added");
};
var handleNodeAdded = function() {
window.globalDeferred.resolve();
window.globalDeferred = null;
};
var mutationListener = function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === "childList" && mutation.addedNodes !== null) {
for (var i = 0; i < mutation.addedNodes.length; i++) {
if (isAdded(mutation.addedNodes[i]))
handleNodeAdded();
}
}
});
};
var setMessage = function(messageHtml) {
document.getElementById("message").innerHTML = messageHtml;
};
var observer;
if (window.MutationObserver) {
setMessage("Your browser supports <code>MutationObserver</code>.");
observer = new MutationObserver(mutationListener);
} else if (window.WebKitMutationObserver) {
setMessage("Your browser supports <code>WebKitMutationObserver</code>.");
observer = new WebKitMutationObserver(mutationListener);
} else {
setMessage("Your browser does not support <code>MutationObserver</code>. You will not be able to run these tests.");
}
var animationListener = function(event) {
if (event.animationName === "nodeInserted" && isAdded(event.target))
handleNodeAdded();
};
var nodeInsertedListener = function(event) {
if (isAdded(event.target))
handleNodeAdded();
};
// Note: cannot use global setup when using ui.benchmarks[i].setup
ui.benchmarks[0].setup = function() {
console.log("setup[0]");
for (var i = 0; i < this.benchmark.count; i++)
addTestContainer(root);
container = root.firstElementChild;
observer.observe(root, {
childList: true,
subtree: true
});
};
ui.benchmarks[1].setup = function() {
console.log("setup[1]");
for (var i = 0; i < this.benchmark.count; i++)
addTestContainer(root);
container = root.firstElementChild;
root.addEventListener("animationstart", animationListener, false);
root.addEventListener("MSAnimationStart", animationListener, false);
root.addEventListener("webkitAnimationStart", animationListener, false);
};
ui.benchmarks[2].setup = function() {
console.log("setup[2]");
for (var i = 0; i < this.benchmark.count; i++) {
var element = addTestContainer(root);
element.addEventListener("DOMNodeInserted", nodeInsertedListener, false);
}
container = root.firstElementChild;
};
ui.benchmarks[0].teardown = function() {
console.log("teardown[0]");
observer.disconnect();
root.innerHTML = "";
};
ui.benchmarks[1].teardown = function() {
console.log("teardown[1]");
root.removeEventListener("animationstart", animationListener, false);
root.removeEventListener("MSAnimationStart", animationListener, false);
root.removeEventListener("webkitAnimationStart", animationListener, false);
root.innerHTML = "";
};
ui.benchmarks[2].teardown = function() {
console.log("teardown[2]");
for (var i = 0; i < root.childNodes.length; i++) {
root.childNodes[i].removeEventListener("DOMNodeInserted",
nodeInsertedListener, false);
}
root.innerHTML = "";
};
</script>
Ready to run.
Test | Ops/sec | |
---|---|---|
MutationObserver |
| ready |
animationstart event (CSS) |
| ready |
DOMNodeInserted event (mutation events) |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.