1

この投稿を読んで、同じことをしようとしましたが、del.DynamicINvoke(args) と比較すると、非常に奇妙な動作に遭遇しました。del(引数)

アップデート

したがって、Jon と usr のコメントの後、新しい作業コードを投稿します。

どんな助けにも本当に感謝します!

コード:

using System;
using System.Diagnostic;
using System.Threading;

namespace DynamicInvokeVsInvoke {
  public class Program {
    static void Main(string[] args) {
      var objArgs = new object[] {100, 1.2345678 };
      Action<int, double> a = (i, d) => {};
      Action<object[]> action = o => a((int)o[0], (double)o[1]);
      var sw = new Stopwatch();
      sw.Start();
      for (int i = 0; i < 1000; i++)
         a.DynamicInvoke(objArgs);
      Console.WriteLine("Dynamic: " + sw.ElapsedMilliseconds);
      sw.Stop();
      sw = new Stopwatch();
      sw.Start();
      for (int i = 0; i < 1000; i++)
         action(objArgs);
      Console.WriteLine("Invoke: " + sw.ElapsedMilliseconds);
      sw.Stop();
    }
  }
}

結果:

「a」が空のメソッドで、ループが 1000000 回実行される場合、DynamicInvoke は約 4000 ミリ秒かかり、直接 Invoke は 20 ミリ秒かかりました。

Thread.Sleep(20) に入れてループを 1000 回実行すると、DynamicInvoke と直接 Invoke に約 20 秒かかりました

ps 何らかの理由で vs からコピー/貼り付けできないので、構文エラーが表示された場合は手動でコードを記述します。お知らせください

4

2 に答える 2

1

最初に注意すること:パフォーマンスを確認するときは、常にリリース/最適化されたビルドを実行していることを確認し、IDEを接続せずに実行してください。通常、Visual Studioではctrl+を使用することができますが、疑わしい場合は、コマンドラインから実行してください。f5

'a'が空のメソッドであり、ループが1000000回実行される場合、DynamicInvokeには約4000ミリ秒かかり、直接Invokeには20ミリ秒かかりました。

けっこうだ; 直接呼び出しの場合は2729ミリ秒、DynamicInvoke直接呼び出しの場合は8ミリ秒です。しかし、それは私たちが期待することです。私たちはそれが遅いことを知っています。DynamicInvokeしかし、ここのすべては私たちが期待する通りです。実際、余分なレベルInvokeのデリゲート呼び出しを不当に実行しているという事実を修正すると(これは、所要時間の約2倍になると予想されます)、次のようになります。

static void Main()
{
    int x = 100;
    double y = 1.2345678;
    var objArgs = new object[] { x, y };
    Action<int, double> a = (i, d) => { };
    var sw = new Stopwatch();
    sw.Start();
    const int loop = 1000000;
    for (int i = 0; i < loop; i++)
        a.DynamicInvoke(objArgs);
    Console.WriteLine("Dynamic: " + sw.ElapsedMilliseconds);
    sw.Stop();
    sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < loop; i++)
        a(x,y);
    Console.WriteLine("Invoke: " + sw.ElapsedMilliseconds);
    sw.Stop();
}

結果:

Dynamic: 2785
Invoke: 3

これまでのところ、予想外のことは何もありません。

Thread.Sleep(20)を挿入し、ループが1000回実行されると、DynamicInvokeと直接Invokeに約20秒かかりました。

はい、20msx1000は間違いなく20秒です。20msのスリープ時間は正確ではありません。その数の周りにいくらかの変動が予想され、1000を掛けると加算されます。特に、スリープ割り込みはCPUサイクルごとに発生するわけではないため、わずかに不規則なスリープサイクルが両者の差を食いつぶすと予想されます。 aInvokeおよびDynamicInvoke(呼び出しごとに約2.75マイクロ秒)。

loop1000に変更して追加すると、次のThread.Sleep(20)ようになります。

Dynamic: 20395
Invoke: 20370

ここでも、驚くべきことは何もありません。実際、aによって導入されたわずかなランダム性に1000を掛けると、たまに。より長くかかるThread.Sleep()場合でも完全に許容できることがわかります。InvokeDynamic

数字には少しも驚くべきことは何も見当たりません。

于 2012-07-17T07:10:54.730 に答える
0

系統誤差を生成している測定セットアップに何かがあります。確かに、DynamicInvoke を使用すると、呼び出されるデリゲートの本体が高速になるとは思わないでしょう。体への影響はありません。

于 2012-07-15T14:07:38.950 に答える