.NETリフレクションのコストはどれくらいですか?


210

私は常に、反射がいかに悪いかを耳にします。私は通常、反射を避け、それなしでは問題を解決できない状況をめったに見つけませんが、私は思っていました...

アプリケーションでリフレクションを使用したことがある人にとって、パフォーマンスヒットを測定しましたか、それは本当にそれほど悪いことですか?


この質問を確認することもできます。stackoverflow.com/questions/224232/...
smaclell

1
fastflect.codeplex.comでAPIを使用します。ゲッター/セッター/インボーカーや他のいくつかのものについては、反射を500xほど高速化します。それを拡張する必要がある場合は、ソースとそれがどのように機能するかの情報もそこにあります。
Brandon Moore、

3
この情報は2014年にどのようにチェックアウトされますか?この4年間で何か変化はありましたか?
Arnthor 2014年

1
インスタンスプロパティに値を割り当てるという単純なタスクは、単純なコーディング(instance.property = value)を使用した場合よりも、リフレクション(PropertyInfo.SetValue(instance、value))を使用した場合の方が約150倍遅くなります。これは.NET 4.0にあります
Thanasis Ioannidis

回答:


130

そうです。しかし、それはあなたが何をしようとしているのかに依存します。

私はリフレクションを使用してアセンブリ(プラグイン)を動的にロードし、そのパフォーマンスの「ペナルティ」は問題ではありません。これは、アプリケーションの起動中に操作を行うためです。

ただし、それぞれにリフレクション呼び出しを使用して一連のネストされたループの内部をリフレクトしている場合は、コードを再確認する必要があります。

「数回」の操作の場合、リフレクションは完全に許容可能であり、遅延や問題に気付くことはありません。これは非常に強力なメカニズムであり、.NETでも使用されているため、試してはならない理由がわかりません。


リフレクションを使用してメソッド、現在のメソッドのクラス名を取得し、try-catchでエラーをログに記録しています。基本的には、エラーのロギング中に関数名をハードコーディングすることを避けます。心配する必要はありますか?
Sangram Nandkhile、2015

@Sangramいいえ、それで結構です
Karthik AMR

@Sangramいいえ、常にキャッチする必要のある多くのエラーがない限り、それは別の問題になるはずです:)
Martin Marconcini

5
@Sangramリフレクションのパフォーマンスが問題になることはないはずですが、標準の古い例外が提供するものをそのままよりエレガントな方法で再実装しようとしているようです...
JacekGorgońDec

152

ジェフ・リヒターは、講演「日常のパフォーマンス」で、リフレクションによるメソッドの呼び出しは、通常の呼び出しよりも約1000倍遅いことを示しています。

Jeffのヒント:メソッドを複数回呼び出す必要がある場合は、リフレクションを1回使用してそれを見つけ、それをdelegateに割り当ててから、delegateを呼び出します。


18
私もDevscoveryに参加し、.NET 3.5のこれらの結果に同意しています。.NET 4用のDevscoveryパフォーマンスベンチマークプログラムを再コンパイルすると、大幅な改善が見られます。コストは100倍遅くなります。typeof演算用反射()ルックアップは、.NET 3.5と.NET 4との間に変化しない使用
ジョンWigger

61

リフレクションのパフォーマンスは実装に依存します(繰り返しの呼び出しはキャッシュする必要があります:などentity.GetType().GetProperty("PropName"))。私が日常的に見ているリフレクションのほとんどは、データリーダーやその他のリポジトリタイプの構造からエンティティにデータを入力するために使用されるため、オブジェクトプロパティを取得または設定するためにリフレクションを使用してパフォーマンスをベンチマークすることにしました。

私は、すべての繰り返し呼び出しをキャッシュし、実際のSetValueまたはGetValue呼び出しの回数のみをキャッシュするため、公平だと思うテストを考案しました。パフォーマンステストのすべてのソースコードは、https://bitbucket.org/grenade/accessortestのbitbucketにあります。精査は歓迎され、奨励されています。

私が得た結論は、リフレクションの実装が適切に行われているときに一度に100,000行未満しか返さないデータアクセスレイヤーでリフレクションを削除することは実用的ではなく、顕著なパフォーマンスの改善を提供しないということです。

存在するエンティティの数(x)に対する時間(y)のグラフ

