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="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://rawgithub.com/spmbt/doT/master/doT.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://borismoore.github.com/jsrender/jsrender.js"></script>
<script src="http://github.com/janl/mustache.js/raw/master/mustache.js"></script>
<script src="https://rawgithub.com/atmajs/MaskJS/master/lib/mask.min.js"></script>
<script src="http://ysugimoto.github.io/Retriever/build/retriever.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0-alpha.2/handlebars.min.js"></script>
<script>
(function(window,undefined){if(!Array.isArray)Array.isArray=function(v){return Object.prototype.toString.call(v)==="[object Array]"};var _Penguin=function(){};var _Config={templateDataAttribute:"data-template",templateMarkDataAttribute:"data-id",scriptMimeType:"text/penguin-template",scriptFor:"data-for",cleanDomAfterCompilation:true,isBuffering:false,jQueryCheckTimeout:5};var _jQueryDetected=false;var _Original$$=undefined;var _PrecompiledTemplates={};var _ReadyList=[];var _TemplateBuffer=[];function _BindGlobals(){if(typeof window.$$!==
"undefined")_Original$$=window.$$;window.$$=_Penguin;window.Penguin=_Penguin}function _CallReadyList(){for(var i=0,l=_ReadyList.length;i<l;++i)_ReadyList[i].call(this)}function _DefineJqueryPlugins(){function __define(){_jQueryDetected=typeof window.jQuery==="function";if(!_jQueryDetected){window.setTimeout(__define,_Config.jQueryCheckTimeout*=1.01);return}jQuery.fn.extend({appendTemplates:function(){var args=[];args.length=arguments.length;for(var i=0,l=args.length;i<l;++i)args[i]=arguments[i];for(var i=
0,l=args.length;i<l;++i)if(args[i]instanceof Template||args[i]instanceof TemplateCollection)args[i]=args[i].Node;return this.append(args)}})}__define()}function _DomNodeToString(n){if("outerHTML"in n)return n.outerHTML;var div=document.createElement("div");div.appendChild(n.cloneNode(true));return div.innerHTML}function _GetElementsByAttribute(attr){var arr=[];var i=0;var all=document.getElementsByTagName("*");for(var j=0,l=all.length;j<l;++j)if(all[j].hasAttribute(attr))arr[i++]=all[j];return arr}
function _GetMarkedElements(el){var next=el;var marks={};var node;while(node=next){if(node.nodeType===Node.ELEMENT_NODE&&node.hasAttribute(_Config.templateMarkDataAttribute))marks[node.getAttribute(_Config.templateMarkDataAttribute)]=node;next=node.firstChild||node.nextSibling;while(next===null&&(node=node.parentNode))next=node.nextSibling}return marks}var _HTMLtoFragment=function(){function makeMap(str){var obj={};var items=str.split(",");for(var i=0;i<items.length;++i)obj[items[i]]=true;return obj}
function HTMLParser(html,handler){function parseEndTag(tag,tagName){var pos;if(!tagName)pos=0;else for(pos=stack.length-1;pos>=0;--pos)if(stack[pos]===tagName)break;if(pos>=0){for(var i=stack.length-1;i>=pos;--i)if(handler.end)handler.end(stack[i]);stack.length=pos}}function parseStartTag(tag,tagName,rest,unary){var attrs=[];tagName=tagName.toLowerCase();if(block[tagName])while(stack.last()&&inline[stack.last()])parseEndTag("",stack.last());if(closeSelf[tagName]&&stack.last()===tagName)parseEndTag("",
tagName);unary=empty[tagName]||!!unary;if(!unary)stack.push(tagName);if(handler.start){attrs.length=0;rest.replace(attr,function(match,name){var value=arguments[2]?arguments[2]:arguments[3]?arguments[3]:arguments[4]?arguments[4]:fillAttrs[name]?name:"";attrs.push({name:name,value:value,escaped:value.replace(/(^|[^\\])"/g,'$1\\"')})});if(handler.start)handler.start(tagName,attrs,unary)}}var index;var chars;var match;var stack=[];var last=html;stack.last=function(){return this[this.length-1]};while(html){chars=
true;if(!stack.last()||!special[stack.last()]){if(html.indexOf("\x3c!--")===0){index=html.indexOf("--\x3e");if(index>=0){if(handler.comment)handler.comment(html.substring(4,index));html=html.substring(index+3);chars=false}}else if(html.indexOf("</")===0){match=html.match(endTag);if(match){html=html.substring(match[0].length);match[0].replace(endTag,parseEndTag);chars=false}}else if(html.indexOf("<")===0){match=html.match(startTag);if(match){html=html.substring(match[0].length);match[0].replace(startTag,
parseStartTag);chars=false}}if(chars){index=html.indexOf("<");var text=index<0?html:html.substring(0,index);html=index<0?"":html.substring(index);if(handler.chars)handler.chars(text)}}else{html=html.replace(new RegExp("(.*)</"+stack.last()+"[^>]*>"),function(all,text){text=text.replace(/\x3c!--(.*?)--\x3e/g,"$1").replace(/<!\[CDATA\[(.*?)]]\x3e/g,"$1");if(handler.chars)handler.chars(text);return""});parseEndTag("",stack.last())}if(html===last)throw"Parse Error: "+html;last=html}parseEndTag()}var startTag=
/^<([-A-Za-z0-9_]+)((?:\s+[\w-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;var endTag=/^<\/([-A-Za-z0-9_]+)[^>]*>/;var attr=/([-A-Za-z0-9_]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;var empty=makeMap("area,base,basefont,br,col,embed,frame,hr,img,input,isindex,keygen,link,menuitem,meta,param,source,track,wbr,embed");var block=makeMap("address,applet,article,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,frameset,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");
var inline=makeMap("a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");var closeSelf=makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");var fillAttrs=makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");var special=makeMap("script,style");return function(html){var frag=document.createDocumentFragment();
var elems=[];var curParentNode=frag;elems[0]=frag;HTMLParser(html,{start:function(tagName,attrs,unary){var elem=document.createElement(tagName);for(var attr in attrs)elem.setAttribute(attrs[attr].name,attrs[attr].value);curParentNode.appendChild(elem);if(!unary){elems.push(elem);curParentNode=elem}},end:function(tag){elems.length-=1;if(!empty[tag])curParentNode=elems[elems.length-1]},chars:function(text){curParentNode.appendChild(document.createTextNode(text))},comment:function(text){var comm=document.createComment(text);
if(curParentNode)curParentNode.appendChild(comm);else elems.push(comm)}});return frag}}();function _Initialise(){function __ready(){_PrecompileTemplates();_DefineJqueryPlugins();_CallReadyList()}_jQueryDetected=typeof window.jQuery==="function";if(_jQueryDetected)jQuery(document).ready(__ready);else document.addEventListener("DOMContentLoaded",__ready,false)}function _IsElement(o){return typeof HTMLElement==="object"?o instanceof HTMLElement:o&&typeof o==="object"&&o!==null&&o.nodeType===Node.ELEMENT_NODE&&
typeof o.nodeName==="string"}function _NOP(){}function _ParseHTML(html){return _HTMLtoFragment(html)}function _PrecompileTemplates(){var elems=_GetElementsByAttribute(_Config.templateDataAttribute);var scripts=function(){var o={};var sourceArr=[];var scriptElems=Array.prototype.slice.call(document.scripts).filter(function(s){return s.hasAttribute(_Config.scriptFor)&&s.type.toLowerCase()===_Config.scriptMimeType});sourceArr.length=scriptElems.length;for(var i=0,l=scriptElems.length;i<l;++i){sourceArr[i]=
scriptElems[i].textContent.replace(/(?!})\s*;\s*$/,"");o[i]=scriptElems[i].getAttribute(_Config.scriptFor);if(_Config.cleanDomAfterCompilation)scriptElems[i].parentNode.removeChild(scriptElems[i])}eval("sourceArr=["+sourceArr.join(",")+"]");for(var i=0,l=sourceArr.length;i<l;++i)o[o[i]]=sourceArr[i];return o}();var name;var model;for(var i=0,l=elems.length;i<l;++i){name=elems[i].getAttribute(_Config.templateDataAttribute);if(elems[i].nodeName.toLowerCase()==="template")if("content"in elems[i])model=
elems[i].content;else model=elems[i].innerHTML;else model=elems[i];_PrecompiledTemplates[name]=_Penguin.Create(model,name in scripts?scripts[name]:null);if(_Config.cleanDomAfterCompilation)elems[i].parentNode.removeChild(elems[i])}}function Template(o){this._original=o.Model;this._node=o.Model.cloneNode(true);this._marks=_GetMarkedElements(this._node);this._func=typeof o.Logic==="function"?o.Logic:null;if(_Config.isBuffering)_TemplateBuffer.push(this)}Object.defineProperties(Template.prototype,{_original:{value:null,
enumerable:false,writable:true},_node:{value:null,writable:true,configurable:false},_marks:{value:null,writable:true,enumerable:false},_func:{value:null,writable:true,enumerable:false},AppendTo:{value:function(n){if(typeof n==="string")n=document.getElementById(n);n.appendChild(this._node);return this},enumerable:true},Clean:{value:function(){if(!(this._node instanceof DocumentFragment))this._node.removeAttribute(_Config.templateDataAttribute);for(var mark in this._marks)this._marks[mark].removeAttribute(_Config.templateMarkDataAttribute);
return this},enumerable:true},Copy:{value:function(){return new Template({Type:"copy",Model:this._original,Logic:this._func})},enumerable:true},DataBind:{value:function(){if(typeof this._func==="function"){var args=[];args.length=arguments.length;for(var i=0,l=args.length;i<l;++i)args[i]=arguments[i];this._func.apply(this,args)}return this},enumerable:true},DataBindCollection:{value:function(coll){var t;var arr=[];arr.length=coll.length;for(var i=0,l=coll.length;i<l;++i){t=this.Copy();t.DataBind.apply(t,
[coll[i],i,coll]);arr[i]=t}return new TemplateCollection(arr)},enumerable:true},Node:{get:function(){return this._node},enumerable:true},Get:{value:function(name){return this._marks[name]},enumerable:true},Logic:{value:function(f){if(typeof f==="function"){this._func=f;return this}else return this._func},enumerable:true},Set:{value:function(a,b,c){var mods=[];var modType;var markedElem;if(arguments.length===1)if(typeof a==="function")a.call(this);else{if(typeof a==="object")for(var mark in a){markedElem=
this._marks[mark];if(typeof a[mark]==="object")for(var subMark in a[mark])mods.push({Mark:markedElem,Property:subMark,Value:a[mark][subMark]});else mods.push({Mark:markedElem,Property:null,Value:a[mark]})}}else if(arguments.length===2){markedElem=this._marks[a];if(typeof b==="function")b.call(markedElem,this);else if(typeof b==="object"&&Array.isArray(b)===false)for(var prop in b)mods.push({Mark:markedElem,Property:prop,Value:b[prop]});else mods.push({Mark:markedElem,Property:null,Value:b})}else if(arguments.length===
3)mods.push({Mark:this._marks[a],Property:b,Value:c});else console.log("Incorrect number of parameters");for(var i=0;i<mods.length;++i){if(mods[i].Mark===undefined){console.log("Marked element not found");continue}modType=typeof mods[i].Value;if(mods[i].Property===null)if(modType==="string"||modType==="boolean"||modType==="number")mods[i].Mark.textContent=mods[i].Value;else if(modType==="function")mods[i].Value.call(mods[i].Mark,this);else if(Array.isArray(mods[i].Value))mods[i].Mark.textContent=
mods[i].Value.join(", ");else console.log("Modification type of element not supported: "+modType);else if(mods[i].Property in mods[i].Mark)mods[i].Mark[mods[i].Property]=mods[i].Value;else mods[i].Mark.setAttribute(mods[i].Property,mods[i].Value)}return this},enumerable:true},toJSON:{value:function(){return{Type:"json",Model:_DomNodeToString(this._original),Logic:typeof this._func==="function"?this._func.toString():null}},enumerable:true}});function TemplateCollection(arr){this._Arr=arr}Object.defineProperties(TemplateCollection.prototype,
{AppendTo:{value:function(n){if(typeof n==="string")n=document.getElementById(n);n.appendChild(this.Node);return this},enumerable:true},AppendToAsync:{value:function(n,ival,cb){if(typeof n==="string")n=document.getElementById(n);if(typeof ival!=="number")ival=0;if(typeof cb!=="function")cb=_NOP;var _self=this;var f=document.createDocumentFragment();var i=0;var l=_self._Arr.length;var chunkSize=Math.ceil(l*.1);var _process=function(){var max=Math.min(i+chunkSize,l);for(;i<max;++i)f.appendChild(_self._Arr[i].Node);
n.appendChild(f);if(i<l){f=document.createDocumentFragment();window.setTimeout(_process,ival)}else cb.call(_self,null)};_process();return _self},enumerable:true},Node:{get:function(){var f=document.createDocumentFragment();for(var i=0,l=this._Arr.length;i<l;++i)f.appendChild(this._Arr[i].Node);return f},enumerable:true},Item:{value:function(i){return this._Arr[i]},enumerable:true},Length:{get:function(){return this._Arr.length},enumerable:true},Push:{value:function(t){if(t instanceof Template)this._Arr.push(t);
return this},enumerable:true}});Object.defineProperties(_Penguin,{Buffer:{value:{},enumerable:true},Create:{value:function(){var elem;var func=null;if(arguments.length===1)if(typeof arguments[0]==="object"){elem=arguments[0].Model;func=arguments[0].Logic}else elem=arguments[0];else if(arguments.length===2){elem=arguments[0];func=arguments[1]}if(typeof elem==="string")elem=_ParseHTML(elem);else if(elem.nodeName.toLowerCase()==="template")if("content"in elem)elem=elem.content;else elem=_ParseHTML(elem.innerHTML);
if(typeof func==="string")eval("func="+func);return new Template({Type:"new",Model:elem,Logic:func})},enumerable:true},Get:{value:function(name){return _PrecompiledTemplates[name].Copy()},enumerable:true},jQuerySupport:{value:function(){_DefineJqueryPlugins();return _Penguin},enumerable:true},Original$$:{get:function(){return _Original$$},enumerable:true},Ready:{value:function(f){if(typeof f==="function")_ReadyList.push(f);return _Penguin},enumerable:true}});Object.defineProperties(_Penguin.Buffer,
{Clear:{value:function(){_TemplateBuffer.length=0;return _Penguin},enumerable:true},Disable:{value:function(){_Config.isBuffering=false;return _Penguin},enumerable:true},Enable:{value:function(){_Config.isBuffering=true;return _Penguin},enumerable:true},Enabled:{get:function(){return _Config.isBuffering},set:function(v){_Config.isBuffering=v?true:false;return _Config.isBuffering},enumerable:true},Collection:{get:function(){var arr=[];arr.length=_TemplateBuffer.length;for(var i=0,l=_TemplateBuffer.length;i<
l;++i)arr[i]=_TemplateBuffer[i];return new TemplateCollection(arr)},enumerable:true},Length:{get:function(){return _TemplateBuffer.length},enumerable:true},Push:{value:function(t){if(t instanceof Template)_TemplateBuffer.push(t);return _Penguin},enumerable:true}});_BindGlobals();_Initialise()})(window);</script>
<!--External Template Definitions-->
<script>
window.sharedVariables = {
header0: "Test render template engine ",
header2: "Header2",
header3: "Header3",
header4: "Header4",
header5: "Header5",
header6: "Header6",
list: ['1000000', '2000000', '3000000', '4000000', '5000000', '6000000', '7000000', '8000000', '9000000', '10000000']
};
window.doTtemplateRaw = "<div><h1 class='header'>{{=it.header}}</h1><h2 class='header2'>{{=it.header2}}</h2><h3 class='header3'>{{=it.header3}}</h3><h4 class='header4'>{{=it.header4}}</h4><h5 class='header5'>{{=it.header5}}</h5><h6 class='header6'>{{=it.header6}}</h6><ul class='list'>{{ for (var i=0,l=it.list.length;i<l;i++) { }}<li class='item'>{{=it.list[i]}}</li>{{ } }}</ul></div>";
window.doTtemplate = doT.compile(doTtemplateRaw);
window.underscoreTemplateRaw = "<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.underscoreTemplate = _.template(underscoreTemplateRaw);
window.underscoreTemplateNoWithRaw = "<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>";
window.underscoreTemplateNoWith = _.template(underscoreTemplateNoWithRaw, null, {variable: 'data'});
//JsRender compiled template (no encoding)
window.jsRenderTemplateRaw = "<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 list}}<li class='item'>{{:#data}}</li>{{/for}}</ul></div>";
window.jsRenderTemplate = $.templates(jsRenderTemplateRaw);
window.mustacheTemplateRaw = "<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>";
window.retrieverTemplateRaw = "<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'>{{loop list}}<li class='item'>{{@%data}}</li>{{/loop}}</ul></div>";
window.retrieverTemplate = Retriever.make(retrieverTemplateRaw).compile();
window.HandlebarsTemplateRaw = "<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>";
window.HandlebarsTemplate = Handlebars.compile(HandlebarsTemplateRaw);
window.maskTemplateRaw = "div { \
h1.header > '~[header]'\
h2.header2 > '~[header2]'\
h3.header3 > '~[header3]'\
h4.header4 > '~[header4]'\
h5.header5 > '~[header5]'\
h6.header6 > '~[header6]'\
ul > each (list) > li > '~[.]'\
}";
window.maskDom = mask.compile(maskTemplateRaw)
</script>
<div style="display:none">
<!-- Begin Penguin -->
<div data-template="content"><h1 data-id="header"></h1><h2 data-id="header2"></h2><h3 data-id="header3"></h3><h4 data-id="header4"></h4><h5 data-id="header5"></h5><h6 data-id="header6"></h6><ul data-id="list"></ul></div>
<li data-template="listItem" data-id="text"></li>
<script type="text/penguin-template" data-for="content">
function(vars){
this.Set({
header: vars.header0,
header2: vars.header2,
header3: vars.header3,
header4: vars.header4,
header5: vars.header5,
header6: vars.header6,
list: function(){
$$.Get("listItem").DataBindCollection(vars.list).AppendTo(this);
}
});
}
</script>
<script type="text/penguin-template" data-for="listItem">
function(i){
this.Set("text", i);
}
</script>
<!-- End Penguin -->
</div>
<div id="template" style=""></div>
template = $('#template').get(0);
Ready to run.
Test | Ops/sec | |
---|---|---|
1.doT.js |
| ready |
2.Underscore |
| ready |
3.Underscore (no "with") |
| ready |
4.JsRender |
| ready |
6.MaskJs |
| ready |
7.doT Compile |
| ready |
8. Retriever |
| ready |
9.Handlebars(compiled) |
| ready |
10. Penguin (no clean) |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.