より速くてよりカッコいいfor文の書き方の後日談です。
前回の記事で、ソースコードをそのまま実行しても意図した処理時間にならないだろう、と書きました。では、意図した結果を得るにはどうすればいいのでしょうか。もったいぶってもしょうがないので答えを明かすと、ソースコード実行時にVMの引数に「-Djava.compiler=none」を指定すれば良いです。
Eclipseから実行する場合の指定指定方法は、以下の画像を参考にしてください。
まず、結果の比較をお見せします。
普通に実行 | VMの引数に「-Djava.compiler=none」を指定 | |||
A | B | A | B | |
1000000 | 4400171 | 3167404 | 118125490 | 92536404 |
2000000 | 0 | 0 | 186552861 | 149656440 |
3000000 | 367 | 0 | 265899392 | 230039448 |
4000000 | 367 | 0 | 368930824 | 304640560 |
5000000 | 367 | 367 | 458535003 | 367827938 |
6000000 | 367 | 367 | 539762604 | 464423300 |
7000000 | 367 | 367 | 619440808 | 521417858 |
8000000 | 367 | 0 | 721453740 | 696986252 |
9000000 | 367 | 367 | 813360185 | 671461372 |
10000000 | 367 | 367 | 905812202 | 728707987 |
A.for(int i=0; i<list.size(); i++)、B.for(int i=0, size=list.size(); i<size; i++)
普通に実行した場合、最初の1000000回以外が劇的に早くなっています。
何が起きてる?
普通に実行した場合、最初はゆっくりですが、途中から劇的に速くなっています。この動作は、Java VMの「HotSpot」という技術が関係しています(本当にそうなのかは、中まで覗いた訳じゃないので推測ですが)。
「HotSpot」の文字が示す通り、Java VMはプログラムを実行中に「ホットスポット」が無いか監視します。一般的な意味での「ホットスポット」とは、局地的に何らかの値が高かったり、局地的に何らかの活動が活発であったりする地点・場所・地域の事です。プログラム中のホットスポットとは、頻繁に実行されるロジックの事です。Java VMはホットスポットを発見すると、次はJust-In-Time(JIT)コンパイラが動作し、ホットスポットを高速に実行できるように最適化(局所的にコンパイルする等)します。
つまり、Javaは実行中にJITコンパイラが動作するため、処理を繰り返すうちにパフォーマンスが大幅に変化する可能性があります。大半のアプリにとっては好ましい事ですが、ベンチマークプログラムにとっては悩ましい挙動です。ちなみに、Java VMに対する「-Djava.compiler=none」の指定の意味は、JITコンパイラには休んでもらい常にインタプリタとして動作させるための指定です。
オチ
JITコンパイラの技術が使用されている動作環境(Javaや.NET)では、パフォーマンスが激しく変化する可能性があります。
つまり、パフォーマンスがジッとしてくれない訳ですね、JIT(ジッと)コンパイラのせいで。
・・・お後がよろしいようで。