Benchmark.javascript cho45 Follow 2011-02-28 22:30:36 License: MIT License Fork10 Fav7 View10587 Play Stop Reload Fullscreen Smart Phone Fork tree Readme JavaScript 254 lines HTML 18 lines CSS 101 lines based on http://cho45.stfuawsc.com/benchmark.html Fork して code という prefix を持った関数をグローバルにいくつか定義するだけでベンチマークが計れます。 jsdo.it だと HTML いじるベンチマークに便利かもしれません。 Benchmark.javascript JSDeferred 0.3.4 var obj = { foo : 1 }; var foo = "foo"; function code1 () { var i = 1000; while (i--) { obj.foo; } } function code2 () { var i = 1000; while (i--) { obj[foo]; } } //=================== function getParams() { var code = []; for (var key in window) if (window.hasOwnProperty(key)) { if (!/^code/.test(key)) continue; code.push(key); } code.sort(); for (var i = 0, len = code.length; i < len; i++) { code[i] = window[ code[i] ].toString().replace(/^[\s(]*function[^(]+\(\)\s*{\s*|\s*}[\s)]*$/g, ''); } return { code : code }; } Deferred.define(); new function Benchmark () { window.onload = init; function createElementFromString (str, opts) { if (!opts) opts = { data: {} }; if (!opts.data) opts.data = { }; var t, cur = opts.parent || document.createDocumentFragment(), root, stack = [cur]; while (str.length) { if (str.indexOf("<") == 0) { if ((t = str.match(/^\s*<(\/?[^\s>\/]+)([^>]+?)?(\/)?>/))) { var tag = t[1], attrs = t[2], isempty = !!t[3]; if (tag.indexOf("/") == -1) { child = document.createElement(tag); if (attrs) attrs.replace(/([a-z]+)=(?:'([^']+)'|"([^"]+)")/gi, function (m, name, v1, v2) { var v = text(v1 || v2); if (name == "class") root && (root[v] = child), child.className = v; child.setAttribute(name, v); } ); cur.appendChild(root ? child : (root = child)); if (!isempty) { stack.push(cur); cur = child; } } else cur = stack.pop(); } else throw("Parse Error: " + str); } else { if ((t = str.match(/^([^<]+)/))) cur.appendChild(document.createTextNode(text(t[0]))); } str = str.substring(t[0].length); } function text (str) { return str .replace(/&(#(x)?)?([^;]+);/g, function (_, isNumRef, isHex, ref) { return isNumRef ? String.fromCharCode(parseInt(ref, isHex ? 16 : 10)): {"lt":"<","gt":"<","amp":"&"}[ref]; }) .replace(/#\{([^}]+)\}/g, function (_, name) { return (typeof(opts.data[name]) == "undefined") ? _ : opts.data[name]; }); } return root; } function newInput (code) { var template = document.getElementById('template-input').value; var e = createElementFromString(template, { data: { code : code } }); document.getElementById('inputs').appendChild(e); return e; } function log (str) { if (log.element) { log.element.value += str + "\n"; log.element.scrollTop = 9999; } } function script (url) { var d = new Deferred(); var script = document.createElement('script'); script.type = "text/javascript"; script.src = url; script.onreadystatechange = function () { if (this.readyState == 'complete' || this.readyState == 'loaded') { log('Loaded: ' + url); d.call(); } }; script.onload = function () { log('Loaded: ' + url); d.call(); }; document.body.appendChild(script); return d; } function init () { document.getElementById('append-button').onclick = function () { newInput("") }; log.element = document.getElementById('log'); var params = getParams(); var scripts = []; var codes = params.code || []; if (!codes.length) { newInput("// input your code"); newInput("// input your code"); return; } var torun = []; for (var i = 0, len = codes.length; i < len; i++) if (codes[i]) { var code = codes[i]; var e = newInput(code); e.result.innerHTML = "waiting..."; e.code = code; e.sec = 0; e.n = 0; torun.push(e); } // calc function call cost var empty = { isEmpty : true, style : {}, result : {}, code : "", sec : 0, n : 0, speed : 0 }; torun.push(empty); var calculate_results = function (callback) { empty.speed = empty.sec / empty.n; var base = 0; for (var i = 0, len = torun.length; i < len; i++) { var run = torun[i]; if (run.isEmpty) continue; run.speed = run.sec / run.n - empty.speed; callback(run); if (run.speed > base) base = run.speed; } if (empty.speed && Math.random() < 0.01) log("Empty function call cost: " + empty.speed); for (var i = 0, len = torun.length; i < len; i++) { var run = torun[i]; if (run.isEmpty) continue; var rate = Math.floor(base / run.speed * 100); run.result.innerHTML += '<br/>' + rate + '%'; var level = 1 - run.speed / base; run.style.background = "hsl(" + (level * 230 - 10) + ", " + (level * 50 + 40) + "%, " + (level * 50 + 50) + "%)"; } }; var devideTime = 30; var totalTime = 3000; var phaseTotal = totalTime / devideTime; parallel(scripts). loop(phaseTotal, function (phase) { for (var i = 0, len = torun.length; i < len; i++) { torun[i]._rand = Math.random(); } torun.sort(function (a, b) { return a._rand - b._rand }); return loop(torun.length, function (i) { var run = torun[i]; return next(function () { var fun = new Function(run.code); run.className += " running"; // run.result.innerHTML = "running..."; var sec = 0, n = 0; return next(function () { var dt = new Date().getTime(); var nt; devide: { do { if (sec >= devideTime) break devide; n++; var ft = new Date().getTime(); fun(); nt = new Date().getTime(); sec += nt - ft; run.sec += nt - ft; run.n ++; } while (nt - dt < 25); // run.result.innerHTML = "running...<br/>total=" + run.sec + "msec / n=" + run.n + "<br/>speed=" + (run.sec / run.n); calculate_results(function (run) { run.result.innerHTML = "interim result, phase=" + (phase + 1) + "/" + phaseTotal + ":<br/>" + "total=" + run.sec + "msec / n=" + run.n + "<br/>speed=" + (run.speed); }); return call(arguments.callee); }; }). error(function (e) { run.result.innerHTML = "Error:" + e; }); }). next(function () { run.className = run.className.replace(/\s*running\s*/g, ""); }); }); }). next(function () { log('calculating results...'); calculate_results(function (run) { run.result.innerHTML = "done<br/>total=" + run.sec + "msec / n=" + run.n + "<br/>speed=" + run.speed; }); log('done'); }). error(function (e) { log(e); }); } }; <form action=""> <div id="inputs"></div> <p style="clear: both"> <input type="button" value="append code" id="append-button"/> <input type="submit" value="run" /> </p> </form> <textarea id="log" disabled="disabled" cols="50" rows="1"></textarea> <textarea id="template-input" class="template"> <div class="target"> <textarea name="code" cols="50" rows="8" class="code">#{code}</textarea> <div class="result"></div> </div> </textarea> Benchmark.javascript body { font-family: "Lucida Console", "Monaco", sans-serif; font-size: 13px; background: #fff; } textarea { width: 100%; font-size: 11px; font-family: "Lucida Console", "Monaco", sans-serif; margin: 0; padding: 0; } textarea.template { display: none; } dd { margin : 0; padding: 0; } ul { list-style: none; margin : 0; padding: 0; } ul li { margin : 0; padding: 0; } .target { padding: 0; clear: both; } .target .code { opacity: 0.8; margin: 0 0 1em 0; width: 40em; height: 9em; float: left; } .target .result { height: 7em; padding: 0.5em 0; margin: 1em 0 0 41em; } .target.running { } #share { font-size: 10px; padding: 0.5em 1em; position: absolute; top: 0; right: 0; background: #000; color: #fff; opacity: 0.8; -moz-border-radius: 0.5em; } #share a , #share a:visited , #share a:link { color: #fff; text-decoration: none; } #description { } #description ul { list-style: disc; padding: 0 0 0 2em; } .target .code { width: 100%; height: 8em; float: none; margin: 0; padding: 0; } .target .result { width: 100%; margin: 0 0 1em 0; padding: 0.5em; height: auto; } form p input { display : none } based on http://cho45.stfuawsc.com/benchmark.html Fork して code という prefix を持った関数をグローバルにいくつか定義するだけでベンチマークが計れます。 jsdo.it だと HTML いじるベンチマークに便利かもしれません。 var obj = { foo : 1 }; var foo = "foo"; function code1 () { var i = 1000; while (i--) { obj.foo; } } function code2 () { var i = 1000; while (i--) { obj[foo]; } } //=================== function getParams() { var code = []; for (var key in window) if (window.hasOwnProperty(key)) { if (!/^code/.test(key)) continue; code.push(key); } code.sort(); for (var i = 0, len = code.length; i < len; i++) { code[i] = window[ code[i] ].toString().replace(/^[\s(]*function[^(]+\(\)\s*{\s*|\s*}[\s)]*$/g, ''); } return { code : code }; } Deferred.define(); new function Benchmark () { window.onload = init; function createElementFromString (str, opts) { if (!opts) opts = { data: {} }; if (!opts.data) opts.data = { }; var t, cur = opts.parent || document.createDocumentFragment(), root, stack = [cur]; while (str.length) { if (str.indexOf("<") == 0) { if ((t = str.match(/^\s*<(\/?[^\s>\/]+)([^>]+?)?(\/)?>/))) { var tag = t[1], attrs = t[2], isempty = !!t[3]; if (tag.indexOf("/") == -1) { child = document.createElement(tag); if (attrs) attrs.replace(/([a-z]+)=(?:'([^']+)'|"([^"]+)")/gi, function (m, name, v1, v2) { var v = text(v1 || v2); if (name == "class") root && (root[v] = child), child.className = v; child.setAttribute(name, v); } ); cur.appendChild(root ? child : (root = child)); if (!isempty) { stack.push(cur); cur = child; } } else cur = stack.pop(); } else throw("Parse Error: " + str); } else { if ((t = str.match(/^([^<]+)/))) cur.appendChild(document.createTextNode(text(t[0]))); } str = str.substring(t[0].length); } function text (str) { return str .replace(/&(#(x)?)?([^;]+);/g, function (_, isNumRef, isHex, ref) { return isNumRef ? String.fromCharCode(parseInt(ref, isHex ? 16 : 10)): {"lt":"<","gt":"<","amp":"&"}[ref]; }) .replace(/#\{([^}]+)\}/g, function (_, name) { return (typeof(opts.data[name]) == "undefined") ? _ : opts.data[name]; }); } return root; } function newInput (code) { var template = document.getElementById('template-input').value; var e = createElementFromString(template, { data: { code : code } }); document.getElementById('inputs').appendChild(e); return e; } function log (str) { if (log.element) { log.element.value += str + "\n"; log.element.scrollTop = 9999; } } function script (url) { var d = new Deferred(); var script = document.createElement('script'); script.type = "text/javascript"; script.src = url; script.onreadystatechange = function () { if (this.readyState == 'complete' || this.readyState == 'loaded') { log('Loaded: ' + url); d.call(); } }; script.onload = function () { log('Loaded: ' + url); d.call(); }; document.body.appendChild(script); return d; } function init () { document.getElementById('append-button').onclick = function () { newInput("") }; log.element = document.getElementById('log'); var params = getParams(); var scripts = []; var codes = params.code || []; if (!codes.length) { newInput("// input your code"); newInput("// input your code"); return; } var torun = []; for (var i = 0, len = codes.length; i < len; i++) if (codes[i]) { var code = codes[i]; var e = newInput(code); e.result.innerHTML = "waiting..."; e.code = code; e.sec = 0; e.n = 0; torun.push(e); } // calc function call cost var empty = { isEmpty : true, style : {}, result : {}, code : "", sec : 0, n : 0, speed : 0 }; torun.push(empty); var calculate_results = function (callback) { empty.speed = empty.sec / empty.n; var base = 0; for (var i = 0, len = torun.length; i < len; i++) { var run = torun[i]; if (run.isEmpty) continue; run.speed = run.sec / run.n - empty.speed; callback(run); if (run.speed > base) base = run.speed; } if (empty.speed && Math.random() < 0.01) log("Empty function call cost: " + empty.speed); for (var i = 0, len = torun.length; i < len; i++) { var run = torun[i]; if (run.isEmpty) continue; var rate = Math.floor(base / run.speed * 100); run.result.innerHTML += '<br/>' + rate + '%'; var level = 1 - run.speed / base; run.style.background = "hsl(" + (level * 230 - 10) + ", " + (level * 50 + 40) + "%, " + (level * 50 + 50) + "%)"; } }; var devideTime = 30; var totalTime = 3000; var phaseTotal = totalTime / devideTime; parallel(scripts). loop(phaseTotal, function (phase) { for (var i = 0, len = torun.length; i < len; i++) { torun[i]._rand = Math.random(); } torun.sort(function (a, b) { return a._rand - b._rand }); return loop(torun.length, function (i) { var run = torun[i]; return next(function () { var fun = new Function(run.code); run.className += " running"; // run.result.innerHTML = "running..."; var sec = 0, n = 0; return next(function () { var dt = new Date().getTime(); var nt; devide: { do { if (sec >= devideTime) break devide; n++; var ft = new Date().getTime(); fun(); nt = new Date().getTime(); sec += nt - ft; run.sec += nt - ft; run.n ++; } while (nt - dt < 25); // run.result.innerHTML = "running...<br/>total=" + run.sec + "msec / n=" + run.n + "<br/>speed=" + (run.sec / run.n); calculate_results(function (run) { run.result.innerHTML = "interim result, phase=" + (phase + 1) + "/" + phaseTotal + ":<br/>" + "total=" + run.sec + "msec / n=" + run.n + "<br/>speed=" + (run.speed); }); return call(arguments.callee); }; }). error(function (e) { run.result.innerHTML = "Error:" + e; }); }). next(function () { run.className = run.className.replace(/\s*running\s*/g, ""); }); }); }). next(function () { log('calculating results...'); calculate_results(function (run) { run.result.innerHTML = "done<br/>total=" + run.sec + "msec / n=" + run.n + "<br/>speed=" + run.speed; }); log('done'); }). error(function (e) { log(e); }); } }; <form action=""> <div id="inputs"></div> <p style="clear: both"> <input type="button" value="append code" id="append-button"/> <input type="submit" value="run" /> </p> </form> <textarea id="log" disabled="disabled" cols="50" rows="1"></textarea> <textarea id="template-input" class="template"> <div class="target"> <textarea name="code" cols="50" rows="8" class="code">#{code}</textarea> <div class="result"></div> </div> </textarea> body { font-family: "Lucida Console", "Monaco", sans-serif; font-size: 13px; background: #fff; } textarea { width: 100%; font-size: 11px; font-family: "Lucida Console", "Monaco", sans-serif; margin: 0; padding: 0; } textarea.template { display: none; } dd { margin : 0; padding: 0; } ul { list-style: none; margin : 0; padding: 0; } ul li { margin : 0; padding: 0; } .target { padding: 0; clear: both; } .target .code { opacity: 0.8; margin: 0 0 1em 0; width: 40em; height: 9em; float: left; } .target .result { height: 7em; padding: 0.5em 0; margin: 1em 0 0 41em; } .target.running { } #share { font-size: 10px; padding: 0.5em 1em; position: absolute; top: 0; right: 0; background: #000; color: #fff; opacity: 0.8; -moz-border-radius: 0.5em; } #share a , #share a:visited , #share a:link { color: #fff; text-decoration: none; } #description { } #description ul { list-style: disc; padding: 0 0 0 2em; } .target .code { width: 100%; height: 8em; float: none; margin: 0; padding: 0; } .target .result { width: 100%; margin: 0 0 1em 0; padding: 0.5em; height: auto; } form p input { display : none } use an iframe compat browser, deer Play on jsdo.it games Author Share ブログに埋め込む QR Tag Download Complete! Description What kind of game? based on http://cho45.stfuawsc.com/benchmark.html Fork して code という prefix を持った関数をグローバルにいくつか定義するだけでベンチマークが計れます。 jsdo.it だと HTML いじるベンチマークに便利かもしれません。 Control Device Smartphone Controllerjsdo.it WebSocket Controller» Mouse Keyboard Touch Device Fullscreen Activated Inactivated jsdo.it games から削除する Submit Author cho45 URLhttp://www.lowreal.net/ http://subtech.g.hatena.ne.jp/cho45/ うんこ〜 Tweet Default Panel Auto play Screenshot Readme JavaScript HTML CSS Size Width: px Height: px code <script type="text/javascript" src="http://jsdo.it/blogparts/xHLO/js"></script> benchmark Discussion Questions on this code? Tags benchmark cho45 Favorite by acrecord mersy yoshimax tsmallfield ToQoz: benchmark tokuhirom: wow! cool! sugyan: benchmarkcho45 Forked sort by latest page views favorite forked for of vs for cho45 00 555 261/18/101 benchmark get first child element benchm cho45 00 859 252/18/101 benchmark forked: Benchmark.javascript acrecord 00 1268 255/18/101 benchmark Benchmark: embed JS template e cho45 00 3769 255/78/101 benchmark coffeescript 1 2 3NEXT>>