【问题标题】:Debug vs. Release performance调试与发布性能
【发布时间】:2011-01-27 14:39:06
【问题描述】:

我遇到过以下段落:

“在 Visual Studio 中编译代码时,IDE 中的调试与发布设置对性能几乎没有影响……生成的代码几乎相同。 C# 编译器实际上并没有做任何优化。 C# 编译器只是吐出 IL……而在运行时它是 JITer 进行所有优化。 JITer 确实有一个 Debug/Release 模式,这对性能有很大的影响。但这并不决定您是否运行项目的 Debug 或 Release 配置,而是决定是否附加了调试器。”

来源是here,播客是here

有人可以指导我阅读可以实际证明这一点的 Microsoft 文章吗?

谷歌搜索“C# 调试与发布性能”主要返回结果说“调试有很多性能损失”、“发布已优化 ”,以及“不要将调试部署到生产环境中”。

【问题讨论】:

  • 另外,如果您关心内存使用,可能会有很大差异。我见过一个案例,在调试模式下编译的多线程 Windows 服务每个线程使用 700MB,而在发布版本中每个线程使用 50MB。在典型的使用条件下,Debug 版本很快就会耗尽内存。
  • @Bengie - 您是否确认如果您将调试器附加到发布版本,它的运行速度仍然快 2 倍?请注意,上面的引用表示 JIT 优化受是否附加调试器的影响。

标签: c# performance debugging release


【解决方案1】:

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

  • 根本不编译未使用的变量
  • 如果某些循环变量被证明是不变量,编译器会将其从循环中取出
  • #debug 指令下编写的代码不包括在内,等等。

其余的取决于 JIT。

完整的优化列表 hereEric Lippert 提供。

【讨论】:

  • 别忘了 Debug.Asserts!在 DEBUG 构建中,如果它们失败,它们将停止线程并弹出一个消息框。在发布时,它们根本没有被编译。这适用于所有具有 [ConditionalAttribute] 的方法。
  • C# 编译器不做尾调用优化;抖动确实如此。如果您想获得 C# 编译器在优化开关打开时所做的准确列表,请参阅blogs.msdn.com/ericlippert/archive/2009/06/11/…
【解决方案2】:

没有任何文章可以“证明”有关性能问题的任何内容。证明更改对性能影响的断言的方法是尝试两种方法,并在现实但受控的条件下进行测试。

您问的是关于性能的问题,所以显然您关心性能。如果您关心性能,那么正确的做法是设定一些性能目标,然后为自己编写一个测试套件来跟踪您针对这些目标的进度。一旦你有了这样一个测试套件,你就可以轻松地使用它来为自己测试诸如“调试构建速度较慢”之类的陈述的真假。

此外,您将能够获得有意义的结果。 “慢”是没有意义的,因为不清楚是慢了 1 微秒还是慢了 20 分钟。 “在现实条件下慢 10%”更有意义。

花费您在网上研究这个问题所花费的时间来构建一个可以回答这个问题的设备。这样,您将获得更准确的结果。您在网上阅读的任何内容都只是猜测关于可能会发生什么。根据您自己收集的事实进行推理,而不是根据其他人对您的程序可能行为方式的猜测。

【讨论】:

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

我无法评论性能,但“不要将调试部署到生产环境”的建议仍然成立,因为调试代码在大型产品中通常会做很多不同的事情。一方面,您可能启用了调试开关,另一方面可能会有额外的冗余完整性检查和不属于生产代码的调试输出。

【讨论】:

  • 我同意你在这个问题上的看法,但这并不能回答主要问题
  • @sagie:是的,我知道这一点,但我认为这一点仍然值得一提。
【解决方案4】:

来自msdn social

没有很好的记录,这里是什么 我知道。编译器发出一个 的实例 System.Diagnostics.DebuggableAttribute。 在调试版本中, IsJitOptimizerEnabled 属性是 没错,在发布版本中它是 错误的。您可以在中看到此属性 带有 ildasm.exe 的程序集清单

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

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

由于禁用了 JIT 编译器优化,基本上调试部署会变慢。

