【发布时间】:2019-04-23 19:54:46
【问题描述】:
我一直在对一些创建类型实例的代码进行基准测试,这个结果对我来说似乎很奇怪:
Delegate deleg = Expression.Lambda(Expression.New(_type)).Compile();
// deleg.DynamicInvoke();
对
Func<object> func = Expression.Lambda<Func<object>>(Expression.New(_type)).Compile();
// func();
使用 BenchmarDotNet 给出(平均,核心):
- 委托:501.790 ns
- 函数:4.710 ns
谁知道为什么差别这么大?
完整的基准测试:
[ClrJob(baseline: true), CoreJob, CoreRtJob]
[RPlotExporter, RankColumn]
public class Benchmarks
{
private Type _type;
private ConstructorInfo _constructor;
private Delegate _delegate;
private Func<object> _func;
[GlobalSetup]
public void GlobalSetup()
{
_type = typeof(TestClass);
_constructor = _type.GetConstructor(Type.EmptyTypes);
_delegate = Expression.Lambda(Expression.New(_type)).Compile();
_func = Expression.Lambda<Func<object>>(Expression.New(_type)).Compile();
}
[Benchmark(Baseline = true)]
public object Instanciate_Using_New()
{
return new TestClass();
}
[Benchmark]
public object Instanciate_Using_Activator()
{
return Activator.CreateInstance(_type);
}
[Benchmark]
public object Instanciate_Using_Constructor()
{
return _constructor.Invoke(null);
}
[Benchmark]
public object Instanciate_Using_Expression_Delegate()
{
return _delegate.DynamicInvoke();
}
[Benchmark]
public object Instanciate_Using_Expression_Func()
{
return _func();
}
}
【问题讨论】:
-
如果将调用与编译一起测量会怎样?
-
不,编译是在 GlobalSetup 中完成的;
-
你应该确保你的问题在他们的目标中是明确的。只有通过阅读代码,您才会发现您的问题不是关于编译性能差异,而是关于调用代码。
-
@LasseVågsætherKarlsen 什么?这个问题怎么不是关于性能的?
-
这与性能有关,但您正在分析调用已编译的代码,而不是分析编译代码。我正是这个意思。您说您正在对“一些创建类型实例的代码”进行基准测试,然后发布一段代码与另一段代码,但您不是在对这些代码段进行基准测试,而是在使用结果进行基准测试。跨度>
标签: c# benchmarking expression-trees