调用委托与方法的性能 [英] Performance of calling delegates vs methods

查看:32
本文介绍了调用委托与方法的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照这个问题 - 使用 C# 将方法作为参数传递 和一些我的个人经验我想更多地了解在 C# 中调用委托与仅调用方法的性能.

Following this question - Pass Method as Parameter using C# and some of my personal experience I'd like to know a little more about the performance of calling a delegate vs just calling a method in C#.

尽管委托非常方便,但我有一个应用程序可以通过委托进行大量回调,当我们重写它以使用回调接口时,我们获得了一个数量级的速度提升.这是 .NET 2.0,所以我不确定 3 和 4 有什么变化.

Although delegates are extremely convenient, I had an app that did lots of callbacks via delegates and when we rewrote this to use callback interfaces we got an order of magnitude speed improvement. This was with .NET 2.0 so I'm not sure how things have changed with 3 and 4.

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

How are calls to delegates handled internally in the compiler/CLR and how does this affect performance of method calls?

编辑 - 阐明我所说的委托与回调接口的含义.

EDIT - To clarify what I mean by delegates vs callback interfaces.

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

For asynchronous calls my class could provide an OnComplete event and associated delegate which the caller could subscribe to.

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

Alternatively I could create an ICallback interface with an OnComplete method that the caller implements and then registers itself with the class that will then call that method on completion (i.e. the way Java handles these things).

推荐答案

我还没有看到这种效果 - 我当然从未遇到过它成为瓶颈.

I haven't seen that effect - I've certainly never encountered it being a bottleneck.

这是一个非常粗略的基准测试,它显示(无论如何在我的盒子上)委托实际上比接口更快:

Here's a very rough-and-ready benchmark which shows (on my box anyway) delegates actually being faster than interfaces:

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 大致相同):

Results (.NET 3.5; .NET 4.0b2 is about the same):

Interface: 5068
Delegate: 4404

现在我并不特别相信这意味着委托真的比接口快……但这让我相当确信它们并没有慢一个数量级.此外,这在委托/接口方法中几乎没有任何作用.显然,随着每次调用的工作量越来越大,调用成本的差异会越来越小.

Now I don't have particular faith that that means delegates are really faster than interfaces... but it makes me fairly convinced that they're not an order of magnitude slower. Additionally, this is doing almost nothing within the delegate/interface method. Obviously the invocation cost is going to make less and less difference as you do more and more work per call.

需要注意的一件事是,您不会在只使用单个接口实例的情况下多次创建新委托.这可能导致问题,因为它会引发垃圾收集等.如果您在循环内使用实例方法作为委托,您会发现在循环外声明委托变量更有效,创建单个委托实例并重用它.例如:

One thing to be careful of is that you're not creating a new delegate several times where you'd only use a single interface instance. This could cause an issue as it would provoke garbage collection etc. If you're using an instance method as a delegate within a loop, you will find it more efficient to declare the delegate variable outside the loop, create a single delegate instance and reuse it. For example:

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

这可能是您看到的问题吗?

Could this have been the problem you were seeing?

这篇关于调用委托与方法的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