debugging和发布版本之间的性能差异

我必须承认,通常我不会在我的程序中debugging发布configuration之间切换,而且我通常select去debuggingconfiguration,即使这些程序实际部署在客户的地方。

据我所知,这些configuration之间的唯一区别是,如果您不手动更改它,则Debug将定义DEBUG常量,并且Release将检查Optimize代码

所以我的问题实际上是双重的:

  1. 这两种configuration有很大的性能差异。 有什么特定types的代码会在这里造成很大的性能差异,还是实际上并不那么重要?

  2. 是否有任何types的代码可以在Debugconfiguration下正常运行,在Releaseconfiguration下可能会失败,或者您可以确定在Debugconfiguration下testing并正常工作的代码也可以正常工作。

C#编译器本身不会在Release版本中改变发射的IL。 值得注意的是,它不再发出NOP操作码,允许您在大括号上设置断点。 最重要的是内置在JIT编译器中的优化器。 我知道它做了以下优化:

  • 方法内联。 方法调用被注入方法的代码所取代。 这是一个很大的问题,它使得属性访问器基本上是免费的。

  • CPU寄存器分配。 局部variables和方法参数可以保持存储在CPU寄存器中,而不需要(或不太频繁)存储回栈帧。 这是一个很大的问题,因为debugging优化代码非常困难。 给挥发性关键字一个意思。

  • 数组索引检查消除。 使用数组时,一个重要的优化(所有.NET集合类在内部使用一个数组)。 当JIT编译器可以validation循环从不索引数组越界时,它将消除索引检查。 大的一个。

  • 循环展开。 通过在体内重复代码4次,循环次数减less,小身体循环得到改善。 降低分支成本,并改善处理器的超标量执行选项。

  • 死码消除。 像if(false){/ /}这样的语句完全被删除。 这可能由于不断的折叠和内联而发生。 其他情况下,JIT编译器可以确定代码没有可能的副作用。 这种优化是使分析代码如此棘手的原因。

  • 代码吊装。 不受循环影响的循环内的代码可以移出循环。 C编译器的优化器将花更多的时间来寻找提升的机会。 然而,由于所需的数据stream分析而导致的昂贵的优化,并且抖动无法承受时间,因此只能提供明显的情况。 迫使.NET程序员写出更好的源代码并提升自己。

  • 常见的子expression式消除。 x = y + 4; z = y + 4; 变成z = x; 像dest [ix + 1] = src [ix + 1]; 为了可读性而编写,而不引入辅助variables。 没有必要妥协的可读性。

  • 恒定的折叠。 x = 1 + 2; 变成x = 3; 这个简单的例子很早就被编译器捕获了,但是在其他优化使这成为可能的时候发生了。

  • 复制传播。 x = a; y = x; 变成y = a; 这有助于寄存器分配器做出更好的决定。 x86抖动是一个很大的问题,因为它只有很less的寄存器可以使用。 select正确的对于性能来说至关重要。

这些都是非常重要的优化,例如,在分析应用程序的Debug版本并将其与Release版本进行比较时,可能会产生很大的差异。 只有当代码处于关键path时,这个代码才是真正重要的,你编写的5%到10%的代码实际上影响了程序的性能。 JIT优化器不够智能,无法知道什么是关键,它只能将所有代码应用到“十一”拨号。

这些优化对程序执行时间的有效结果往往受其他地方运行的代码的影响。 读取一个文件,执行一个dbase查询等等。使得JIT优化器的工作完全不可见。 它不介意虽然:)

JIT优化器是非常可靠的代码,主要是因为它已经被testing了数百万次。 在您的程序的发布构build版本中遇到问题极为罕见。 它确实发生。 x64和x86抖动都在结构上有问题。 x86抖动在浮点一致性方面存在问题,当浮点计算的中间值以80位精度保存在FPU寄存器中时,会产生细微差别的结果,而不是在刷新到内存时被截断。

  1. 是的,有很多性能差异,这些都适用于你的代码。 debugging很less做性能优化,而且发布模式非常多;

  2. 只有依赖于DEBUG常量的代码才能在发布版本中执行不同的操作。 除此之外,你不应该看到任何问题。

