C# 4.0 运行时代码专用化的表达式树与IL.Emit

C# 4.0 运行时代码专用化的表达式树与IL.Emit,c#-4.0,code-generation,metaprogramming,specialization,partial-specialization,C# 4.0,Code Generation,Metaprogramming,Specialization,Partial Specialization,我最近了解到,可以在运行时生成C#代码,我想使用这个特性。我有一些代码可以进行一些非常基本的几何计算,比如计算线-平面交点,我认为我可以通过为一些方法生成专门的代码来获得一些性能优势,因为许多计算都是针对同一平面或同一直线反复执行的。通过专门化计算交点的代码,我认为我应该能够获得一些性能优势 问题是我不知道从哪里开始。通过阅读一些博客文章和浏览MSDN文档,我发现了两种在运行时生成代码的可能策略:表达式树和IL.Emit。使用表达式树似乎容易得多,因为不需要了解操作码和其他各种与MSIL相关的复

我最近了解到,可以在运行时生成C#代码,我想使用这个特性。我有一些代码可以进行一些非常基本的几何计算,比如计算线-平面交点,我认为我可以通过为一些方法生成专门的代码来获得一些性能优势,因为许多计算都是针对同一平面或同一直线反复执行的。通过专门化计算交点的代码,我认为我应该能够获得一些性能优势


问题是我不知道从哪里开始。通过阅读一些博客文章和浏览MSDN文档,我发现了两种在运行时生成代码的可能策略:表达式树和IL.Emit。使用表达式树似乎容易得多,因为不需要了解操作码和其他各种与MSIL相关的复杂情况,但我不确定表达式树是否与手动生成的MSIL一样快。那么,对于我应该使用哪种方法,有什么建议吗?

这两种方法的性能通常是相同的,因为表达式树在内部被遍历,并作为IL使用与您自己使用的相同的底层系统函数发出。从理论上讲,使用低级函数发射更有效的IL是可能的,但我怀疑是否会有任何实际重要的性能增益。这将取决于任务,但与表达式树发出的IL相比,我还没有对发出的IL进行任何实际优化

我强烈建议使用反向编译CLR程序集的工具。有了它,您可以看到实际遍历表达式树并实际发出IL的代码


最后是一个警告。我在语言解析器中使用了表达式树,其中函数调用绑定到运行时从文件编译的语法规则。这里是一个键。对于我遇到的许多问题,当您希望在编译时实现的是已知的时,那么您将不会通过运行时代码生成获得太多性能。某些CLR JIT优化也可能对动态代码不可用。这只是我实践中的一个观点,您的领域可能会有所不同,但如果性能至关重要,我更愿意看本机代码和高度优化的库。如果不使用LAPACK/MKL,我所做的一些工作将非常缓慢。但这只是一条未被要求的建议,所以请谨慎对待。

两者的性能通常是相同的,因为表达式树在内部被遍历,并作为IL使用与您自己使用的相同的底层系统函数发出。从理论上讲,使用低级函数发射更有效的IL是可能的,但我怀疑是否会有任何实际重要的性能增益。这将取决于任务,但与表达式树发出的IL相比,我还没有对发出的IL进行任何实际优化

我强烈建议使用反向编译CLR程序集的工具。有了它,您可以看到实际遍历表达式树并实际发出IL的代码


最后是一个警告。我在语言解析器中使用了表达式树,其中函数调用绑定到运行时从文件编译的语法规则。这里是一个键。对于我遇到的许多问题,当您希望在编译时实现的是已知的时,那么您将不会通过运行时代码生成获得太多性能。某些CLR JIT优化也可能对动态代码不可用。这只是我实践中的一个观点,您的领域可能会有所不同,但如果性能至关重要,我更愿意看本机代码和高度优化的库。如果不使用LAPACK/MKL,我所做的一些工作将非常缓慢。但这只是一条并没有被要求的建议,所以请谨慎对待。

如果我是你们的情况,我会尝试从高层次到低层次的替代方案,增加“所需的时间和精力”,降低可重用性顺序,一旦性能暂时足够好,我就会停止,即:

  • 首先,我要检查Math.NET、LAPACK或其他类似的数字库是否已经具有类似的功能,或者我可以根据自己的需要修改/扩展代码

  • 第二,我会尝试表达树

  • 第三,我会检查(即使是在预发布版本中)

  • 第四,我考虑用不安全的C代码编写普通例程

  • [第五,我会考虑辞职,开始另一个职业生涯:)

  • 只有当这些都不起作用时,我才不会在运行时尝试发射IL


但也许我对低级方法有偏见;您的专业知识、经验和观点可能会有所不同。

如果我是您的情况,我会尝试从高级别到低级别的替代方案,以增加“所需的时间和精力”并降低可重用性顺序,并且我会在性能暂时足够好时停止,即:

  • 首先,我要检查Math.NET、LAPACK或其他类似的数字库是否已经具有类似的功能,或者我可以根据自己的需要修改/扩展代码

  • 第二,我会尝试表达树

  • 第三,我会检查(即使是在预发布版本中)

  • 第四,我考虑用不安全的C代码编写普通例程

  • [第五,我会考虑辞职,开始另一个职业生涯:)

  • 只有当这些都不起作用时,我才不会在运行时尝试发射IL


但也许我对低级方法有偏见;你的专业知识、经验和观点可能会有所不同。

我要补充的是,编写自己的IL充满了oppo