このエントリーをはてなブックマークに追加 hatena-bookmark fb-like g-plusone
line-it
pocket
  • 作成日時:
  • 更新日時:

JavaScriptで渡された配列引数をディープコピーする場合デフォルト引数を適当に使うより引数省略を検知してディープコピーを省略したほうが高速

とあるpull requestで.JavaScriptクラスのコンストラクタで.配列引数にundefinedが渡されていることをtypeof foo === 'undefined'によって検知して.引数が省略されている場合new Arrayして,引数が省略されていなかった場合配列のディープコピーを行っているのを見ました.

私は見た,思った,書いた.「それデフォルト引数設定すれば良くないですか?」

とすると「引数を省略した場合配列のディープコピーが生じるのでかなりの無駄になる」と返されました.

私はそんなことで大した差が生じるとは思えなかったので,とりあえず計測するコードを書きました.

JavaScriptのベンチマークツールもっと良いのが知りたいです.

const Benchmark = require('benchmark');

class DefaultArg {
    constructor(foo = (new Array(19 * 19)).fill(0)) {
        this.bar = [...foo];
    }
}

class IfSet {
    constructor(foo) {
        if (typeof foo === 'undefined') {
            foo = new Array(
                19 * 19
            );
            foo.fill(0);
            this.bar = foo;
        } else {
            this.bar = [...foo];
        }
    }
}

const suite = new Benchmark.Suite;

// add tests
suite.add('DefaultArg', () => {
    new DefaultArg()
}).add('IfSet', () => {
    new IfSet()
}).on('cycle', function(event) {
    console.log(String(event.target));
}).on('complete', function() {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
}).run();
2018-03-02T17:23:45 ncaq@karen/pts/7(0) ~/Documents/archive/2018-03
% node default-arg-vs-if-set.js
DefaultArg x 62,730 ops/sec ±0.74% (92 runs sampled)
IfSet x 1,443,601 ops/sec ±0.69% (90 runs sampled)
Fastest is IfSet

予想に反して手動検知するほうがかなり速いことがわかりました.

V8の最適化を過信しすぎていたようですね.あとパフォーマンスの肌感覚が身についていなかった.

まあ私が書く時は今後もデフォルト引数を適当に使っていきますが,気にする人にも正当性があることがわかりました.

このエントリーをはてなブックマークに追加 hatena-bookmark fb-like g-plusone
line-it
pocket