我最近了解到可以在运行时生成C#代码,我想使用此功能。我有一些代码可以做一些非常基本的几何计算,比如计算线平面交叉点,我想我可以通过为某些方法生成专门的代码来获得一些性能优势,因为许多计算是针对同一平面或同一行执行的再来一次。通过专门化计算交叉点的代码,我认为我应该能够获得一些性能上的好处。
问题在于我不知道从哪里开始。通过阅读一些博客文章和浏览MSDN文档,我遇到了两种在运行时生成代码的可能策略:表达式树和IL.Emit。使用表达式树似乎更容易,因为不需要学习任何有关OpCodes和其他各种MSIL相关复杂性的知识,但我不确定表达式树是否与手动生成的MSIL一样快。那么有什么建议我应该采用哪种方法?
答案 0 :(得分:4)
两者的性能通常是相同的,因为表达式树在内部被遍历并使用您自己使用的相同底层系统函数作为IL发出。理论上可以使用低级函数发出更高效的IL,但我怀疑是否会有任何实际上重要的性能增益。这取决于任务,但与表达树发出的IL相比,我没有对发射的IL进行任何实际优化。
我强烈建议使用名为ILSpy的工具反向编译CLR程序集。有了它,您可以查看实际遍历表达式树并实际发出IL的代码。
最后,一个警告。我在语言分析器中使用了表达式树,其中函数调用绑定到在运行时从文件编译的语法规则。编译是这里的关键。对于我遇到的许多问题,当你想要实现的目标在编译时已知时,那么运行时代码生成就不会获得太多的性能。某些CLR JIT优化可能也不适用于动态代码。这只是我的实践中的意见,你的域名会有所不同,但如果性能至关重要,我宁愿看看本机代码,高度优化的库。如果不使用LAPACK / MKL,我所做的一些工作将是慢速的蜗牛。但这只是未提出要求的一部分,所以请耐心等待。
答案 1 :(得分:2)
如果我在你的情况下,我会尝试从高级别到低级别的替代方案,增加“需要时间和努力”并降低可重用性顺序,并且我会在性能足够好的时候立即停止存在,即:
首先,我会检查Math.NET,LAPACK或类似的数字库是否已经具有相似的功能,或者我可以根据我的需要调整/扩展代码;
第二,我会尝试表达树;
第三,我检查Roslyn Project(即使它是预发布版本);
第四,我考虑用不安全的C代码编写常见例程;
[第五,我考虑退出并开始其他职业的新职业:)],
并且只有当这些都没有成功时,我才会在运行时尝试发射IL而无望。
但也许我对低级别方法有偏见;您的专业知识,经验和观点可能会有所不同。