【讨论】:

    【解决方案5】:

    您阅读的内容非常有效。由于 JIT 优化,发布通常更精简,不包括调试代码(#IF DEBUG 或 [Conditional("DEBUG")]),最小的调试符号加载并且通常不考虑是较小的程序集,这将减少加载时间。在 VS 中运行代码时,由于加载了更广泛的 PDB 和符号,性能差异更加明显,但如果单独运行,性能差异可能不太明显。某些代码会比其他代码优化得更好,并且它使用与其他语言相同的优化启发式算法。

    Scott 对内联方法优化有很好的解释here

    请参阅this article 简要说明为什么它在 ASP.NET 环境中的调试和发布设置不同。

    【讨论】:

      【解决方案6】:

      您应该注意的一点是,关于性能以及是否附加了调试器,这让我们大吃一惊。

      我们有一段代码,涉及许多紧密的循环,似乎需要很长时间才能调试,但它本身运行得很好。换句话说,没有客户或客户遇到问题,但当我们调试时,它似乎像糖蜜一样运行。

      罪魁祸首是其中一个紧密循环中的Debug.WriteLine,它会吐出数以千计的日志消息,这些消息是不久前调试会话留下的。似乎当调试器被附加并监听这样的输出时,涉及的开销会减慢程序的速度。对于这个特定的代码,它本身的运行时间约为 0.2-0.3 秒,附加调试器时需要 30 多秒。

      简单的解决方案,只需删除不再需要的调试消息。

      【讨论】:

        【解决方案7】:

        msdn 网站...

        发布与调试配置

        当你还在为你的 项目,您通常会构建您的 通过使用调试应用程序 配置,因为这 配置使您可以查看 变量值和控制 在调试器中执行。你可以 还可以在 发布配置以确保 你还没有引入任何错误 仅在一种类型的构建或 另一个。在 .NET 框架中 编程,这样的错误非常罕见, 但它们可能会发生。

        当您准备好分发您的 应用程序到最终用户,创建一个 发布版本,这将是很多 更小,通常会有很多 性能优于 相应的调试配置。你 可以在 项目设计器的构建窗格,或 在构建工具栏中。更多 信息,请参阅构建配置。

        【讨论】:

          【解决方案8】:

          我最近遇到了性能问题。产品完整列表花费了太多时间,大约 80 秒。我调整了数据库,改进了查询,没有任何区别。我决定创建一个 TestProject,我发现同样的过程在 4 秒内执行。然后我意识到该项目处于调试模式,而测试项目处于发布模式。我将主项目切换到发布模式,产品完整列表只用了 4 秒即可显示所有结果。

          总结:调试模式比运行模式慢得多,因为它保留了调试信息。您应该始终以发布模式进行部署。如果包含 .PDB 文件,您仍然可以获得调试信息。例如,这样您就可以使用行号记录错误。

          【讨论】:

          • “运行模式”是指“发布”?
          • 是的,完全正确。发布没有所有的调试开销。
          【解决方案9】:

          在很大程度上,这取决于您的应用程序是否受计算限制,并且并不总是像 Lasse 的示例那样容易分辨。如果我对它在做什么有任何疑问,我会暂停它几次并检查堆栈。如果发生了一些我并不真正需要的额外内容,我会立即发现它。

          【讨论】:

            【解决方案10】:

            调试和发布模式有所不同。有一个工具Fuzzlyn:它是一个利用 Roslyn 生成随机 C# 程序的 fuzzer。它在 .NET 核心上运行这些程序,并确保它们在调试和发布模式下编译时给出相同的结果。

            用这个工具发现并报告了很多错误。

            【讨论】:

              【解决方案11】:

              关闭日志记录和调试 确保在构建应用程序以供发布之前停用日志记录并禁用调试选项。您可以通过删除源文件中对 Log 方法的调用来停用日志记录。您可以通过从清单文件中的标记中删除 android:debuggable 属性或通过在清单文件中将 android:debuggable 属性设置为 false 来禁用调试。此外,删除在您的项目中创建的所有日志文件或静态测试文件。

              https://developer.android.com/studio/publish/preparing

              How to remove all debug logging calls before building the release version of an Android app?

              Difference between debug and release apks

              开发、测试、验收和生产

              https://blog.chizobaogbonna.me/having-different-variants-debug-staging-release-of-your-app-on-a-single-device-2efdcaaf4950 https://ajiethkumar.wordpress.com/2017/04/07/it-environments-management/ https://www.onlinecomputertips.com/support-categories/networking/646-what-is-a-dmz 内部网络与外围

              https://dev.to/aws-builders/jump-over-a-hurdle-of-working-with-amplify-backend-environment-c77

              https://en.wikipedia.org/wiki/Development,_testing,_acceptance_and_production https://oroinc.com/b2b-ecommerce/blog/testing-and-staging-environments-in-ecommerce-implementation/

              https://medium.com/the-liberators/want-to-be-agile-drop-your-dtap-pipeline-7dcb496fe9e3

              https://www.bmc.com/blogs/what-is-shift-left-shift-left-testing-explained/ https://blogs.vmware.com/management/2013/11/features-for-thought-series-vcac-6-0-simplify-application-deployments-across-any-environment.html https://enterprise.arcgis.com/en/server/10.3/administer/linux/arcgis-server-in-development-staging-and-production-environments.htm https://learn.timextender.com/courses/259790/lectures/4029947 https://humanitec.com/blog/kubernetes-environments-basics https://blogs.oracle.com/openomics/leveraging-a-disaster-recovery-site-for-development-part-2 https://doc.oroinc.com/cloud/environments/

              【讨论】:

                猜你喜欢
                • 2019-11-25
                • 2014-10-23
                • 2011-03-26
                • 2015-01-13
                • 1970-01-01
                • 2011-04-02
                • 2011-03-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多