mapとforeachのベンチマーク
趣旨
map
とforeach
のどちらが効率的かは昔から話題になっている- 可読性を考えたら
foreach
一択なんだけど、map
のほうが効率的な場合があるかもしれない- 変数を明示的に作る場合と、暗黙的に作る場合で何か違うかもしれない
- 確認してみよう
参考リンク
- 2019年 Writing faster Perl code • Wim Vanderbauwhede
- 2011年 Benchmarking in Perl: Map versus For Loop | End Point Dev
- perlperf
- Time Efficiency - Programming Perl
環境
デバイス
プロセッサ 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
が優勢
容量が大きくなるとメモリの確保に時間がかかるだけのような気がする。
配列に要素を追加するケース
- 配列の容量が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% --
配列の要素を変更するケース
- 配列の容量が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% --