ページ

2014年4月1日

JITはすごいんだよ、とか

前回のリフレクションのベンチマークはJITの影響を受けています。Javaはコンパイル時だけじゃなくって実行時にももっと早くコードを実行できないか考えてくれるすごい子なのです。またはJITがないと使い物にならない速度でしか動かないかもしれません。普通に使用する分には可愛い子なのですが、ベンチマークするにはJITは厄介な子です。実際のソフトウエアとベンチマークでは最適化のされ方が異なるので、速度がかなり違ってきます。

で、前回の結果をJITのあるなしで計測すると次のようになります。

JITあり
=======
$ java timing.TimeCalls
Java version 1.7.0_51
Java HotSpot(TM) 64-Bit Server VM
24.51-b03
Oracle Corporation

Direct call using member field:
 231 7 6 6 6
 average time = 6 ms.
Direct call using passed value:
 8 6 6 6 6
 average time = 6 ms.
Call to object using member field:
 30 6 7 6 7
 average time = 7 ms.
Call to object using passed value:
 12 7 6 6 7
 average time = 7 ms.
Reflection call using member field:
 74 32 30 37 31
 average time = 33 ms.
Reflection call using passed value:
 179 151 145 127 120
 average time = 136 ms.

Direct call using member field:
 7 7 6 3 6
 average time = 6 ms.
Direct call using passed value:
 6 6 6 7 5
 average time = 6 ms.
Call to object using member field:
 6 6 5 7 6
 average time = 6 ms.
Call to object using passed value:
 6 6 6 6 6
 average time = 6 ms.
Reflection call using member field:
 39 31 34 38 28
 average time = 33 ms.
Reflection call using passed value:
 114 117 114 117 112
 average time = 115 ms.

JITなし
=======
$ java -Djava.compiler=none timing.TimeCalls
Java version 1.7.0_51
Java HotSpot(TM) 64-Bit Server VM
24.51-b03
Oracle Corporation

Direct call using member field:
 711 669 665 664 670
 average time = 667 ms.
Direct call using passed value:
 732 732 742 751 740
 average time = 741 ms.
Call to object using member field:
 730 696 675 676 676
 average time = 681 ms.
Call to object using passed value:
 673 686 673 681 677
 average time = 679 ms.
Reflection call using member field:
 4505 4487 4444 4448 4441
 average time = 4455 ms.
Reflection call using passed value:
 7293 7342 7386 7318 7359
 average time = 7351 ms.

Direct call using member field:
 680 666 672 679 667
 average time = 671 ms.
Direct call using passed value:
 742 736 736 744 742
 average time = 740 ms.
Call to object using member field:
 671 673 671 672 670
 average time = 672 ms.
Call to object using passed value:
 681 679 674 670 670
 average time = 673 ms.
Reflection call using member field:
 4453 4563 4521 4593 4565
 average time = 4561 ms.
Reflection call using passed value:
 7453 7307 7323 7348 7415
 average time = 7348 ms.


まあ、JITありに比べてない方は100倍遅いですね。ただし、今回は傾向は同じです。別の種類のベンチマークだと傾向が同じになるとは限りません。今回はループで何回も回していますが、最適化のされ方によってはループが回らなかったりします。

最終的にはDaoでDTOに値を詰めるって話にするつもりで、その場合メソッドの直接の呼び出しだとコストはほとんどかからない、リフレクションだとこれくらい、バイトコードを作るのはリフレクションよりは速そうだ、ってことぐらいがわかればイイかな、と。

本当はhibernateを使うのがいいのですが、これからのhibernateの導入は敷居が高いので、それじゃ似たようなコードのコピペをせずに、daoのコードをどれくらい少なくできるのか?ってことです。


それから、昔10倍遅かったと記憶していましたが、JITなしではちょうど10倍ぐらい遅いですね。記憶はあっていたのかもしれません。



http://www.ibm.com/developerworks/jp/java/library/j-jtp12214/

0 件のコメント: