LoginSignup
6
7

More than 5 years have passed since last update.

Benckmark.js で node.js 環境 と ブラウザ(PhantomJS)でベンチマーク

Last updated at Posted at 2013-09-16

これまで ブラウザ側でベンチマーク取ったことなかったので、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
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7