朝の頭の体操に。
面白いな、と思ったのは、上記リンク先の話題を手元で試していたときに、
@data = map { rand 10 } (1..1e7); $sum += $_ for @data;
だとメモリーを喰いまくるのに、
$sum += rand 10 for 1..1e7;
だとほとんどメモリーを喰わないこと。後者も for
は配列を回すループなのに。この書き方に限っては、内部では配列を作らずに動作しているのだろうか?
試しに↓も試してみる。
@arr = 1..1e7; $sum += rand 10 for @arr;
これを、Win32 ActivePerl の環境で、タスクマネージャを起動しつつ、perl コマンドを呼び出してコンソール上で直打ちしていたわけですが (つまり、状況としては↓みたいな感じ)、
C:\Documents and Settings\murachi>perl @arr = 1..1e7; $sum += rand 10 for @arr; ^Z
面白いのは、以下の行を書いて [Enter] を押した時点で、タスクマネージャが perl コマンドプロセスによる大量のメモリー領域確保を検知したこと。
@arr = 1..1e7;
つまり、配列変数はコンパイル時に領域確保が行われる模様 (もちろん、変数の内容がコンパイル時に判別できる場合だけなんだろうけど)。結果として、最適化の余地がなくなってしまうわけか。
ループ文を含むスクリプトで異様にメモリーを喰いまくるのが気になる場合のチェックポイントとして認識しておくといいかも。ていうか、for
ループで回す配列に直接範囲演算子による式を渡すとメモリーを喰わないってのは予想外だった。
セコメントをする