ジッとしてくれないJava VM

Pocket

より速くてよりカッコいいfor文の書き方の後日談です。

前回の記事で、ソースコードをそのまま実行しても意図した処理時間にならないだろう、と書きました。では、意図した結果を得るにはどうすればいいのでしょうか。もったいぶってもしょうがないので答えを明かすと、ソースコード実行時にVMの引数に「-Djava.compiler=none」を指定すれば良いです。

Eclipseから実行する場合の指定指定方法は、以下の画像を参考にしてください。
jit

まず、結果の比較をお見せします。

普通に実行 VMの引数に「-Djava.compiler=none」を指定
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(ジッと)コンパイラのせいで。
・・・お後がよろしいようで。

Pocket

コメントを残す

メールアドレスが公開されることはありません。