これまで ブラウザ側でベンチマーク取ったことなかったので、node.js と ブラウザの両方で動作するモジュールでベンチマーク取ってみた。
構成は以下のとおり
.
|-- b/
| |-- bench.html
| |-- bench.js
| |-- drive.js
| `-- run-phantom.js
|-- index.js
|-- node_modules/
`-- benchmark/
`-- benchmark.js
-
b/
ベンチマーク関係のディレクトリ -
b/bench.html
htmlファイル -
b/bench.js
ベンチマークスイートファイル -
b/driver.js
htmlにベンチマークの結果を表示するドライバーjs -
b/run-phantom.js
phantomjs で *.html を開くランナーjs -
index.js
モジュール本体
index.js
(function (global) {
'use strict'
var isBrowser = !! global.self
var isNodeJS = !! global.global
function curry (f) {
var args = []
var bind = function (x) {
args.push(x)
return (args.length >= f.length) ? f.apply(null, args) : bind
}
return bind
}
if (isNodeJS) {
module.exports = curry
}
else {
global.curry = curry
}
})(this.self || global)
bench.js
(function (global) {
'use strict'
var isBrowser = !! global.self
var isNodeJS = !! global.global
var Benchmark, suite, path, curry, onError
if (isNodeJS) {
path = require('path')
curry = require(path.join( __dirname, '../index'))
Benchmark = require('benchmark').Benchmark
suite = new Benchmark.Suite
onError = function (err) {
console.error(err)
process.exit(1)
}
}
else {
curry = global.curry
Benchmark = global.Benchmark
suite = global.suite = new Benchmark.Suite
onError = function (err) {
console.log(err)
}
}
function area (x, y) { return x * y }
function sq (x, y, z) { return area(area(x, y), z) }
var x = 2, y = 3, z = 4
suite.add('(x * y * z)', function () {
(x * y * z) === 24
})
.add('sq(x, y, z)', function () {
sq(x, y, z) === 24
})
.add('curry(sq)(x)(y)(z)', function () {
curry(sq)(x)(y)(z) === 24
})
.on('error', onError)
.on('cycle', function (ev) {
console.log(String(ev.target))
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').pluck('name')
})
.run({async: true})
})(this.self || global)
dirve.js
(function (global) {
'use strict'
if ((! console) || typeof console.log !== 'function')
throw new Error('"console.log" not found')
var x = {
count: 0
, dom: document.querySelector('#status')
, toString: function (x) { return Object.prototype.toString.apply(x) }
}
var colors = {
complete: '#00ff00'
, error: '#ff0000'
, cycle: '#ffff00'
}
Object.keys(colors).forEach(function (level) {
x[level] = function (msg) {
if (this.toString(msg) === '[object Error]')
msg = msg.toString()
document.title = this.dom.innerHTML = msg
this.dom.setAttribute('style', 'background-color:' + colors[level])
}
})
var y = {
dom: document.querySelector('#tests')
, append: function (str) {
var li = document.createElement('li')
li.innerHTML = str
this.dom.appendChild(li)
}
}
var log = console.log
console.log = function (str) {
y.append(str)
log.apply(console, arguments)
}
global.suite.on('error', function (err) {
x.error(err)
})
.on('cycle', function () {
x.cycle( 'Running Benchmark [' + (x.count += 1) + '/'
+ this.length + ']' )
})
.on('complete', function () {
x.complete( 'Running Benchmark [' + this.length + '/'
+ this.length + ']' )
})
})(this)
bench.html
<!doctype html>
<head>
<meta charset="utf-8" />
<script src="../index.js"></script>
<script src="../node_modules/benchmark/benchmark.js"></script>
<title>Benchmark - curry</title>
</head>
<body>
<div id="status"></div>
<div id="contents">
<div id="result"></div>
<ol id="tests"></ol>
</div>
</body>
<script src="./bench.js"></script>
<script src="./drive.js"></script>
run-phantom.js
#!/usr/bin/env phantomjs
var system = require('system')
if (system.args.length !== 2) {
console.log('usage: ./run-phantom.js URL')
phantom.exit(1)
}
var page = require('webpage').create()
page.onConsoleMessage = function (msg) {
console.log(msg)
}
page.open(system.args[1], function (isStatus) {
if (isStatus !== 'success') {
console.log('can not access network')
return process.exit(1)
}
console.log('fetch ok ... ' + system.args[1])
setInterval(function () {
var completed = page.evaluate(function () {
return /^Complete\s/.test(document.title)
})
if (completed) phantom.exit(0)
}, 250)
})
ベンチマークを取る
node.js 環境
$ node b/bench.js
PhantomJS 環境
$ phantomjs b/run-phantom.js b/bench.html