使用附加到进程的CLR调试器,.NET代码运行速度会变慢吗?

Ken*_*Ken 2 .net c# debugging

几乎就是标题所说的:我正在运行一个很长的程序,它附加了CLR调试器,所以我可以捕获并检查异常.我的性能是否与在没有调试器的情况下运行它相当,或者是否存在严重(2-10倍或更多)的惩罚?

Han*_*ant 7

重要的是:工具+选项,调试,通用,抑制模块负载的JIT优化.如果你想调试发布代码并获得可比较的性能,你希望这样做.但是这会使调试代码变得更加困难,JIT优化器会将本地变量存储在CPU寄存器中(Watch将无法工作)并重新排序和内联代码(踩踏行为很奇怪).

然后是DebuggableAttribute,由编译器自动生成.它的IsJITOptimizerEnabled和IsJITTrackingEnabled属性很重要.首先,他们努力使局部变量保持活动只需要比所需更长的时间,防止垃圾收集器收集您可能希望在调试器中检查的引用.容易避免,只需调试Release版本而不是Debug版本.

然后在您的程序中发生特定的事情,唤醒调试器并使其窃取CPU周期:

  • 当你的程序抛出异常时.调试器在抛出之前会对其进行一次射击.称为"第一次机会通知",您可以在"输出"窗口中看到它.这就是Debug + Exceptions对话框的工作原理.减慢异常处理速度很慢.
  • 当您的程序加载或卸载DLL时.很多东西都发生在加载时,调试器试图找到DLL的符号.检查是否需要激活任何断点.并在"输出"窗口中显示通知.这通常只会使程序的启动变慢,尤其是在打开混合模式调试时.
  • 当您使用Trace类与DefaultTraceListener,Debug.Write/Line()方法或Console.Write/Line并启用托管进程时.输出显示在"输出"窗口中,会大大减慢这些调用的速度.
  • 当程序中的某个线程启动或停止时.在"输出"窗口中可见.让它减慢你的程序将是一个设计错误.

就是这样,只要不执行上面列出的操作,调试器就会停止运行并让代码全速运行.像ASP.NET和Silverlight这样的运行时环境很特殊,可能还有额外的开销.在64位操作系统上调试Any CPU程序也是如此,这需要远程调试器,因为VS仅为32位.


Jon*_*eet 5

我看到了相当大的差异,是的.

特别是,当抛出异常,他们采取了很多当调试器附加更长的时间.有这可能会影响行为的一些其他显著的优化-例如,垃圾收集器是很多更具侵略性的时候没有连接调试器.

为什么不记录异常而不是破解调试器?除了其他任何东西,这意味着如果你想回去查看昨天发生的异常并将其与刚刚发生的异常进行比较,那很容易......回到过去很难回事:)