反射のいくつかの部分は非常にうまく行っていないことを、言われています。それは本当ですか、それのどの部分が遅いと思われますか?
背景:現在、リフレクションを使用して自己書き残し層を試しています。私はまだ測定をしていない。私は、最適化の可能な点がどこにあるのかを知る必要があるので、プログラムをうまく設計することができます。
反射のいくつかの部分は非常にうまく行っていないことを、言われています。それは本当ですか、それのどの部分が遅いと思われますか?
背景:現在、リフレクションを使用して自己書き残し層を試しています。私はまだ測定をしていない。私は、最適化の可能な点がどこにあるのかを知る必要があるので、プログラムをうまく設計することができます。
リフレクションを使用するほとんどのフレームワークでは、リフレクション操作の結果をキャッシュするので、リフレクション操作を再度実行する必要はありません。実際、起動時にすべてが一度起こります。
それ以外は、すべての部分が「不適格」です。通常のコードではリフレクションAPI全体を避ける必要があります。フレームワークの場合 - 第1段落を参照してください。
オブジェクトc = klass.newInstance()の反射的な作成をどのようにキャッシュしますか? –
@Pangea - もちろん、作成はキャッシュできません。しかし、他のすべてのメタデータはです。 – Bozho
お返事ありがとうございます。私が使用するFieldオブジェクトをキャッシュすることを検討します。 – user573215
通常、メソッド呼び出しがうまく機能します。パフォーマンスの問題は、Class.getMethod()
、Class.getField()
、Class.getDeclaredMethod()
などClass.forName()
でも発生します(リフレクションよりも動的なクラスローディングですが)。
このように、メソッドの配置方法の結果をキャッシュすることをお勧めします。
Method m = Class.getMethod("foo"); // do it once
// now invoke it as many times as you want
m.invoke(obj);
これらの方法がなぜ遅いのかを実証できますか?私の要点は、Class.getField()は、Map.getが階層のトラバーサルに加えて同じことをしていることです。 Class.getDeclaredFieldsはもっと簡単です。私にとってMethod.invokeははるかに複雑に見えます。もちろん、これはただの感覚です。 – maaartinus
お返事ありがとうございます。私はgetDeclaredFields()を使用します。だから多分私はそれらのフィールドをキャッシュします。私がこれまでに得たときに私はそれを噛み合わせます。 – user573215
言い換えれば、最初に行われたことがなかったことを行うためにタイプシステムを回避することです。それで、あなたが何をしても遅くなるでしょう。
Reflectionを使用すると、パフォーマンスをトレードオフして、より簡単に書かれ、より簡単に保守できる簡単なソリューションを得ることができます。あなたが自分のコードをリフレクションで複雑にするとすぐに、あなたは何か間違ったことをしています。
更新
"単純" と、私は、コードの以下の行を意味します。基本的にはより短い解決策。リフレクションでは、型の安全性を放棄して、より短く、より簡潔なプログラムを書くことができます。これは、動的なタイピングの合理的な背後にあります。 Javaジェネリックスはより複雑なプログラムを提供しますが、タイプセーフティがあります。リフレクションを使用すると、静的に型指定された言語で動的な型指定を行うことができます。私の指摘は、プログラムの "リフレクション"バージョンが同等の "非反射"バージョンよりも複雑な場合、非反射バージョンはより速く実行され、複雑さが少ないため、優れています。
反射の他の用途もありますが、メタプログラミングは実際にはそれらの1つではありません。メタプログラミングは、別のプログラムを書き込むプログラムを書く場所です。たとえば、大規模なファイルグループの名前を再フォーマットするとします。多分結婚式の写真のコレクション。
mv "1bill and fred(kfjw0f3).jpg" "1 - bill and fred.jpg"
mv "2sam and kim(g02fsgsg).jpg" "2 - sam and kim.jpg"
.
.
.
このmvコマンドのリストを生成するRubyプログラムはメタプログラムになります。
お返事ありがとうございます。私は最初のパラグラフに行く。私はあなたが「より単純な解決策」を意味するかどうかはわかりません。それは、何を反映しているのかをメタプログラミングしているのではないのですか? – user573215
速度は、主に(総単純化、しかし者が第二のためにそれを実行してみましょう)
プロセッサ上で実行する必要がどのように多くの命令にダウンしています。
メソッドを呼び出すと、コードを最小限のオーバーヘッドでJITコンパイルできます。あなたはすでにどのメソッドが呼び出されるのかを知っているので、それを有効な方法で呼び出すかどうか、返すもの、必要なコードなどを知ることができます。
これをリフレクションで実行すると、窓。メソッドを文字列で見つけようとしたら、それを正しく呼び出すかどうかを確認してから、すべてのコードを取得して実行する必要があります。通常、これは事前に行うことはできません。
これは、バック静的および動的の違いに来る:
静的:早期知ら速く、すべてのものは、実行時に必要な最小限の労力。
ダイナミック:遅く、状況が遅くなるため、実行時に状況を把握する必要があります。
これは反射が「悪い」という意味ではありません!!!!!!!!スピードはすべてではなく、すべての終わり!!!!!
時間を節約して簡単にするなら、それをやりましょう!後であなたがより良いパフォーマンスを必要とし、リフレクションが時間の〜80%で実行される〜20%にあることが分かったら、他の解決策を検討してください。そうであれば、Javaは非常に異なる言語になり、おそらくオブジェクトをほとんど使用しないでしょう。明らかにスピードを念頭に置いて、反射に関する知識を持っている必要があります。これはまさにあなたがこの質問をしている理由です。 :D
心配しないでください。非常に速いです。特にデータベース操作と比較して。
ランタイムバイトコード生成のような永続性フレームワークでの最適化は非常に奇妙です。ここでデータベースについて話しています...反射を使用してください。
PS:非常に良いとrelavantブログ記事、代わりに独自の永続化層を作成する今日
http://buzdin.blogspot.com/2011/01/is-java-reflection-really-slow.html
を公開し、あなたは多くのオープンソースのものの一つに貢献することを検討してください。 –
反射が遅いのは何ですか?クラスとオブジェクトのイントロスペクションと比較する他のメカニズムは何ですか? – Xailor