Celeron2.7GHz メモリ1GB Debian sidな環境で実行。20回試行した平均。
-
origは元のプログラム。
-
xrange は for に書かれている range(num) を xrange(num) に変えたもの。
-
xrange,1 は、上に加えてリストの要素 (x,y) を単なる整数の 1 に変えたもの。
-
*2.3/2.4/2.5 はそれぞれPythonのバージョン 2.3.5, 2.4.4, 2.5 に対応。
-
引数は1000を与えた
-
数字は1回あたりの実行時間をあらわし、単位は秒
| orig | xrange | xrange,1 | |
| for_comp2.3 | 0.91 | 0.78 | 0.29 |
| for_comp2.4 | 0.81 | 0.49 | 0.27 |
| for_comp2.5 | 0.75 | 0.52 | 0.24 |
| list_comp2.3 | 1.00 | 0.53 | 0.23 |
| list_comp2.4 | 0.89 | 0.43 | 0.22 |
| list_comp2.5 | 0.81 | 0.44 | 0.19 |
この結果からわかることは
-
ループ内の処理が割と小さいxrange,1 では 同じバージョンでリスト内包表記とforループを比べるとリスト内包表記のほうが速いようだ。
-
100万回のループで50msecから60msec程度。
-
注: res.appendの呼び出しが遅いだけかもしれない。
-
元のコードではリスト内包表記のほうが常に遅い。
-
Python処理系のバージョンがあがるに従ってどちらも高速化されている。
-
このような単純な例ですら、ループ処理の形式よりループ内で実行される処理のほうが支配的。 つまり実用上は(実行時間最適化をしようとしているときですら)常にループの形式による速度の差は2番手、3番手の関心事になる。
-
例: range を xrange にするだけで230msecから470msec程度、ループ形式の違いより1桁大きい。
-
自作のベンチマークルーチンでは対象関数を20回連続で実行するため、このrangeとxrangeの大きな差はGCの処理量にあるのかもしれない。
結論: リスト内包表記にしろforにしろ気になるほどの違いはないので、その場の意図が伝わりやすい書き方を選択するべき。
補足: 現状のdebianにはpython2.5用のpsycoがないため省略したが、psyco を利用することで orig で for_comp2.3: 0.277, list_comp2.3: 0.279 となった。速度が問題になる際にはまずpsycoの利用を考えるべきだろう。
