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
All tests across all revisions of the original shoot off.
Please, do not remove tests when making future revisions; additions are welcome. Please do not cheat using script blocks.
Libraries: Mustache (0.3.0) jQuery (beta 1, discontinued) Kendo UI Handlebars Underscore John Resig's Micro Templates T2 jqote2 (10/21/2010)
<script src="https://www.cinsoft.net/mylib099-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/ext-core/3/ext-core.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/yui/2.9.0/build/yuiloader/yuiloader-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/mootools/1.3/mootools-yui-compressed.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/prototype/1/prototype.js"></script>
<!---------------------------------------->
<!-- EXTERNAL LIBRARIES HOSTED BY A CDN -->
<!---------------------------------------->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.3.0/mustache.min.js"></script>
<script src="https://github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script>
<script src="http://cdn.kendostatic.com/2011.2.804/js/kendo.all.min.js"></script>
<script src="https://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
<!--------------------------->
<!-- MASTER TEMPLATE DATA -->
<!--------------------------->
<script>
window.tpl = {};
window.tpl.vars = {
header: "Header",
header2: "Header2",
header3: "Header3",
header4: "Header4",
header5: "Header5",
header6: "Header6",
list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
};
window.tpl.vars2 = {
header: "Header",
header2: "Header2",
header3: "Header3",
header4: "Header4",
header5: "Header5",
header6: "Header6",
list: [{i: '1'}, {i: '2'}, {i: '3'}, {i: '4'}, {i: '5'}, {i: '6'}, {i: '7'}, {i: '8'}, {i: '9'}, {i: '10'}]
};
/****************************************
TEMPLATE ENGINES NOT HOSTED BY A CDN
****************************************/
//Please minify any hard included library and note the version.
//Resig Template Function (modified to support ')
function tmpl(a) {
var b = "var p=[];" + "with(obj){p.push('" + a.replace(/[\r\t\n]/g, " ").replace(/'(?=[^#]*#>)/g, "\t").split("'").join("\\'").split("\t").join("'").replace(/<#=(.+?)#>/g, "',$1,'").split("<#").join("');").split("#>").join("p.push('") + "');}return p.join('');";
return new Function("obj", b)
}
//Resig modified template function (no "with" block)
function tmpl2(a) {
var b = "var p=[];" + "p.push('" + a.replace(/[\r\t\n]/g, " ").replace(/'(?=[^#]*#>)/g, "\t").split("'").join("\\'").split("\t").join("'").replace(/<#=(.+?)#>/g, "',$1,'").split("<#").join("');").split("#>").join("p.push('") + "');return p.join('');";
return new Function("data", b)
}
//T2 Template as found on the original shootoff (origin unknown)
window.T2template = function() {
var a = function(b, c, d) {
if(Object.prototype.toString.call(b) === "[object Array]") {
var e = "";
for(var f in b)e += a(b[f], c, d);
return e
} else {
return c.replace(/\{([^\{\}]*)\}/g, function(c, e) {
if(e.substring(0, 1) == "@") {
e = e.substring(1);
var f = d[e], g = b[e];
return typeof f === "string" && Object.prototype.toString.call(g) === "[object Array]" ? a(g, f, d) : c
}
var h = b[e];
return typeof h === "string" || typeof h === "number" ? h : c
})
}
};
var b = function(a, b, c, d, e) {
var f = a.split(/[\(,\)]/), g = f.shift();
switch(g) {
case"exists":
for(var h in f) {
if(!b[f[h]])return false
}
return true;
case"first":
return d == 0;
case"middle":
return d > 0 && d < e - 1;
case"last":
return d == e - 1
}
return false
};
var c = function(a, d, e, f, g) {
if(Object.prototype.toString.call(a) === "[object Array]") {
var h = "", i = a.length;
for(var j in a)h += c(a[j], d, e, parseInt(j, 10), i);
return h
} else {
return d.replace(/\{([^\{\}]*)\}/g, function(h, i) {
if(i.substring(0, 1) == "@") {
i = i.substring(1);
var j = e[i], k = a[i];
return typeof j === "string" && Object.prototype.toString.call(k) === "[object Array]" ? c(k, j, e, f, g) : h
} else if(i.substring(0, 1) == "?") {
if(b(i.substring(1), a, d, f, g))return "{!+}"; else return "{!-}"
}
var l = a[i];
return typeof l === "string" || typeof l === "number" ? l : h
}).replace(/\{\!\-\}.+?\{\/\?\}/g, "").replace(/\{\!\+\}(.+?)\{\/\?\}/g, "$1")
}
};
var d = {
compile: function(a, b) {
var d = a._, e = a;
return c(b, d, e, 1, 1)
}, s_compile: function(b, c) {
var d = b._, e = b;
return a(c, d, e)
}
};
return d
}()
//jQote2 (10/21/2010)
(function($) {
var _ = false, E1 = "UndefinedTemplateError", E2 = "TemplateCompilationError", E3 = "TemplateExecutionError", A = "[object Array]", S = "[object String]", F = "[object Function]", n = 1, c = "%", q = /^[^<]*(<[\w\W]+>)[^>]*$/, ts = Object.prototype.toString;
function r(e, x) {
throw ($.extend(e, x), e)
}
function dns(f) {
var a = [];
if(ts.call(f) !== A)return _;
for(var i = 0, l = f.length; i < l; i++)a[i] = f[i].jqote_id;
return a.length ? a.sort().join('.').replace(/(\b\d+\b)\.(?:\1(\.|$))+/g, "$1$2") : _
}
function l(s, t) {
var f, g = [], t = t || c, x = ts.call(s);
if(x === F)return s.jqote_id ? [s] : _;
if(x !== A)return [$.jqotec(s, t)];
if(x === A)for(var i = 0, l = s.length; i < l; i++)return g.length ? g : _
}
$.fn.extend({
jqote: function(x, y) {
var x = ts.call(x) === A ? x : [x], d = "";
this.each(function(i) {
var f = $.jqotec(this, y);
for(var j = 0; j < x.length; j++)d += f.call(x[j], i, j, x, f)
});
return d
}
});
$.each({app: "append", pre: "prepend", sub: "html"}, function(x, y) {
$.fn["jqote" + x] = function(e, d, t) {
var p, r, s = $.jqote(e, d, t), $$ = !q.test(s) ? function(s) {
return $(document.createTextNode(s))
} : $;
if(!!(p = dns(l(e))))r = new RegExp("(^|\\.)" + p.split(".").join("\\.(.*)?") + "(\\.|$)");
return this.each(function() {
var z = $$(s);
$(this)[y](z);
(z[0].nodeType === 3 ? $(this) : z).trigger("jqote." + x, [z, r])
})
}
});
$.extend({
jqote: function(e, d, t) {
var s = "", t = t || c, f = l(e);
if(f === _)r(new Error("Empty or undefined template passed to $.jqote"), {type: E1});
d = ts.call(d) !== A ? [d] : d;
for(var i = 0, m = f.length; i < m; i++)for(var j = 0; j < d.length; j++)s += f[i].call(d[j], i, j, d, f[i]);
return s
}, jqotec: function(x, t) {
var h, e, y, t = t || c, z = ts.call(x);
if(z === S && q.test(x)) {
e = y = x;
if(h = $.jqotecache[x])return h
} else {
e = z === S || x.nodeType ? $(x) : x instanceof jQuery ? x : null;
if(!e[0] || !(y = e[0].innerHTML) && !(y = e.text()))r(new Error("Empty or undefined template passed to $.jqotec"), {type: E1});
if(h = $.jqotecache[$.data(e[0], "jqote_id")])return h
}
var s = "", i, a = y.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]/g, "").split("<" + t).join(t + ">\x1b").split(t + ">");
for(var m = 0, k = a.length; m < k; m++)s += a[m].charAt(0) !== "\x1b" ? "out+='" + a[m].replace(/(\\|["'])/g, "\\$1") + "'" : (a[m].charAt(1) === "=" ? ";out+=(" + a[m].substr(2) + ");" : (a[m].charAt(1) === "!" ? ";out+=$.jqotenc((" + a[m].substr(2) + "));" : ";" + a[m].substr(1)));
s = "try{" + ('var out="";' + s + ";return out;").split("out+='';").join("").split('var out="";out+=').join("var out=") + '}catch(e){e.type="' + E3 + '";e.args=arguments;e.template=arguments.callee.toString();throw e;}';
try {
var f = new Function("i, j, data, fn", s)
} catch(e) {
r(e, {type: E2})
}
i = e instanceof jQuery ? $.data(e[0], "jqote_id", n) : e;
return $.jqotecache[i] = (f.jqote_id = n++, f)
},
jqotefn: function(e) {
var t = ts.call(e), i = t === S && q.test(e) ? e : $.data($(e)[0], "jqote_id");
return $.jqotecache[i] || _
}, jqotetag: function(s) {
if(ts.call(s) === S)c = s
}, jqotenc: function(s) {
return s.toString().replace(/&(?!\w+;)/g, '&').split('<').join('<').split('>').join('>').split('"').join('"').split("'").join(''')
}, jqotecache: {}
});
$.event.special.jqote = {
add: function(o) {
var n, h = o.handler, d = !o.data ? [] : ts.call(o.data) !== A ? [o.data] : o.data;
if(!o.namespace)o.namespace = "app.pre.sub";
if(!d.length || !(n = dns(l(d))))return;
o.handler = function(e, m, r) {
return !r || r.test(n) ? h.apply(this, [e, m]) : null
}
}
}
})(jQuery);
/********************************
TEMPLATE DEFINITIONS
********************************/
// jQuery - Beta 1 (discontinued)
window.tpl.jQuery = $.template(null, "<div><h1 class='header'>{{html header}}</h1><h2 class='header2'>{{html header2}}</h2><h3 class='header3'>{{html header3}}</h3><h4 class='header4'>{{html header4}}</h4><h5 class='header5'>{{html header5}}</h5><h6 class='header6'>{{html header6}}</h6><ul class='list'>{{each list}}<li class='item'>{{html $value}}</li>{{/each}}</ul></div>");
// Underscore
window.tpl.underscore = _.template("<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6><ul class='list'><% for (var i = 0, l = list.length; i < l; i++) { %><li class='item'><%= list[i] %></li><% } %></ul></div>");
// Mustache
window.tpl.mustache = "<div><h1 class='header'>{{{header}}}</h1><h2 class='header2'>{{{header2}}}</h2><h3 class='header3'>{{{header3}}}</h3><h4 class='header4'>{{{header4}}}</h4><h5 class='header5'>{{{header5}}}</h5><h6 class='header6'>{{{header6}}}</h6><ul class='list'>{{#list}}<li class='item'>{{{.}}}</li>{{/list}}</ul></div>";
// Handlebars
window.tpl.handlebars = Handlebars.compile("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#each list}}<li class='item'>{{this}}</li>{{/each}}</ul></div>");
// Kendo
window.tpl.kendo = kendo.template("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>", {useWithBlock: true});
window.tpl.kendo2 = kendo.template("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>", {useWithBlock: false});
//John Resig's approach
window.tpl.resig = tmpl("<div><h1 class='header'><#= header #></h1><h2 class='header2'><#= header2 #></h2><h3 class='header3'><#= header3 #></h3><h4 class='header4'><#= header4 #></h4><h5 class='header5'><#= header5 #></h5><h6 class='header6'><#= header6 #></h6><ul class='list'><# for (var i = 0, l = list.length; i < l; i++) { #><li class='item'><#= list[i] #></li><# } #></ul></div>");
window.tpl.resig2 = tmpl2("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>");
//T2 Template
window.tpl.T2 = {
_: "<div><h1 class='header'>{header}</h1><h2 class='header2'>{header2}</h2><h3 class='header3'>{header3}</h3><h4 class='header4'>{header4}</h4><h5 class='header5'>{header5}</h5><h6 class='header6'>{header6}</h6><ul class='list'>{@list}</ul></div>",
list: "<li class='item'>{i}</li>"
};
//jQuote2
window.tpl.jqote = $.jqotec("<div><h1 class='header'><%= this.header %></h1><h2 class='header2'><%= this.header2 %></h2><h3 class='header3'><%= this.header3 %></h3><h4 class='header4'><%= this.header4 %></h4><h5 class='header5'><%= this.header5 %></h5><h6 class='header6'><%= this.header6 %></h6><ul class='list'><% for (var n = 0, l = this.list.length; n < l; n++) { %><li class='item'><%= this.list[n] %></li><% } %></ul></div>");
</script>
Ready to run.
Test | Ops/sec | |
---|---|---|
Mustache 0.3.0 |
| ready |
jQuery (beta 1, discontinued) |
| ready |
Kendo UI |
| ready |
Kendo UI (no "with" block) |
| ready |
Handlebars |
| ready |
Underscore |
| ready |
Resig Micro Templates |
| ready |
Resig Micro Templates (No "with" block) |
| ready |
T2 |
| ready |
T2 (logic) |
| ready |
jqote2 (10/21/2010) |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.