javascript ランダムな配列の生成処理で「Array.apply」と「Array().fill」のパフォーマンスを計測する

javascript ランダムな配列の生成処理で「Array.apply」と「Array().fill」のパフォーマンスを計測する

javascriptで、「Array.apply」と「Array().fill」でランダムな配列の生成処理を行った時のパフォーマンスを計測するサンプルコードを記述してます。

環境

  • OS windows11 pro 64bit
  • Apache 2.4.43
  • ブラウザ chrome 103.0.5060.114

パフォーマンス計測

「performance.now」を使用して、「Array.apply」と「Array().fill」を使用して、
ランダムな5個の値がある配列を生成する処理を100万回実行し、パフォーマンスを計測するサンプルコードとなります。

<script>

    // 実行回数
    const times = 1_000_000;

    // 空白を埋めるだけの関数
    function spacePadding(val, n = 8) {
        for (; val.length < n; val += ' ');
        return val;
    }

    // 計測結果を表示
    const benchmark = (name, start, end) => {
        let report = (end - start).toPrecision(3);
        // 表示を見やすくするため関数名に空白を埋める
        name = spacePadding(name)
        console.log(`実行回数:${times}回 関数名:${name} 実行時間:${report}(ms)`);
    }

    // 計測
    start = performance.now();

    for (let i = 0; i < times; ++i) {
        Array.apply(null, { length: 5 }).map((x) => ~~(Math.random() * 10))
    }

    end = performance.now();

    benchmark('Array.apply', start, end);

    // 計測
    start = performance.now();

    for (let i = 0; i < times; ++i) {
        Array(5).fill().map(x => ~~(Math.random() * 10))
    }

    end = performance.now();

    benchmark('Array().fill()', start, end);

</script>

実行結果(chrome 103.0.5060.114)

<1回目>
実行回数:1000000回 関数名:Array.apply 実行時間:513(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:296(ms)

<2回目>
実行回数:1000000回 関数名:Array.apply 実行時間:519(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:303(ms)

<3回目>
実行回数:1000000回 関数名:Array.apply 実行時間:534(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:300(ms)

Array().fillの方がいいという結果になりました。

firefox97.0の場合も、同じような結果になりました。

<1回目>
実行回数:1000000回 関数名:Array.apply 実行時間:459(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:146(ms)

<2回目>
実行回数:1000000回 関数名:Array.apply 実行時間:453(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:142(ms)

<3回目>
実行回数:1000000回 関数名:Array.apply 実行時間:470(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:141(ms)

for文を使用

for文を使用した場合は、forが一番パフォーマンスもよくなります。

<script>

    // 実行回数
    const times = 1_000_000;

    // 空白を埋めるだけの関数
    function spacePadding(val, n = 8) {
        for (; val.length < n; val += ' ');
        return val;
    }

    // 計測結果を表示
    const benchmark = (name, start, end) => {
        let report = (end - start).toPrecision(3);
        // 表示を見やすくするため関数名に空白を埋める
        name = spacePadding(name)
        console.log(`実行回数:${times}回 関数名:${name} 実行時間:${report}(ms)`);
    }

    let arr = []
    // 計測
    start = performance.now();
   
    for (let i = 0; i < times; ++i) {

        arr = []

        for (let j = 0; j < 5; j++) {
            arr.push(~~(Math.random() * 10)); // 生成
        }
    }

    end = performance.now();

    benchmark('for', start, end);

    // 計測
    start = performance.now();

    for (let i = 0; i < times; ++i) {
        Array.apply(null, { length: 5 }).map((x) => ~~(Math.random() * 10))
    }

    end = performance.now();

    benchmark('Array.apply', start, end);

    // 計測
    start = performance.now();

    for (let i = 0; i < times; ++i) {
        Array(5).fill().map(x => ~~(Math.random() * 10))
    }

    end = performance.now();

    benchmark('Array().fill()', start, end);

</script>

実行結果(chrome 103.0.5060.114)

実行回数:1000000回 関数名:for      実行時間:85.9(ms)
実行回数:1000000回 関数名:Array.apply 実行時間:489(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:328(ms)

e実行結果(firefox 97.0)

実行回数:1000000回 関数名:for      実行時間:96.0(ms)
実行回数:1000000回 関数名:Array.apply 実行時間:436(ms)
実行回数:1000000回 関数名:Array().fill() 実行時間:134(ms)