1

我读了这篇文章并尝试做同样的事情,但是在比较 del.DynamicINvoke(args) 与时遇到了一个非常奇怪的行为。德尔(参数)

更新

因此,在 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 毫秒,直接调用需要 20 毫秒

当我放入 Thread.Sleep(20) 并且循环运行 1000 次时,DynamicInvoke 和直接 Invoke 大约需要 20 秒

ps 由于某种原因,我无法从 vs 复制/粘贴,所以如果您看到语法错误,我会手动编写代码,请告诉我

4

2 回答 2

1

首先要注意:在查看性能时,请始终确保您正在运行发布/优化的构建,并且在没有附加 IDE 的情况下运行它。您通常可以在 Visual Studio 中使用ctrl+ f5,但如果有疑问:从命令行运行它。

当“a”为空方法并且循环运行 1000000 次时,DynamicInvoke 大约需要 4000 毫秒,直接调用需要 20 毫秒

很公平; 我得到 2729msDynamicInvoke和 8ms 的直接调用;但这正是我们所期望的;我们知道DynamicInvoke比较慢。但这里的一切都如我们所料。事实上,如果我们纠正Invoke不公平地运行额外级别的委托调用的事实(我们应该期望这大约使所花费的时间加倍),我们得到:

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 秒

是的,20ms x 1000 绝对是 20 秒。20ms 的睡眠时间并不准确;我们预计这个数字会有一些差异,当乘以 1000 时会加起来。特别是,睡眠中断不会在每个 CPU 周期触发,所以我们应该预期稍微不规则的睡眠周期会吃掉两者之间的差异aInvokeDynamicInvoke(每次调用大约 2.75 微秒)。

更改loop为 1000 并添加一个Thread.Sleep(20)我得到:

Dynamic: 20395
Invoke: 20370

同样,这里没有什么令人惊讶的。事实上,由于 a 引入的轻微随机性Thread.Sleep(),乘以 1000,我会发现如果Invoke偶尔花费比Dynamic.

我认为这些数字丝毫没有令人惊讶的地方。

于 2012-07-17T07:10:54.730 回答
0

您的测量设置中有一些东西会产生系统误差。您肯定不会认为使用 DynamicInvoke 可以更快地调用委托的主体。它对身体没有影响。

于 2012-07-15T14:07:38.950 回答