更改为通用接口的性能影响

Pie*_*rOz 6 .net c# clr performance interface

我研究使用Visual Studio在C#/ .NET中开发的应用程序.在我的方法的原型中,ReSharper经常建议我用更通用的输入参数替换输入参数的类型.例如,List <> with IEnumerable <>如果我只在我的方法体中使用带有foreach的列表.我可以理解为什么写这个看起来更聪明,但我非常关心性能.我担心如果我听ReSharper我的应用程序的性能会降低...

当我写作时,有人能够(或多或少)向我解释幕后发生的事情(即在CLR中):

public void myMethod(IEnumerable<string> list)
{
  foreach (string s in list)
  {
    Console.WriteLine(s);
  }
}

static void Main()
{
  List<string> list = new List<string>(new string[] {"a", "b", "c"});
  myMethod(list);
}
Run Code Online (Sandbox Code Playgroud)

和有什么区别:

public void myMethod(List<string> list)
{
  foreach (string s in list)
  {
    Console.WriteLine(s);
  }
}

static void Main()
{
  List<string> list = new List<string>(new string[] {"a", "b", "c"});
  myMethod(list);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 11

你担心表现 - 但你有任何理由担心这个问题吗?我的猜测是你根本没有对代码进行基准测试.使用性能更高的代码替换可读,干净的代码之前始终进行基准测试

在这种情况下,无论如何,呼叫Console.WriteLine将完全支配性能.

虽然我怀疑在使用和这里之间可能存在理论上的性能差异,但我怀疑它在现实世界的应用程序中的重要性的案例数量正在消失.List<T>IEnumerable<T>

它甚至不像序列类型被用于许多操作 - 只有一个调用GetEnumerator()被声明为返回IEnumerator<T>.随着列表变大,两者之间的性能差异将变得更,因为它只会在循环开始时产生任何影响.

但是,忽略分析,要做的就是在对其进行编码决策之前测量性能.

至于幕后发生的事情 - 你必须深入研究每种情况下元数据中究竟是什么的深层细节.我怀疑在接口的情况下,有一个额外的重定向级别,至少在理论上 - CLR必须解决目标对象的类型vtable for的IEnumerable<T>位置,然后调用适当的方法的代码.在这种情况下List<T>,JIT会知道正确的偏移到vtable中,而没有额外的查找.这只是基于我对JITting,thunking,vtables以及它们如何应用于接口的朦胧理解.它可能略有错误,但更重要的是它是一个实现细节.

  • 未记录的JIT优化.接口方法调度程序试图发挥智能.从这里[link](http://blogs.microsoft.co.il/blogs/sasha/archive/2007/02/27/JIT-Optimizations_2C00_-Inlining_2C00_-and-Interface-Method-Dispatching-_2800_Part-1-of- N_2900_.aspx) (2认同)