gpt4 book ai didi

c# - 表达树生成的IL是否经过优化?

转载 作者:太空狗 更新时间:2023-10-29 19:59:47 24 4
gpt4 key购买 nike

好的,这仅仅是好奇心,对现实世界没有任何帮助。

我知道使用表达式树可以像常规C#编译器一样即时生成MSIL。因为编译器可以决定优化,所以我很想问在Expression.Compile()期间生成的IL是什么情况。基本上有两个问题:

  • 由于在编译时,编译器在 Debug模式和 Release模式下可以生成不同的IL(可能略有不同),因此在 Debug模式和 Release模式下编译表达式时生成的IL是否存在差异?
  • 同样,在运行时将IL转换为本地代码的JIT在 Debug模式和 Release模式下也应该有很大的不同。编译表达式也是如此吗?还是表达式树中的IL根本不被抖动?

  • 我的理解可能有缺陷,以防万一。

    注意:我正在考虑分离调试器的情况。我问的是Visual Studio中“调试”和“发布”随附的默认配置设置。

    最佳答案

    Since at compile time the compiler can produce different (may be slightly) IL in debug mode and release mode, is there ever a difference in the IL generated by compiling an expression when built in debug mode and release mode?



    这实际上有一个非常简单的答案:不。给定两个相同的LINQ/DLR表达式树,如果一个由在Release模式下运行的应用程序编译,而另一个在Debug模式下运行的应用程序编译,则生成的IL将没有差异。我不确定该如何实现;我不知道 System.Core中的代码有任何可靠的方法可以知道您的项目正在运行调试版本或发布版本。

    但是,这个答案实际上可能会产生误导。表达式编译器发出的IL在调试和发行版本之间可能不会有所不同,但是在C#编译器发出表达式树的情况下,表达式树本身的结构可能在调试和发行模式之间有所不同。我对LINQ/DLR内部非常熟悉,但是对C#编译器却不太了解,所以我只能说在这些情况下可能有所不同(也可能没有)。

    Also JIT which convert IL to native code at run time should be vastly different in both debug mode and release mode. Is this also the case with compiled expressions? Or are IL from expression trees not jitted at all?



    对于预优化的IL和未优化的IL,JIT编译器吐出的机器代码不一定会有很大不同。结果可能完全相同,特别是如果唯一的区别是几个额外的临时值。我怀疑这两种方法在更大,更复杂的方法中会有更大的差异,因为JIT通常会花费时间/精力来优化给定方法。但是,听起来您对如何将LINQ/DLR表达式树的编译质量与以调试或 Release模式编译的C#代码进行比较感兴趣。

    我可以告诉你,LINQ/DLR LambdaCompiler执行的优化很少-肯定比 Release模式下的C#编译器少; Debug模式可能更接近一些,但我会花钱在更具侵略性的C#编译器上。 LambdaCompiler通常不会尝试减少对临时本地语言的使用,而条件,比较和类型转换之类的操作通常会使用比您期望的更多的中间本地语言。我实际上只能想到它确实执行的三个优化:
  • 如果可能,将内联嵌套的lambda(并且“在可能的情况下”往往是“大部分时间”)。实际上,这可以有很大帮助。请注意,这仅在InvokeLambdaExpression时才有效;如果您在表达式中调用已编译的委托(delegate),则它不适用。
  • 至少在某些情况下,会省略不必要/冗余的类型转换。
  • 如果在编译时知道TypeBinaryExpression(即[value] is [Type])的值,则可以将该值内联为常数。

  • 除#3之外,表达式编译器不执行“基于表达式”的优化。也就是说,它不会分析表达式树以寻找优化机会。列表中的其他优化几乎没有树中其他表达式的上下文。

    通常,您应该假设,由LINQ/DLR表达式生成的IL与C#编译器生成的IL相比,优化程度要低得多。但是,生成的IL代码 有资格进行JIT优化,因此,除非您实际尝试使用等效代码来衡量它,否则很难评估对现实世界的性能影响。

    用表达式树编写代码时要牢记的一件事是,实际上,您是编译器1。 LINQ/DLR树被设计为由其他一些编译器基础结构发出,例如各种DLR语言实现。因此,取决于您要在表达式级别上进行优化。如果您是一个草率的编译器,并且发出一堆不必要的或冗余的代码,则生成的IL将更大,并且不太可能被JIT编译器积极地优化。因此,请注意构造的表达式,但不要过多担心。如果您需要高度优化的IL,则可能应该自己发出它。但是在大多数情况下,LINQ/DLR树的性能很好。

    1如果您曾经想知道LINQ/DLR表达式为何如此繁琐,要求精确的类型匹配,那是因为它们旨在用作多种语言的编译器目标,每种语言在方法绑定(bind),隐式和显式类型上可能有不同的规则因此,在手动构造LINQ/DLR树时,必须完成编译器通常会在幕后完成的工作,例如自动为隐式转换插入代码。

    关于c# - 表达树生成的IL是否经过优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19355297/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com