mapとforeachのベンチマーク

趣旨

  • mapforeachのどちらが効率的かは昔から話題になっている
  • 可読性を考えたらforeach一択なんだけど、mapのほうが効率的な場合があるかもしれない
    • 変数を明示的に作る場合と、暗黙的に作る場合で何か違うかもしれない
  • 確認してみよう

参考リンク

環境

バイス

プロセッサ   Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz   1.99 GHz
実装 RAM  16.0 GB (15.8 GB 使用可能)
システムの種類 64 ビット オペレーティング システム、x64 ベース プロセッサ

システム

エディション  Windows 11 Pro
バージョン   22H2
OS ビルド  22621.819
エクスペリエンス    Windows Feature Experience Pack 1000.22636.1000.0

Perl ランタイム

perl --version

This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread

結果

まとめ

  • 配列の容量が1000以下ではforeachが優勢
  • 配列の容量が1000以上ではmapが優勢

容量が大きくなるとメモリの確保に時間がかかるだけのような気がする。

配列に要素を追加するケース

steph-skardal.pl

  • 配列の容量が1000以下ではforeachが優勢
  • 配列の容量が1000以上ではmapが優勢
$ perl steph-skardal.pl
#listsize=3
Benchmark: timing 10000 iterations of foreach, map...
   foreach: 0.0579259 wallclock secs ( 0.05 usr +  0.00 sys =  0.05 CPU) @ 212765.96/s (n=10000)
            (warning: too few iterations for a reliable count)
       map: 0.0469069 wallclock secs ( 0.03 usr +  0.00 sys =  0.03 CPU) @ 322580.65/s (n=10000)
            (warning: too few iterations for a reliable count)
            Rate foreach     map
foreach 212766/s      --    -34%
map     322581/s     52%      --
#listsize=100
Benchmark: timing 10000 iterations of foreach, map...
   foreach: 1.04346 wallclock secs ( 1.01 usr +  0.00 sys =  1.01 CPU) @ 9852.22/s (n=10000)
       map: 0.977082 wallclock secs ( 0.92 usr +  0.00 sys =  0.92 CPU) @ 10857.76/s (n=10000)
           Rate foreach     map
foreach  9852/s      --     -9%
map     10858/s     10%      --
#listsize=1000
Benchmark: timing 10000 iterations of foreach, map...
   foreach: 11.135 wallclock secs ( 9.31 usr +  0.00 sys =  9.31 CPU) @ 1073.88/s (n=10000)
       map: 10.9311 wallclock secs ( 9.63 usr +  0.00 sys =  9.63 CPU) @ 1038.96/s (n=10000)
          Rate     map foreach
map     1039/s      --     -3%
foreach 1074/s      3%      --
#listsize=10000
Benchmark: timing 10000 iterations of foreach, map...
   foreach: 152.767 wallclock secs (108.44 usr +  1.19 sys = 109.62 CPU) @ 91.22/s (n=10000)
       map: 138.602 wallclock secs (123.38 usr +  0.45 sys = 123.83 CPU) @ 80.76/s (n=10000)
          Rate     map foreach
map     80.8/s      --    -11%
foreach 91.2/s     13%      --

配列の要素を変更するケース

wim-vanderbauwhede.pl

  • 配列の容量が1000以下ではfor-index/foreachが優勢
  • 配列の容量が1000以上ではmapが優勢
$ perl wim-vanderbauwhede.pl
#listsize=3
Benchmark: timing 10000 iterations of for-index, foreach, map...
 for-index: 0.0232739 wallclock secs ( 0.02 usr +  0.00 sys =  0.02 CPU) @ 625000.00/s (n=10000)
            (warning: too few iterations for a reliable count)
   foreach: 0.023376 wallclock secs ( 0.02 usr +  0.00 sys =  0.02 CPU) @ 625000.00/s (n=10000)
            (warning: too few iterations for a reliable count)
       map: 0.0108192 wallclock secs ( 0.00 usr +  0.00 sys =  0.00 CPU)
            (warning: too few iterations for a reliable count)
                            Rate         for-index           foreach         map
for-index               625000/s                --                0%       -100%
foreach                 625000/s                0%                --       -100%
map       10000000000000000000/s 1600000000000000% 1600000000000000%          --
#listsize=100
Benchmark: timing 10000 iterations of for-index, foreach, map...
 for-index: 0.219677 wallclock secs ( 0.17 usr +  0.00 sys =  0.17 CPU) @ 58139.53/s (n=10000)
            (warning: too few iterations for a reliable count)
   foreach: 0.194073 wallclock secs ( 0.17 usr +  0.00 sys =  0.17 CPU) @ 58479.53/s (n=10000)
            (warning: too few iterations for a reliable count)
       map: 0.145457 wallclock secs ( 0.14 usr +  0.00 sys =  0.14 CPU) @ 71428.57/s (n=10000)
            (warning: too few iterations for a reliable count)
             Rate for-index   foreach       map
for-index 58140/s        --       -1%      -19%
foreach   58480/s        1%        --      -18%
map       71429/s       23%       22%        --
#listsize=1000
Benchmark: timing 10000 iterations of for-index, foreach, map...
 for-index: 1.72424 wallclock secs ( 1.59 usr +  0.00 sys =  1.59 CPU) @ 6277.46/s (n=10000)
   foreach: 1.48833 wallclock secs ( 1.44 usr +  0.00 sys =  1.44 CPU) @ 6958.94/s (n=10000)
       map: 1.74567 wallclock secs ( 1.47 usr +  0.00 sys =  1.47 CPU) @ 6807.35/s (n=10000)
            Rate for-index       map   foreach
for-index 6277/s        --       -8%      -10%
map       6807/s        8%        --       -2%
foreach   6959/s       11%        2%        --
#listsize=10000
Benchmark: timing 10000 iterations of for-index, foreach, map...
 for-index: 22.525 wallclock secs (16.39 usr +  0.03 sys = 16.42 CPU) @ 608.94/s (n=10000)
   foreach: 20.2237 wallclock secs (15.06 usr +  0.00 sys = 15.06 CPU) @ 663.88/s (n=10000)
       map: 18.1616 wallclock secs (16.62 usr +  0.00 sys = 16.62 CPU) @ 601.50/s (n=10000)
           Rate       map for-index   foreach
map       602/s        --       -1%       -9%
for-index 609/s        1%        --       -8%
foreach   664/s       10%        9%        --