调试与发布性能

sag*_*gie 130 c# debugging performance release

我遇到了以下段落:

在Visual Studio中编译代码时,IDE中的"调试与发布"设置对性能几乎没有差别......生成的代码几乎相同.C#编译器并没有真正进行任何优化.C#编译器只是吐出IL ...而在运行时它是执行所有优化的JITer.JITer确实具有调试/释放模式,这对性能产生巨大影响.但这并不能决定你是否运行项目的调试或发布配置,而是关闭是否附加了调试器."

来源在这里,播客在这里.

有人可以指导我一篇能够证明这一点的微软文章吗?

谷歌搜索" C#debug vs release performance "主要返回结果,说" Debug有很多性能损失 "," 发布已经优化 "," 不要将调试部署到生产中 ".

Adr*_*scu 96

部分正确.在调试模式下,编译器为所有变量发出调试符号,并按原样编译代码.在发布模式中,包括一些优化:

  • 未使用的变量根本没有编译
  • 如果证明它们是不变量,则编译器会从循环中取出一些循环变量
  • #debug指令下编写的代码不包含在内.

其余的由JIT决定.

编辑:优化全部列表这里的礼貌埃里克利珀

  • C#编译器不进行尾调用优化; 抖动呢.如果您想要准确列出C#编译器在启用优化开关时所执行的操作,请参阅http://blogs.msdn.com/ericlippert/archive/2009/06/11/what-does-the-optimize-switch- do.aspx (13认同)
  • 不要忘记Debug.Asserts!在DEBUG构建中,如果它们失败,它们将暂停该线程并弹出一个消息框.在发布中,他们根本没有编译.这适用于具有[ConditionalAttribute]的所有方法. (10认同)

Eri*_*ert 62

没有任何文章可以"证明"任何有关性能问题的内容.证明关于变更对性能影响的断言的方法是尝试两种方式并在现实但受控制的条件下对其进行测试.

你问一个关于表现的问题,所以很明显你关心表现.如果您关心性能,那么正确的做法是设置一些性能目标,然后自己编写一个测试套件,跟踪您实现这些目标的进度.一旦你有了这样的测试套件,你就可以轻松地使用它来自己测试语句的真实性或虚假性,例如"调试版本更慢".

此外,您将能够获得有意义的结果."较慢"毫无意义,因为尚不清楚它是慢一毫秒还是二十分钟慢."在现实条件下慢10%"更有意义.

花点时间在网上研究这个问题,建立一个回答问题的设备.通过这种方式,您将获得更准确的结果.你在网上看到的任何东西都只是猜测发生什么.你自己收集的事实的原因,而不是其他人猜测你的程序可能会如何表现的原因.

  • 我认为您可以关心性能,但仍然希望使用“调试”。例如,如果您的大部分时间都在等待依赖项,我认为在调试模式下构建不会有很大的不同,但是您可以获得在堆栈跟踪中获取行号的额外好处,这可能有助于更快地修复错误并使更快乐的用户。关键是您必须权衡利弊,一般的“在调试中运行速度较慢,但​​前提是您受 CPU 限制”语句足以帮助做出决定。 (3认同)

Kon*_*lph 11

我无法对性能发表评论,但建议"不要将调试部署到生产"仍然只是因为调试代码在大型产品中通常会有很多不同的东西.首先,您可能有调试开关处于活动状态,而另一件事可能会有额外的冗余完整性检查和调试输出不属于生产代码.

  • @sagie:是的,我知道这一点,但我认为这一点仍值得制作. (5认同)

Nei*_*eil 6

来自msdn social

它没有很好的记录,这是我所知道的.编译器发出System.Diagnostics.DebuggableAttribute的实例.在调试版本中,IsJitOptimizerEnabled属性为True,在发行版本中为False.您可以使用ildasm.exe在程序集清单中看到此属性

JIT编译器使用此属性来禁用会使调试变得困难的优化.像循环不变的提升一样移动代码的那些.在选定的情况下,这可以在性能上产生很大的不同.虽然不常见.

将断点映射到执行地址是调试器的工作.它使用.pdb文件和JIT编译器生成的信息,它为代码地址映射提供IL指令.如果您要编写自己的调试器,则可以使用ICorDebugCode :: GetILToNativeMapping().

由于禁用了JIT编译器优化,因此调试部署基本上会更慢.