草庐IT

c# - 调试版本和发布版本之间的性能差异

coder 2023-07-06 原文

我必须承认,通常我不会在我的程序中的 Debug 和 Release 配置之间切换,而且我通常选择去 Debug 配置,即使程序实际部署在客户处也是如此。

据我所知,如果不手动更改,这些配置之间的唯一区别是 Debug 具有 DEBUG 常量已定义,Release 已检查优化代码。

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

  • 这两种配置之间是否有很大的性能差异。是否有任何特定类型的代码会导致这里的性能出现巨大差异,或者它实际上并不那么重要?
  • 是否有任何类型的代码可以在 Debug 配置下正常运行而在 Release 配置下可能会失败,或者您能否确定在 Debug 配置下测试并正常工作的代码在 Release 配置下也能正常工作。
  • 最佳答案

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

  • 方法内联。方法调用被注入(inject)方法的代码所取代。这是一个很大的问题,它使属性访问器基本上免费。
  • 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 = 一个; y = x;变成 y = a;这有助于寄存器分配器做出更好的决策。这是 x86 抖动中的一个大问题,因为它几乎没有可用的寄存器。让它选择正确的对性能至关重要。

  • 这些是非常重要的优化,例如,当您分析应用程序的调试版本并将其与发布版本进行比较时,它们可以产生很大的不同。只有当代码在您的关键路径上时才真正重要,您编写的 5% 到 10% 的代码实际上会影响程序的性能。 JIT 优化器不够聪明,无法预先知道什么是关键的,它只能对所有代码应用“将其转换为 11”拨号。

    这些优化对程序执行时间的有效结果通常会受到在别处运行的代码的影响。读取文件、执行 dbase 查询等。使 JIT 优化器所做的工作完全不可见。不过没关系:)

    JIT 优化器是非常可靠的代码,主要是因为它已经接受了数百万次的测试。在您的程序的 Release 构建版本中出现问题的情况极为罕见。然而它确实发生了。 x64 和 x86 抖动都存在结构问题。 x86 抖动在浮点一致性方面存在问题,当浮点计算的中间体以 80 位精度保存在 FPU 寄存器中而不是在刷新到内存时被截断时,会产生细微不同的结果。

    关于c# - 调试版本和发布版本之间的性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4043821/

    有关c# - 调试版本和发布版本之间的性能差异的更多相关文章

    1. ruby - 将差异补丁应用于字符串/文件 - 2

      对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

    2. ruby-on-rails - Rails 应用程序之间的通信 - 2

      我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

    3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

      我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

    4. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

      我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

    5. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

      在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

    6. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

      我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

    7. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

      如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

    8. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

      我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

    9. ruby-on-rails - 无法让 rspec、spork 和调试器正常运行 - 2

      GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'

    10. c# - 如何在 ruby​​ 中调用 C# dll? - 2

      如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

    随机推荐