上のグラフは、私の小さなベンチマークの出力を示しており、反射を上回るメカニズムは、100,000サイクルのマークを付けた後にのみ顕著に機能することを示しています。ほとんどのDALは一度に数百またはおそらく数千の行しか返さず、これらのレベルではリフレクションは問題なく実行されます。


9
必ずしも。DAL変換は数千のアイテムでのみ可能ですが、アプリケーションを使用する同時ユーザー(Webの場合)を掛けると、まるで100万のアイテムを変換するかのように合計されます。特定の方法が100倍遅い場合、大小のセットではそれだけ遅くなります。遅いほど遅い。
Robert Koritnik 2012

@RobertKoritnikこれは、サーバー上のWebメソッドが非同期でないことを前提としています
Kurren

@kurrenの非同期性はリフレクションに影響を与えず、サーバーリソースに影響を与えます。もちろん、非同期Webメソッドはより多くのユーザーにサービスを提供できますが、リフレクションは依然として遅くなります。そして、それ自体の反省は、とにかく同期プロセスです。一方、データのフェッチは、非同期設計でうまく機能する唯一の部分になります。
Robert Koritnik 2014年

3
グラフのハイパーメソッドとは何ですか?リフレクターとどう違うの?
ブライアンレジェンド

:私はこの@LoneCoder参照している必要がありますcodeproject.com/Articles/18450/...によってstackoverflow.com/users/23354/marc-gravell
手榴弾


12

私の最も適切な経験は、大きなオブジェクトモデル内の同じ型の2つのデータエンティティをプロパティごとに比較するコードを記述したことです。うまくいった、試してみた、明らかに犬のように走った。

私は落胆していましたが、ロジックを変更することなく、同じアルゴリズムを使用して比較を行うためのメソッドを自動生成し、プロパティに静的にアクセスできることが一夜でわかりました。この目的のためにコードを適応させるのにまったく時間はかかりませんでした。オブジェクトモデルが変更されるたびにボタンをクリックするだけで更新できる静的コードを使用して、エンティティごとにプロパティごとの詳細な比較を行うことができました。

私のポイント:同僚との会話で、リフレクションの使用はランタイム操作を実行するのではなく、コードを自動生成してコンパイルすることである可能性があることを何度か指摘したため、これはよく検討する価値があります。


Visual Studioがこのように優れたテンプレートをサポートしていることを考えると、コード生成を使用する実用的な方法です
Sebastian

12

大規模ではありません。マーティンが言っているように、あなたが愚かな場所でそれを使用しているのでない限り、私はデスクトップ開発でそれを問題にしたことがありません。多くの人々がデスクトップ開発におけるそのパフォーマンスについて全く不合理な恐れを持っていると聞いています。

