为什么调用抽象方法比在.NET中使用接口方法更快?

时间:2017-02-26 16:30:32

标签: c# .net performance clr benchmarking

我有一个接口I,一个抽象类A,这两个具体的类,以及一个用作基线的具体类C

interface I
{
    void Do();
}
abstract class A
{
    public abstract void Do();
}
class C
{
    public void Do() {}
}
class IImpl : I
{
    public void Do() {}
}
class AImpl : A
{
    public override void Do() {}
}

我使用C.Do()I.Do()A.Do()BenchmarkDotNet的来电进行了基准测试。

public class Bench
{
    private C _c;
    private I _i;
    private A _a;

    [Setup]
    public void Setup()
    {
        _c = new C();
        _i = new IImpl();
        _a = new AImpl();
    }

    [Benchmark(Baseline = true)]
    public void ConcreteCall()
    {
        _c.Do();
    }
    [Benchmark]
    public void InterfaceCall()
    {
        _i.Do();
    }
    [Benchmark]
    public void AbstractCall()
    {
        _a.Do();
    }
}

基准测试结果始终显示调用A.Do()的速度超过I.Do()

        Method |      Mean |    StdErr |    StdDev | Scaled | Scaled-StdDev |
-------------- |---------- |---------- |---------- |------- |-------------- |
  ConcreteCall | 0.0673 ns | 0.0114 ns | 0.0440 ns |   1.00 |          0.00 |
 InterfaceCall | 1.4944 ns | 0.0084 ns | 0.0325 ns |  62.92 |         74.68 |
  AbstractCall | 0.8178 ns | 0.0139 ns | 0.0539 ns |  34.43 |         40.99 |

我在此结构上尝试了一些变体,例如从ImplA派生了一个I类,或者通过A实现线性化层次结构I,每次都重现同样的效果。

当然,差异并不大 - 朋友之间的距离是700皮秒? - 但我想了解.NET运行时中发生了什么。我理解为什么C.Do()是迄今为止最快的 - 在查找方法实现方面没有间接性 - 但为什么通过抽象类的调用通过接口击败了调用?我在OSX上使用.NET Core 1.1和x64 RyuJit。

0 个答案:

没有答案