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