【问题标题】:Is there a way to tell if a C# assembly has been compiled with the optimization parameter?有没有办法判断 C# 程序集是否已使用优化参数编译?
【发布时间】:2010-08-20 18:02:08
【问题描述】:

相反,有没有办法判断它是在启用还是禁用优化参数的情况下编译的。我不想知道它是发布还是调试,因为可以启用或不启用优化。从我的角度来看,即使代码说它是发布版本,它真的优化了吗?谢谢。

【问题讨论】:

    标签: c# optimization assemblies


    【解决方案1】:

    我迟到了 8 年,但如果你和我一样想要 C# 方式,那就是:

    using System.ComponentModel;
    using System.Diagnostics;
    using System.Reflection;
    
    internal static class AssemblyExtensions
    {
        public static bool IsOptimized(this Assembly asm)
        {
            var att = asm.GetCustomAttribute<DebuggableAttribute>();
            return att == null || att.IsJITOptimizerDisabled == false;
        }
    }
    

    作为扩展方法:

    static void Main(string[] args)
    {
        Console.WriteLine("Is optmized: " + typeof(Program).Assembly.IsOptimized());
    }
    

    【讨论】:

      【解决方案2】:

      一种检查方法是查看程序集上的DebuggableAttribute (doc)。如果 C# 编译器通过了 /optimize 选项,则不会设置 DisableOptimizations 标志。

      注意:尽管这适用于大多数情况,但这并不是 100% 万无一失的解决方案。至少可以通过以下方式破解它

      1. 使用具有不同语义的另一种语言进行编译以进行优化
      2. 如果用户手动定义 DebuggableAttribute,它将优先于 C# 编译器定义的内容

      【讨论】:

      • 1.可能不是问题,因为问题是关于 C# 程序集,但是,不会 2. 仍然有效(如果用户覆盖该属性,那不会摆脱运行时优化,因此可以考虑程序集因为没有优化?)
      • @Zaki 是和不是。 JIT 优化将被禁用,但不会启用其他 C# 编译器优化。
      • @Hans,把自己和负面的东西搞混了。固定。
      • 很好,谢谢大家。在 Scott Hanselman 的博客上找到了这个,它提供了代码来做到这一点。谢谢。 hanselman.com/blog/…
      • 请注意,您可以使用 ILSpy(或类似工具)查看程序集的属性。
      【解决方案3】:

      使用 Ildasm.exe 查看程序集清单:

        // --- The following custom attribute is added automatically, do not uncomment -------
        //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(
                valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) 
                = ( 01 00 02 00 00 00 00 00 ) 
      

      这是发布版本。调试构建值为 ( 01 00 07 01 00 00 00 00 )

      另一个问题是调试器可以禁用 JIT 优化器。这是 VS、工具 + 选项、调试、常规、“抑制模块加载时的 JIT 优化”中的一个可配置选项。如果您正在调试 Release 版本并想要相当的性能,您希望关闭它。它使调试更具挑战性,随着优化器重新排列和内联代码,单步执行的行为很奇怪,而且您通常无法检查局部变量的值,因为它们存储在 CPU 寄存器中。

      【讨论】:

      • 当我设置为启用时,C#“优化代码”,并在调试中重建,我仍然看到你引用的调试值。 // --- 自动添加以下自定义属性,不要取消注释 ------- // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics. DebuggableAttribute/DebuggingModes) = (01 00 07 01 00 00 00 00)
      • 我刚刚重新检查了VS2012。不,仍然像我描述的那样工作。更改选项后不要忘记重建。
      • 谢谢。当代码未优化时,我得到了我上面描述的内容,这与您的描述相匹配,但是当我对其进行优化时,默认情况下设置为发布模式,清单中根本没有提到调试属性。是的,这与我上面的陈述相冲突,抱歉。我将继续查看我的程序集,看看是否可以看到带有您提到的构建值的 DebuggableAttribute - 当代码设置为优化时。这是VS2010。谢谢。
      • 在对这种方法进行一些后续操作时,“(01 00 02 00 00 00 00 00)”的 DebuggableAttribute 值似乎是一个优化的程序集,但只有 pdb 输出。如果程序集在输出设置为完整的情况下进行了优化,则 DebuggableAttribute 将显示为“(01 00 03 00 00 00 00 00)”。最后,如果它被优化,输出设置为无,这里将根本没有 DebuggableAttribute。
      【解决方案4】:

      这篇文章可能对您有所帮助http://www.panopticoncentral.net/archive/2004/02/03/267.aspx

      具体来说,在 ildasm 中,您可以查找 DebuggableAttribute 和 NOP 的缺失。

      【讨论】:

      • 该信息特定于 VB.Net 编译器。它的语义与 C# 非常相似但略有不同。
      最近更新 更多