一尘不染

调用代表与方法的性能

c#

接下来的问题- 使用C#将方法作为参数传递,以及我的一些个人经验,我想了解更多有关调用委托的性能而不是仅使用C#调用方法的性能。

尽管委托非常方便,但我有一个应用程序通过委托进行了许多回调,当我们重写该程序以使用回调接口时,速度得到了改善。这是.NET
2.0的版本,所以我不确定3和4的变化。

如何在编译器/ CLR中内部处理对委托的调用,这如何影响方法调用的性能?


编辑 -为了澄清我的意思是委托与回调接口。

对于异步调用,我的类可以提供OnComplete事件和调用者可以预订的关联委托。

或者,我可以用调用者实现的OnComplete方法创建一个ICallback接口,然后向该类注册自己,该类将在完成时调用该方法(即Java处理这些事情的方式)。


阅读 218

收藏
2020-05-19

共1个答案

一尘不染

我还没有看到这种效果-我当然从来没有遇到过瓶颈。

这是一个非常粗糙的基准,它(无论如何在我的盒子上)显示了委托实际上比接口要

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);
}

难道这就是您所看到的问题?

2020-05-19