据我所知,如果不手动更改,则这些配置之间的唯一区别是Debug定义了
DEBUG
常量,而Release则检查了Optimize代码。所以我的问题实际上是双重的:
这两种配置之间在性能上有很大差异。是否有任何特定类型的代码会在这里造成性能上的巨大差异,或者实际上它不那么重要?
是否有任何类型的代码在Debug配置下可以正常运行而在Release配置下可能会失败,或者您可以确定在Debug配置下经过测试且可以正常工作的代码在Release配置下也可以正常工作。
#1 楼
C#编译器本身不会在Release版本中对发出的IL进行很大的更改。值得注意的是,它不再发出允许您在花括号上设置断点的NOP操作码。最大的一个是内置在JIT编译器中的优化器。我知道它可以进行以下优化:方法内联。方法调用由注入方法的代码代替。这是一个很大的问题,它使属性访问器基本免费。
CPU寄存器分配。局部变量和方法参数可以保持存储在CPU寄存器中,而无需(或不太频繁)存储回堆栈帧。这是一个很大的问题,值得注意的是使调试优化的代码变得如此困难。并赋予volatile关键字一个含义。
数组索引检查消除。使用数组时的一项重要优化(所有.NET集合类在内部使用数组)。当JIT编译器可以验证循环永不对数组进行索引时,它将消除索引检查。大个子。
循环展开。通过在主体中重复执行多达4次且减少循环的代码,可以改善具有小主体的循环。降低分支成本并改善处理器的超标量执行选项。
消除死代码。像if(false){/.../}这样的语句被完全消除。这可能是由于不断折叠和内嵌而发生的。在其他情况下,JIT编译器可以确定代码没有可能的副作用。这种优化使概要分析代码变得如此棘手。
代码提升。不受循环影响的循环内的代码可以移出循环。 C编译器的优化器将花费更多的时间来寻找提升的机会。然而,由于需要进行数据流分析,因此这是一项昂贵的优化,并且抖动无法承受时间,因此只能提升明显的情况。迫使.NET程序员编写更好的源代码并自行提升。
常见子表达式消除。 x = y + 4; z = y + 4;变成z = x;在dest [ix + 1] = src [ix + 1]等语句中很常见;为提高可读性而编写,而没有引入辅助变量。无需牺牲可读性。
不断折叠。 x = 1 + 2;变成x = 3;这个简单的示例早已被编译器捕获,但发生在JIT时,其他优化使之成为可能。
复制传播。 x = a; y = x;变成y = a;这有助于寄存器分配器做出更好的决策。这是x86抖动中的一个大问题,因为它很少使用寄存器。选择合适的选项对于性能而言至关重要。
这些非常重要的优化可以极大地改善性能,例如,在分析应用的Debug版本并将其与发布版本。这只是真正重要,尽管当代码位于关键路径上时,所编写代码的5%至10%实际上会影响程序的性能。 JIT优化器不够聪明,无法预先知道关键是什么,它只能对所有代码应用“将其旋转到11”拨盘。
这些优化对程序执行时间的有效结果通常受在其他地方运行的代码的影响。读取文件,执行dbase查询等。使这项工作完全不可见。不过,它并不介意:)
JIT优化器是非常可靠的代码,主要是因为它已经经受了数百万次测试。在程序的发布版本中出现问题的情况很少见。但是确实发生了。 x64和x86抖动都存在结构问题。 x86抖动在浮点一致性方面存在麻烦,当浮点计算的中间值以80位精度保存在FPU寄存器中,而不是在刷新到内存时会被截断时,会产生完全不同的结果。
评论
我不认为所有集合都使用数组:LinkedList
– svick
2011年6月18日18:26
我认为CLR将FPU配置为53位精度(匹配64位宽的双精度),因此对于Float64值,不应有80位扩展的双精度计算。但是,Float32计算可能会以这种53位精度进行计算,并且只有在存储到内存时才会被截断。
– Govert
2012年5月21日15:34
volatile关键字不适用于存储在堆栈框架中的局部变量。从msdn.microsoft.com/zh-cn/library/x13ttww7.aspx上的文档中:“ volatile关键字只能应用于类或结构的字段。不能将局部变量声明为volatile。”
–克里斯·范德莫滕
2014年5月5日,11:45
作为一个卑微的修正,我想在这方面真正使Debug和Release版本之间有所不同的是“优化代码”复选框,该复选框通常在Release上启用,而在Debug上禁用。只是要确保读者不要开始认为这两个构建配置之间存在着“不可思议的”,看不见的差异,这些差异超出了Visual Studio中项目属性页的范围。
– chiccodoro
2014年7月2日在10:37
也许值得一提的是,实际上System.Diagnostics.Debug上的任何方法都无法在调试版本中执行任何操作。另外,变量的确定速度还不够快,请参见(stackoverflow.com/a/7165380/20553)。
–马丁·布朗
2014-10-20 14:00
#2 楼
是的,存在许多性能差异,这些差异确实适用于您的所有代码。 Debug几乎没有进行性能优化,而释放模式却非常多;
只有依赖
DEBUG
常数的代码在发布版本中的执行可能会有所不同。除此之外,您应该不会看到任何问题。DEBUG
方法是依赖Debug.Assert()
常数的框架代码示例,该方法定义了[Conditional("DEBUG)"]
属性。这意味着它还取决于DEBUG
常数,并且不包含在发行版中。评论
都是如此,但是您能衡量出差异吗?还是在使用程序时注意到差异?当然,我不想鼓励任何人以调试模式发布他们的软件,但是问题是,是否存在巨大的性能差异,我看不到这一点。
– testalino
2010-10-28 14:35
还值得注意的是,调试版本与原始源代码的关联程度远高于发行版。如果您认为(但是不太可能)有人尝试对您的可执行文件进行反向工程,则您不希望通过部署调试版本来使它们变得更容易。
– jwheron
2010-10-28 14:42
@testalino-好吧,这些天很难。处理器已经变得如此之快,以至于由于用户的行为,用户几乎不等待进程实际执行代码,因此这是相对的。但是,如果您实际上在做一些漫长的过程,是的,您会注意到。以下代码例如在DEBUG下运行速度降低40%:AppDomain.CurrentDomain.GetAssemblies()。Sum(p => p.GetTypes()。Sum(p1 => p1.GetProperties()。Length))。
–Pieter van Ginkel
2010-10-28 14:42
另外,如果您位于asp.net上并使用debug而不是release,则可能会在页面上添加一些脚本,例如:大约有7k行的MicrosoftAjax.debug.js。
– BrunoLM
2010-10-28 15:34
#3 楼
这在很大程度上取决于应用程序的性质。如果您的应用程序是大量使用UI的,那么您可能不会注意到任何区别,因为连接到现代计算机的最慢的组件是用户。如果您使用某些UI动画,则可能需要测试在DEBUG版本中运行时是否可以察觉到任何明显的滞后。但是,如果您有许多计算量大的计算,那么您会注意到差异(可能高达@Pieter提到的40%,尽管这将取决于计算的性质。)
这基本上是设计折衷。如果要在DEBUG版本下发布,那么如果用户遇到问题,则可以获得更有意义的回溯,并且可以进行更灵活的诊断。通过发布DEBUG版本,您还可以避免优化程序产生模糊的Heisenbug。
#4 楼
我的经验是,中型或大型应用程序在Release版本中的响应速度明显更快。尝试一下您的应用程序,看看它的感觉。
与Release版本咬合的一件事是,Debug版本代码有时可以抑制竞争条件和其他与线程相关的错误。优化的代码可能导致指令重新排序,更快的执行可能加剧某些竞争条件。
#5 楼
您永远不应将.NET Debug版本发布到生产环境中。它可能包含丑陋的代码以支持“编辑并继续”功能,或者谁知道呢。据我所知,这仅在VB中发生,而不是在C#中发生(请注意:原始文章被标记为C#),但它仍应为暂停Microsoft认为允许他们使用Debug版本所做的事情提供理由。实际上,在.NET 4.0之前,VB代码泄漏的内存与具有为支持“编辑并继续”而构造的事件的对象实例的数量成比例。 (尽管据报告,此问题是根据https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging生成的代码修复的看起来很讨厌,创建WeakReference
对象并按住它们将它们添加到静态列表中)我当然不希望在生产环境中提供任何这种调试支持!评论
我已经多次发布了Debug版本,但从未遇到问题。也许唯一的区别是,我们的服务器端应用程序不是支持许多用户的Web应用程序。但这是具有很高处理负载的服务器端应用程序。根据我的经验,Debug和Release之间的区别似乎完全是理论上的。我从未见过任何与我们的应用程序有任何实际差异。
–山姆·戈德堡
18年6月8日在13:52
#6 楼
我会说很大程度上取决于您的实现。通常,差异不是很大。我做了很多测量,但常常看不到差异。如果您使用非托管代码,大量数组和类似的东西,则性能差异会稍大一些,但世界却不一样(例如C ++)。
通常,发布代码中的代码较少显示错误(更高的公差),因此开关应该可以正常工作。
评论
对于受IO约束的代码,发布版本可能很容易调试得很快。
–理查德
2010-10-28 15:02
#7 楼
以我的经验,发布模式中最糟糕的事情是晦涩的“发布错误”。由于IL(中间语言)在Release模式下进行了优化,因此存在可能在Debug模式下未发现的错误。还有其他SO问题可以解决此问题:在调试模式下不存在发行版中的错误的常见原因
我经历过一两次,在此简单的控制台应用程序可以很好地运行在“调试”模式下,但输入完全相同,则在“发布”模式下会出错。这些错误极其难以调试(具有讽刺意味的是,根据发布模式的定义)。
评论
为了跟进,下面的文章提供了发行错误的示例:codeproject.com/KB/trace/ReleaseBug.aspx
–罗伊
2010-10-28 14:58
如果使用Debug设置测试并批准了该应用程序,即使它抑制了错误,仍然会导致问题,即使这会导致发行版本的构建在部署过程中失败。
–ØyvindBråthen
2010-10-28 18:33
#8 楼
**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:
1) More optimized code
2) Some additional instructions are removed and developer can’t set a breakpoint on every source code line.
3) Less memory is used by the source code at runtime.
4) Scripts & images downloaded by webresource.axd are cached.
5) It has small size, and runs fast.
评论
似乎在发布模式下,有时列表的前几个元素编号不正确。列表中的某些元素也是重复的。 :)
–吉安·保罗(Gian Paolo)
18年1月19日在14:36
评论
相关:stackoverflow.com/questions/33871181/…