私は常に、反射がいかに悪いかを耳にします。私は通常、反射を避け、それなしでは問題を解決できない状況をめったに見つけませんが、私は思っていました...
アプリケーションでリフレクションを使用したことがある人にとって、パフォーマンスヒットを測定しましたか、それは本当にそれほど悪いことですか?
私は常に、反射がいかに悪いかを耳にします。私は通常、反射を避け、それなしでは問題を解決できない状況をめったに見つけませんが、私は思っていました...
アプリケーションでリフレクションを使用したことがある人にとって、パフォーマンスヒットを測定しましたか、それは本当にそれほど悪いことですか?
回答:
そうです。しかし、それはあなたが何をしようとしているのかに依存します。
私はリフレクションを使用してアセンブリ(プラグイン)を動的にロードし、そのパフォーマンスの「ペナルティ」は問題ではありません。これは、アプリケーションの起動中に操作を行うためです。
ただし、それぞれにリフレクション呼び出しを使用して一連のネストされたループの内部をリフレクトしている場合は、コードを再確認する必要があります。
「数回」の操作の場合、リフレクションは完全に許容可能であり、遅延や問題に気付くことはありません。これは非常に強力なメカニズムであり、.NETでも使用されているため、試してはならない理由がわかりません。
ジェフ・リヒターは、講演「日常のパフォーマンス」で、リフレクションによるメソッドの呼び出しは、通常の呼び出しよりも約1000倍遅いことを示しています。
Jeffのヒント:メソッドを複数回呼び出す必要がある場合は、リフレクションを1回使用してそれを見つけ、それをdelegateに割り当ててから、delegateを呼び出します。
リフレクションのパフォーマンスは実装に依存します(繰り返しの呼び出しはキャッシュする必要があります:などentity.GetType().GetProperty("PropName")
)。私が日常的に見ているリフレクションのほとんどは、データリーダーやその他のリポジトリタイプの構造からエンティティにデータを入力するために使用されるため、オブジェクトプロパティを取得または設定するためにリフレクションを使用してパフォーマンスをベンチマークすることにしました。
私は、すべての繰り返し呼び出しをキャッシュし、実際のSetValueまたはGetValue呼び出しの回数のみをキャッシュするため、公平だと思うテストを考案しました。パフォーマンステストのすべてのソースコードは、https://bitbucket.org/grenade/accessortestのbitbucketにあります。精査は歓迎され、奨励されています。
私が得た結論は、リフレクションの実装が適切に行われているときに一度に100,000行未満しか返さないデータアクセスレイヤーでリフレクションを削除することは実用的ではなく、顕著なパフォーマンスの改善を提供しないということです。
上のグラフは、私の小さなベンチマークの出力を示しており、反射を上回るメカニズムは、100,000サイクルのマークを付けた後にのみ顕著に機能することを示しています。ほとんどのDALは一度に数百またはおそらく数千の行しか返さず、これらのレベルではリフレクションは問題なく実行されます。
ループしていない場合でも、心配する必要はありません。
私の最も適切な経験は、大きなオブジェクトモデル内の同じ型の2つのデータエンティティをプロパティごとに比較するコードを記述したことです。うまくいった、試してみた、明らかに犬のように走った。
私は落胆していましたが、ロジックを変更することなく、同じアルゴリズムを使用して比較を行うためのメソッドを自動生成し、プロパティに静的にアクセスできることが一夜でわかりました。この目的のためにコードを適応させるのにまったく時間はかかりませんでした。オブジェクトモデルが変更されるたびにボタンをクリックするだけで更新できる静的コードを使用して、エンティティごとにプロパティごとの詳細な比較を行うことができました。
私のポイント:同僚との会話で、リフレクションの使用はランタイム操作を実行するのではなく、コードを自動生成してコンパイルすることである可能性があることを何度か指摘したため、これはよく検討する価値があります。
大規模ではありません。マーティンが言っているように、あなたが愚かな場所でそれを使用しているのでない限り、私はデスクトップ開発でそれを問題にしたことがありません。多くの人々がデスクトップ開発におけるそのパフォーマンスについて全く不合理な恐れを持っていると聞いています。
ただし、コンパクトフレームワーク(通常はここにあります)では、これはほとんどの嫌悪感であり、ほとんどの場合、ペストのように回避する必要があります。私はまだそれを頻繁に使用することでうまくいくことができますが、あまり面白くないそのアプリケーションには本当に注意しなければなりません。:(
パフォーマンスが重要なコードのために.NETライブラリによって内部的に行われるリフレクションについてさえ心配する必要があるのは十分に悪いことです。
次の例は廃止されました。当時(2008年)はtrueですが、最近のCLRバージョンで修正されています。ただし、一般的にリフレクションはまだいくらかコストがかかります。
適例:高性能コードのロック(C#)/ SyncLock(VB.NET)ステートメントで「オブジェクト」として宣言されたメンバーを使用しないでください。どうして?CLRは値型をロックできないため、オブジェクトが実際に参照型ではなく値型であるかどうかを確認するために、実行時リフレクション型チェックを実行する必要があります。
プログラミングのすべてのものと同様に、パフォーマンスコストと得られるあらゆる利益とのバランスをとる必要があります。リフレクションは、注意して使用すると非常に貴重なツールです。リフレクションを使用してバインディングを行うO / RマッピングライブラリをC#で作成しました。これは素晴らしくうまくいきました。ほとんどのリフレクションコードは1回しか実行されなかったため、パフォーマンスへの影響はほとんどありませんでしたが、メリットは大きかったです。新しいファンダングルソートアルゴリズムを作成している場合、おそらくリフレクションが不十分であるため、リフレクションはおそらく使用しません。
ここであなたの質問に正確に回答できなかったことに感謝します。私のポイントは、それは本当に重要ではないということです。必要に応じて反射を使用します。これは、いつどのように使用するかを学ぶために必要なもう1つの言語機能です。
リフレクションは、頻繁にオブジェクトを作成するために使用すると、パフォーマンスに顕著な影響を与える可能性があります。リフレクションに大きく依存しているコンポジットUIアプリケーションブロックに基づくアプリケーションを開発しました。リフレクションによるオブジェクトの作成に関連する顕著なパフォーマンスの低下がありました。
ただし、ほとんどの場合、リフレクションの使用に問題はありません。アセンブリを検査する必要があるだけの場合は、非常に軽量で高速なMono.Cecilをお勧めします
パラメータのリストと一致するメソッドをリクエストするたびにランタイムが行う必要がある多くのチェックのため、リフレクションはコストがかかります。どこか深いところに、コードが存在し、型のすべてのメソッドをループし、その可視性を検証し、戻り値の型をチェックし、すべてのパラメーターの型もチェックします。これらはすべて時間がかかります。
そのメソッドを内部で実行すると、実際のターゲットメソッドを実行する前に、互換性のあるパラメーターのリストを渡したかどうかをチェックするようなコードがいくつかあります。
将来的に継続的に再利用する場合は、可能であれば常にメソッドハンドルをキャッシュすることをお勧めします。すべての優れたプログラミングのヒントと同様に、自分自身を繰り返すことを避けることはしばしば意味があります。この場合、特定のパラメータを使用してメソッドを継続的に検索し、それを毎回実行するのは無駄です。
ソースをつついて、何が行われているかを確認してください。
すべての場合と同様に、すべては状況を評価することです。でDotNetNukeのと呼ばれる、かなりコアコンポーネントがありますFillObject
使用の反射がデータローからオブジェクトを移入することが。
これはかなり一般的なシナリオであり、MSDNに、Reflectionを使用してビジネスオブジェクトをASP.NETフォームコントロールにバインドするパフォーマンスの問題に関する記事があります。
パフォーマンスはさておき、その特定のシナリオでリフレクションを使用することについて私が気に入らない点の1つは、コードを一目で理解する能力が低下する傾向があることです。厳密に型指定されたデータセットやLINQ to SQLのようなものとは対照的に、時間の安全性。