デリゲートとメソッドの呼び出しのパフォーマンス
質問
この質問に続く C#を使用してパラメータとしてメソッドを渡す という質問と私の個人的な経験に従って、C#でメソッドを呼び出す場合と比較してデリゲートを呼び出す場合のパフォーマンスについてもう少し知りたいと思います。
デリゲートは非常に便利ですが、デリゲートを介して多くのコールバックを行うアプリがあり、これをコールバック インターフェイスを使用するように書き直したところ、1 桁の速度向上が得られました。 これは .NET 2.0 でのことなので、3 と 4 でどのように変わったかはわかりません。
デリゲートへの呼び出しはコンパイラ/CLRで内部的にどのように処理され、これがメソッド呼び出しのパフォーマンスにどのように影響するのでしょうか。
EDIT - デリゲートとコールバックインターフェースの意味を明確にするために。
非同期呼び出しのために、私のクラスはOnCompleteイベントと、呼び出し側がサブスクライブできる関連デリゲートを提供することができます。
代わりに、呼び出し側が実装するOnCompleteメソッドを持つICallbackインターフェースを作成し、完了時にそのメソッドを呼び出すクラスに自分自身を登録することができます(つまり、Javaがこれらのことを処理する方法)。
どのように解決するのですか?
そのような効果は見たことがありません。確かに、それがボトルネックになっていることには遭遇したことがありません。
これは非常に大雑把なベンチマークですが、(私の環境では) デリゲートが実際に より速い です。
using System;
using System.Diagnostics;
interface IFoo
{
int Foo(int x);
}
class Program : IFoo
{
const int Iterations = 1000000000;
public int Foo(int x)
{
return x * 3;
}
static void Main(string[] args)
{
int x = 3;
IFoo ifoo = new Program();
Func<int, int> del = ifoo.Foo;
// Make sure everything's JITted:
ifoo.Foo(3);
del(3);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
x = ifoo.Foo(x);
}
sw.Stop();
Console.WriteLine("Interface: {0}", sw.ElapsedMilliseconds);
x = 3;
sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
x = del(x);
}
sw.Stop();
Console.WriteLine("Delegate: {0}", sw.ElapsedMilliseconds);
}
}
結果(.NET 3.5; .NET 4.0b2もほぼ同じです)。
Interface: 5068
Delegate: 4404
さて、私は特に信じてはいませんが、それはデリゲートが 本当に しかし、それは、デリゲートが桁違いに遅いわけではないと確信させてくれます。さらに、これはデリゲート/インターフェースのメソッドの中ではほとんど何もしていません。呼び出しごとの作業が多くなればなるほど、呼び出しのコストは明らかに少なくなっていきます。
注意すべき点は、単一のインターフェイスインスタンスしか使用しないような場合に、新しいデリゲートを何度も作成していないことです。これは は ガベージコレクションを引き起こすことになり、問題が発生します。ループ内でインスタンスメソッドをデリゲートとして使用する場合、ループ外でデリゲート変数を宣言し、単一のデリゲートインスタンスを作成し、それを再利用することがより効果的であることがわかります。例えば
Func<int, int> del = myInstance.MyMethod;
for (int i = 0; i < 100000; i++)
{
MethodTakingFunc(del);
}
の方が効率的です。
for (int i = 0; i < 100000; i++)
{
MethodTakingFunc(myInstance.MyMethod);
}
これが、あなたが見ていた問題だったのでしょうか?
関連
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み】C# - パスに不正な文字がある場合
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] C#でベースコンストラクタを呼び出す
-
[解決済み] 0.1fを0にすると、なぜ10倍もパフォーマンスが落ちるのですか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] Swift Betaのパフォーマンス:配列のソート
-
[解決済み] Objective-Cでデリゲートを作成するにはどうしたらいいですか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】ここで「要求URIに一致するHTTPリソースが見つかりませんでした」となるのはなぜですか?
-
[解決済み】ASP.NET Core Dependency Injectionのエラーです。アクティブ化しようとしているときに、タイプのサービスを解決できません。
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み】MetadataException: 指定されたメタデータ・リソースをロードできない
-
[解決済み】 C# 条件演算子エラー 代入、call、increment、decrement、await、new object 式のみ文として使用可能です。
-
[解決済み】Unityでゲームオブジェクトのすべての子をループスルーして破壊する方法?
-
[解決済み】画像のペイントにTextureBrushを使用する方法
-
[解決済み】プロセスが実行されているかどうかを知るには?
-
[解決済み] C#でメソッドをパラメータとして渡す