javascript 前後の空白の除去処理で「trim」と「replace(正規表現)」のパフォーマンスを計測する

javascript 前後の空白の除去処理で「trim」と「replace(正規表現)」のパフォーマンスを計測する

javascriptで、「trim」と「replace(正規表現)」で前後の空白の除去処理を行った時のパフォーマンスを計測するサンプルコードを記述してます。

環境

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

パフォーマンス計測

「performance.now」を使用して、「trim」と「replace(正規表現)」を使用して、
前後の空白の除去処理を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)`);
  }

  let str = "  abc  "
  
  // 計測
  start = performance.now();
  
    for (let i = 0; i < times; ++i) {
      str.trim();
    }
  
  end = performance.now();
  
  benchmark('trim', start, end);
  
  // 計測
  start = performance.now();
  
    for (let i = 0; i < times; ++i) {
      str.replace(/(^\s+)|(\s+$)/g,'');
    }
  
  end = performance.now();
  
  benchmark('replace', start, end);
  
</script>

実行結果(chrome 103.0.5060.134)

<1回目>
実行回数:1000000回 関数名:trim     実行時間:45.7(ms)
実行回数:1000000回 関数名:replace  実行時間:119(ms)

<2回目>
実行回数:1000000回 関数名:trim     実行時間:99.3(ms)
実行回数:1000000回 関数名:replace  実行時間:159(ms)

<3回目>
実行回数:1000000回 関数名:trim     実行時間:60.7(ms)
実行回数:1000000回 関数名:replace  実行時間:124(ms)

「trim」の方がいいという結果になりました。

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

<1回目>
実行回数:1000000回 関数名:trim     実行時間:99.0(ms)
実行回数:1000000回 関数名:replace  実行時間:144(ms)

<2回目>
実行回数:1000000回 関数名:trim     実行時間:43.0(ms)
実行回数:1000000回 関数名:replace  実行時間:138(ms)

<3回目>
実行回数:1000000回 関数名:trim     実行時間:40.0(ms)
実行回数:1000000回 関数名:replace  実行時間:197(ms)

safari15.5では、逆の結果となりました。

<1回目>
実行回数:1000000回 関数名:trim     実行時間:78.0(ms)
実行回数:1000000回 関数名:replace  実行時間:22.0(ms)

<2回目>
実行回数:1000000回 関数名:trim     実行時間:79.0(ms)
実行回数:1000000回 関数名:replace  実行時間:22.0(ms)

<3回目>
実行回数:1000000回 関数名:trim     実行時間:82.0(ms)
実行回数:1000000回 関数名:replace  実行時間:23.0(ms)

「trimStart」と「trimEnd」

「trimStart」と「trimEnd」も正規表現を使用した場合とパフォーマンスを比較してみます。

<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 str = "  abc  "

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

  for (let i = 0; i < times; ++i) {
    str.trimStart();
  }

  end = performance.now();

  benchmark('trimStart', start, end);

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

  for (let i = 0; i < times; ++i) {
    str.replace(/^\s+/g, '');
  }

  end = performance.now();

  benchmark('replace(/^\s+/g)', start, end);

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

  for (let i = 0; i < times; ++i) {
    str.trimEnd();
  }

  end = performance.now();

  benchmark('trimEnd', start, end);

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

  for (let i = 0; i < times; ++i) {
    str.replace(/\s+$/g,'');
  }

  end = performance.now();

  benchmark('replace(/\s+$/g)', start, end);

</script>

実行結果(chrome 103.0.5060.134)

<1回目>
実行回数:1000000回 関数名:trimStart 実行時間:64.7(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:82.3(ms)
実行回数:1000000回 関数名:trimStart 実行時間:30.0(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:91.4(ms)

<2回目>
実行回数:1000000回 関数名:trimStart 実行時間:49.6(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:79.4(ms)
実行回数:1000000回 関数名:trimEnd 実行時間:28.5(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:103(ms)

<3回目>
実行回数:1000000回 関数名:trimStart 実行時間:33.1(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:75.7(ms)
実行回数:1000000回 関数名:trimEnd 実行時間:28.9(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:92.8(ms)

こちらも正規表現よりも「trim」の方がいいという結果になりました。

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

<1回目>
実行回数:1000000回 関数名:trimStart 実行時間:53.0(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:99.0(ms)
実行回数:1000000回 関数名:trimEnd  実行時間:41.0(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:115(ms)

<2回目>
実行回数:1000000回 関数名:trimStart 実行時間:44.0(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:101(ms)
実行回数:1000000回 関数名:trimEnd  実行時間:40.0(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:117(ms)

<3回目>
実行回数:1000000回 関数名:trimStart 実行時間:43.0(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:110(ms)
実行回数:1000000回 関数名:trimEnd  実行時間:47.0(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:118(ms)

safari15.5では、「trimStart」の場合は「正規表現」の方が速く「trimEnd」は、ほぼ同じという結果になりました。

<1回目>
実行回数:1000000回 関数名:trimStart 実行時間:72.0(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:24.0(ms)
実行回数:1000000回 関数名:trimEnd  実行時間:67.0(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:68.0(ms)

<2回目>
実行回数:1000000回 関数名:trimStart 実行時間:72.0(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:24.0(ms)
実行回数:1000000回 関数名:trimEnd  実行時間:70.0(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:74.0(ms)

<3回目>
実行回数:1000000回 関数名:trimStart 実行時間:73.0(ms)
実行回数:1000000回 関数名:replace(/^s+/g) 実行時間:26.0(ms)
実行回数:1000000回 関数名:trimEnd  実行時間:70.0(ms)
実行回数:1000000回 関数名:replace(/s+$/g) 実行時間:70.0(ms)