Chu*_*huu 10 .net c# performance delegates
我试图比较三种不同的方式将委托传递给C#中的函数 - 由lambda,委托和直接引用.让我感到惊讶的是直接参考方法(即ComputeStringFunctionViaFunc(object[i].ToString))比其他方法慢六倍.有谁知道为什么会这样?
完整代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
namespace FunctionInvocationTest
{
class Program
{
static void Main(string[] args)
{
object[] objectArray = new object[10000000];
for (int i = 0; i < objectArray.Length; ++i) { objectArray[i] = new object(); }
ComputeStringFunction(objectArray[0]);
ComputeStringFunctionViaFunc(objectArray[0].ToString);
ComputeStringFunctionViaFunc(delegate() { return objectArray[0].ToString(); });
ComputeStringFunctionViaFunc(() => objectArray[0].ToString());
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
s.Start();
for (int i = 0; i < objectArray.Length; ++i)
{
ComputeStringFunction(objectArray[i]);
}
s.Stop();
Console.WriteLine(s.Elapsed.TotalMilliseconds);
s.Reset();
s.Start();
for (int i = 0; i < objectArray.Length; ++i)
{
ComputeStringFunctionViaFunc(delegate() { return objectArray[i].ToString(); });
}
s.Stop();
Console.WriteLine(s.Elapsed.TotalMilliseconds);
s.Reset();
s.Start();
for (int i = 0; i < objectArray.Length; ++i)
{
ComputeStringFunctionViaFunc(objectArray[i].ToString);
}
s.Stop();
Console.WriteLine(s.Elapsed.TotalMilliseconds);
s.Reset();
s.Start();
for (int i = 0; i < objectArray.Length; ++i)
{
ComputeStringFunctionViaFunc(() => objectArray[i].ToString());
}
s.Stop();
Console.WriteLine(s.Elapsed.TotalMilliseconds);
Console.ReadLine();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ComputeStringFunction(object stringFunction)
{
}
public static void ComputeStringFunctionViaFunc(Func<string> stringFunction)
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
修复代码以实际调用ToString()/ stringFunction(),并使用Mono 2.10.9进行测量:
ComputeStringFunctionViaFunc(objectArray[i].ToString);很慢因为object.ToString是虚拟的.检查每个对象以防它覆盖ToString并且ToString应该调用被覆盖的对象.创建其他委托是为了引用非虚函数(快速),它直接调用虚函数(也很快).当修改生成的IL以进行更改时,可以看到这是原因
ldelem.ref
dup
ldvirtftn instance string object::ToString()
Run Code Online (Sandbox Code Playgroud)
至
ldelem.ref
ldftn instance string object::ToString()
Run Code Online (Sandbox Code Playgroud)
总是指object.ToString,从来不是一个压倒一切的功能.这三种方法大约需要同时进行.
更新:一个额外的方法,直接绑定objectArray[i]但仍然ToString虚拟调用:
for (int i = 0; i < objectArray.Length; ++i)
{
ComputeStringFunctionViaFunc(objectArray[i].ToStringHelper);
}
static class Extensions
{
public static string ToStringHelper(this object obj)
{
return obj.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
也提供与其他非虚拟代表大致相同的时间.
| 归档时间: |
|
| 查看次数: |
350 次 |
| 最近记录: |