依赖于DEBUG常量的框架代码的一个例子是Debug.Assert()方法,它具有定义的属性[Conditional("DEBUG)"] 。 这意味着它也依赖于DEBUG常量,这不包含在发布版本中。

这很大程度上取决于您的应用程序的性质。 如果您的应用程序的UI很重,您可能不会注意到任何区别,因为连接到现代计算机的最慢组件是用户。 如果您使用一些UIanimation,则可能需要testing在DEBUG构build中运行时是否可以察觉到任何明显的滞后。

但是,如果你有很多计算繁重的计算,那么你会注意到差异(可能高达@ @ @ @ @ @ @提到的40%,尽pipe这取决于计算的性质)。

这基本上是一个devise权衡。 如果您在DEBUG版本下发布,那么如果用户遇到问题,则可以获得更有意义的回溯,并且可以执行更灵活的诊断。 通过在DEBUG版本中发布,你也可以避免优化器产生晦涩的Heisenbugs 。

  • 我的经验是,在发布版本中,中等规模或更大的应用程序显然更有响应。 试试看你的应用程序,看看它的感觉如何。

  • 有一件事情可以咬住你发布的版本是debugging生成代码有时可以抑制竞争条件和其他线程相关的错误。 优化的代码可能导致指令重新sorting,更快的执行会加剧某些竞争条件。

您不应该将.NET Debug版本发布到生产环境中。 它可能包含丑陋的代码来支持编辑和继续或谁知道还有什么。 据我所知,这只发生在VB而不是C# (注意:原始post被标记为C#) ,但它应该仍然有理由暂停微软认为他们被允许做一个debugging版本。 实际上,在.NET 4.0之前,VB代码会泄漏内存,与您构build的支持“编辑并继续”的事件的对象实例数成正比。 (虽然这是报告是固定的每个https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging ,生成的代码看起来讨厌,创buildWeakReference对象,并把它们添加到一个静态列表,同时持有一个锁 )我当然不希望在生产环境中的任何这种debugging支持!

根据我的经验,发布模式中最糟糕的事情是晦涩的“发布漏洞”。 由于IL(中间语言)在释放模式下进行了优化,因此存在debugging模式中不会出现的错误的可能性。 还有其他的SO问题可以解决这个问题: 在debugging模式下,发布版本错误的常见原因不存在

这发生在我身上一次或两次,一个简单的控制台应用程序可以在debugging模式下完美地运行,但给定完全相同的input,会在发布模式下出错。 这些错误极其难以debugging(具有讽刺意义的是,释放模式的定义)。

我会说1)在很大程度上取决于你的实施。 通常,差异不是那么大。 我做了很多测量,经常看不出有什么不同。 如果你使用非托pipe代码,很多巨大的数组和类似的东西,性能差异稍大,但不是一个不同的世界(如在C + +)。 2)通常在释放代码中显示更less的错误(更高的容忍度),因此开关应该工作正常。

  **Debug Mode:** Developer use debug mode for debugging the web application on live/local server. Debug mode allow developers to break the execution of program using interrupt 3 and step through the code. Debug mode has below features: 1) Less optimized code 2) Some additional instructions are added to enable the developer to set a breakpoint on every source code line. 3) More memory is used by the source code at runtime. 4) Scripts & images downloaded by webresource.axd are not cached. 5) It has big size, and runs slower. **Release Mode:** Developer use release mode for final deployment of source code on live server. Release mode dlls contain optimized code and it is for customers. Release mode has below features: More optimized code Some additional instructions are removed and developer can't set a breakpoint on every source code line. 1) Less memory is used by the source code at runtime. 2) Scripts & images downloaded by webresource.axd are cached. 3) It has small size, and runs fast. 4) Scripts & images downloaded by webresource.axd are cached. 5) It has small size, and runs fast.