ページ

2014年4月1日

あれからJavaのリフレクションのスピードはどうなったのか?

僕が一番最近Javaのリフレクションのパフォーマンスを計測したのは、今のアリエルの開発を始めたぐらいで、ライブラリの選定をしている時でした。jdkのバージョンも覚えていません。それより前はいつやったのか覚えていません。
その時の結果の詳細は残っていませんが、リフレクションは通常のアクセスより10倍以上遅い、って印象だけが残っています。印象でものを語るのは良くないし、バージョンが上がるに連れて改善されているのかもしれないので、もう一度計測してみました。

以前は自分でコードを書いていたのですが、今回はサボって http://www.ibm.com/developerworks/jp/java/library/j-dyn0603/ にあるコードで試します。このページには1.4での計測結果ものっていて、いいかも。

ちなみに、今回はLinux上のSunのJDKでコンパイル・ビルド・実行しています。それから、結果に乗っている最初の一回目の数値は無視してください。

まず、リフレクションでオブジェクトを作るときの結果です。

Java version 1.7.0_51
Java HotSpot(TM) 64-Bit Server VM
24.51-b03
Oracle Corporation

Direct Object creation:
 49 1 2 1 2
 average time = 2 ms.
Reflection Object creation:
 44 3 3 2 3
 average time = 3 ms.
Direct byte[8] creation:
 10 7 8 11 10
 average time = 9 ms.
Reflection byte[8] creation:
 12 8 8 8 8
 average time = 8 ms.
Direct byte[64] creation:
 101 79 37 8 7
 average time = 33 ms.
Reflection byte[64] creation:
 7 7 7 8 8
 average time = 8 ms.

Direct Object creation:
 2 2 1 3 1
 average time = 2 ms.
Reflection Object creation:
 2 4 5 4 4
 average time = 4 ms.
Direct byte[8] creation:
 9 6 7 8 8
 average time = 7 ms.
Reflection byte[8] creation:
 8 8 10 9 8
 average time = 9 ms.
Direct byte[64] creation:
 9 8 11 9 7
 average time = 9 ms.
Reflection byte[64] creation:
 9 11 11 10 8
 average time = 10 ms.

オブジェクトの作成は若干リフレクションの方が遅いですが、使用用途にもよりますが、この程度であればリフレクションを使ってもそれほどオーバーヘッドもなく、問題ないでしょう。


次にオブジェクトの中のフィールドへのアクセスです。昔、偉い人が「privateなんて飾りです。リフレクションをシラン人はわからんのです。」って言っていましたが、それがこういうことです。
で、結果ですが、


Java version 1.7.0_51
Java HotSpot(TM) 64-Bit Server VM
24.51-b03
Oracle Corporation

Direct access using member field:
 8 6 6 7 6
 average time = 6 ms.
Reference access to member field:
 28 7 7 5 7
 average time = 7 ms.
Reflection access to member field:
 3544 3486 3437 3433 3482
 average time = 3460 ms.

Direct access using member field:
 7 5 7 6 6
 average time = 6 ms.
Reference access to member field:
 6 6 6 6 6
 average time = 6 ms.
Reflection access to member field:
 3538 3555 3515 3545 3482
 average time = 3524 ms.

で、reference accessはまあ、どうでもいいです。reflection accessだと、10倍どころじゃないですね。600倍ぐらい遅いです。数回だけならまだしも、アクセス数が増えると使い物にならないですね。JRubyとかJPythonは、基本的にメンバー変数に直接アクセスはしないんだろうか?

最後にメソッドの呼び出しです。

Java version 1.7.0_51
Java HotSpot(TM) 64-Bit Server VM
24.51-b03
Oracle Corporation

Direct call using member field:
 8 7 6 6 3
 average time = 6 ms.
Direct call using passed value:
 11 6 3 6 7
 average time = 6 ms.
Call to object using member field:
 10 6 7 7 6
 average time = 7 ms.
Call to object using passed value:
 8 6 5 7 6
 average time = 6 ms.
Reflection call using member field:
 71 32 30 29 33
 average time = 31 ms.
Reflection call using passed value:
 158 139 138 122 117
 average time = 129 ms.

引数なしでの呼び出しは、通常の5倍遅いです。引数ありでは20倍の遅さです。メンバー変数へ直接アクセスすするよりは、メソッドを通してアクセスするほうが効率は良さそうですね。

IBMのサイトの結果と比べると…、IBMのサイトのグラフが対数になっていて、よくわかりません。多分、あんまり変わっていないです。

ということで、

- リフレクションでのオブジェクトの作成はオーバーヘッドがほとんどない
- メンバーフィールドにアクセスするのは遅すぎるのでやらないほうがいい。
- メソッド呼び出しは5から20倍遅いので、使う場合は注意する

1 件のコメント:

for IT the さんのコメント...

I have read your blog its very attractive and impressive. I like it your blog.

Java Training in Chennai Core Java Training in Chennai Core Java Training in Chennai

Java Online Training Java Online Training Core Java 8 Training in Chennai Core java 8 online training JavaEE Training in Chennai Java EE Training in Chennai