ただし、コンパクトフレームワーク(通常はここにあります)では、これはほとんどの嫌悪感であり、ほとんどの場合、ペストのように回避する必要があります。私はまだそれを頻繁に使用することでうまくいくことができますが、あまり面白くないそのアプリケーションには本当に注意しなければなりません。:(


5
新しい言葉を教えてくれた+1:アナセマ。また、不合理な恐れについて言及した。不合理に恐れるプログラマーを恐れます。彼らは自分が何をしているかを本当に知らず、他の人々が彼らに伝えたことに基づいているだけなのです。咳貨物カルト咳
bsneeze 2009年

1
ああカーゴカルト。今、好奇心の強い人間の行動の良い例があります。
平凡な2009年

10

パフォーマンスが重要なコードのために.NETライブラリによって内部的に行われるリフレクションについてさえ心配する必要があるのは十分に悪いことです。

次の例は廃止されました。当時(2008年)はtrueですが、最近のCLRバージョンで修正されています。ただし、一般的にリフレクションはまだいくらかコストがかかります。

適例:高性能コードのロック(C#)/ SyncLock(VB.NET)ステートメントで「オブジェクト」として宣言されたメンバーを使用しないでください。どうして?CLRは値型をロックできないため、オブジェクトが実際に参照型ではなく値型であるかどうかを確認するために、実行時リフレクション型チェックを実行する必要があります。


13
公平を期すために、反射型チェックは高速です。
ジミー、

1
このような「パフォーマンスクリティカルなコード」について、最初から.NETを実際に使用する必要がありますか?
Sep

1
@Seph:.NETの動的/反射部分、いいえ。しかし、通常のC#/。NETはなぜですか?C ++とC#の高速化は、アプリケーションレイヤーではわずかです(C ++は、集中的な数学ルーチンで数パーセント高速です)。そして、私はあなたがアセンブリを提案していないと思います...
DeepSpace101 2013年

ボックス化された値タイプ(つまり、オブジェクト)はロックオンできます。@BryceWagnerは正しいです。

1
(私にとって)公平に言えば、答えは「単純なナンセンス」ではなく「時代遅れ」であると言う方が正確です。lock(obj)の動作についての私の発言は、それらが書かれた時点では正確でしたが、CLRの実装固有の動作はもうなくなっています。
McKenzieG1 2014

5

プログラミングのすべてのものと同様に、パフォーマンスコストと得られるあらゆる利益とのバランスをとる必要があります。リフレクションは、注意して使用すると非常に貴重なツールです。リフレクションを使用してバインディングを行うO / RマッピングライブラリをC#で作成しました。これは素晴らしくうまくいきました。ほとんどのリフレクションコードは1回しか実行されなかったため、パフォーマンスへの影響はほとんどありませんでしたが、メリットは大きかったです。新しいファンダングルソートアルゴリズムを作成している場合、おそらくリフレクションが不十分であるため、リフレクションはおそらく使用しません。

ここであなたの質問に正確に回答できなかったことに感謝します。私のポイントは、それは本当に重要ではないということです。必要に応じて反射を使用します。これは、いつどのように使用するかを学ぶために必要なもう1つの言語機能です。


3

リフレクションは、頻繁にオブジェクトを作成するために使用すると、パフォーマンスに顕著な影響を与える可能性があります。リフレクションに大きく依存しているコンポジットUIアプリケーションブロックに基づくアプリケーションを開発しました。リフレクションによるオブジェクトの作成に関連する顕著なパフォーマンスの低下がありました。

ただし、ほとんどの場合、リフレクションの使用に問題はありません。アセンブリを検査する必要があるだけの場合は、非常に軽量で高速なMono.Cecilをお勧めします


3

パラメータのリストと一致するメソッドをリクエストするたびにランタイムが行う必要がある多くのチェックのため、リフレクションはコストがかかります。どこか深いところに、コードが存在し、型のすべてのメソッドをループし、その可視性を検証し、戻り値の型をチェックし、すべてのパラメーターの型もチェックします。これらはすべて時間がかかります。

そのメソッドを内部で実行すると、実際のターゲットメソッドを実行する前に、互換性のあるパラメーターのリストを渡したかどうかをチェックするようなコードがいくつかあります。

将来的に継続的に再利用する場合は、可能であれば常にメソッドハンドルをキャッシュすることをお勧めします。すべての優れたプログラミングのヒントと同様に、自分自身を繰り返すことを避けることはしばしば意味があります。この場合、特定のパラメータを使用してメソッドを継続的に検索し、それを毎回実行するのは無駄です。

ソースをつついて、何が行われているかを確認してください。


3

すべての場合と同様に、すべては状況を評価することです。でDotNetNukeのと呼ばれる、かなりコアコンポーネントがありますFillObject使用の反射がデータローからオブジェクトを移入することが。

これはかなり一般的なシナリオであり、MSDNに、Reflectionを使用してビジネスオブジェクトをASP.NETフォームコントロールにバインドするパフォーマンスの問題に関する記事があります。

パフォーマンスはさておき、その特定のシナリオでリフレクションを使用することについて私が気に入らない点の1つは、コードを一目で理解する能力が低下する傾向があることです。厳密に型指定されたデータセットやLINQ to SQLのようなものとは対照的に、時間の安全性。


2

リフレクションによってアプリのパフォーマンスが大幅に低下することはありません。リフレクションを使用しないことで特定のことをより迅速に実行できる場合がありますが、リフレクションが一部の機能を実現する最も簡単な方法である場合は、それを使用します。パフォーマンスの問題が発生した場合は、リフレクションからコードをリファクタリングできます。


1

答えは、場合によって異なります。タスクリストアプリケーションに配置する場合は、それほど大きな問題ではありません。Facebookの永続化ライブラリに入れたい場合は、大変なことです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.