【发布时间】:2020-04-02 17:09:11
【问题描述】:
我听说过很多关于 Linq Expression 性能的信息。但自己无法检查。 请查看下一个 .NET Core 应用示例:
class Program
{
static void Main(string[] args)
{
var classType = Type.GetType("ConsoleApp1.TestClass");
var classConstructor = classType.GetConstructor(new[] { typeof(string) });
//var param = Expression.Parameter(typeof(string));
//var newExpression = Expression.New(classConstructor, param);
//LambdaExpression lambda = Expression.Lambda(newExpression, param);
//var compiled = lambda.Compile();
//var instance = compiled.DynamicInvoke("test");
//var instance = Activator.CreateInstance(classType, "test");
//var instance = classConstructor.Invoke(new object[] { "test" });
Console.ReadLine();
}
}
class TestClass
{
public TestClass(string param)
{
}
}
当我在未注释 Expression 版本的情况下运行此代码时,代码的运行速度会慢 10 倍。 请告知可能出现的问题或符合预期。
【问题讨论】:
-
你执行了多少次实例化?您应该同时保留
classConstructor和compiled变量,然后进行热身(调用这三个变量几次),然后开始您的基准测试 -
这完全取决于你“听说过很多关于Linq Expression 性能”...通常是“不要使用反射调用某物百万次,编译一次表达式并使用它百万次,或使用
dynamic为您缓存反射,或至少缓存大部分反射调用“...将单个反射调用与创建表达式进行比较绝对不会显示出好处... -
我的意思是,lambda表达式编译一次,编译后的表达式应该保存。反射构造函数检索也必须发生一次并且应该被存储。然后,只有这样,您才能运行已编译的 lambda / ConstructorInfo 实例化比较基准。
-
DynamicInvoke比反射还要糟糕。编译表达式在编译为强类型委托并使用Invoke调用时才有意义。 -
如果我们要编译一次并运行它数百万次,那么使用 Roslyn(或 CodeDom)编译一个实现接口以创建实例的具体类怎么样? (也有强类型)。我猜没有什么能比得上:)
标签: c# performance reflection linq-expressions