我可以在附加调试器的DEBUG中避免慢速.net异常吗?

时间:2015-10-28 15:31:12

标签: .net visual-studio debugging exception exception-handling

我可以运行一个在调试器中大量使用异常的程序而不是在调试器中捕获异常吗?

具体来说,我正在尝试使用TSQL ScriptDOM解析器,我理解it's use of ANTLR is slow in debug mode

  

如果你看一下调试输出,你会发现并不奇怪   这是由Microsoft®SQLServer®2012Transact-SQL引起的   ScriptDom解析器,因为它基于ANTLR框架,所以   使用异常展开AST制作,这就是它的作用   在调试器内部运行时速度很慢。

我完全理解.net例外are slow when thrown

如果使用标准DEBUG配置运行,并且连接了调试器,我怎样才能避免缓慢?

  • 我已禁用intellitrace。
  • 我未定义DEBUG常量。
  • 我在工具>中关闭了异常消息选项>调试>输出窗口。

我还能尝试什么?

  • 我可以通过app.config更改CLR设置吗?
  • 在Visual Studio中更改选项?

这是我用于解析的特定代码。

TSqlParser parser = new TSql110Parser(false);
IList<ParseError> errors;
TSqlFragment fragment = parser.Parse(new StringReader(sqltext), out errors);

使用CTRL + F5运行时,它快速完成,并使用F5(附带调试器),我放弃等待。

4 个答案:

答案 0 :(得分:7)

您可以执行的一种可能的解决方法(我遇到了一个类似的问题,如果在调试器附加到特别大的数据集上时,如果使用图像处理库会抛出OutOfMemoryException),则会在调用之前设置断点在断点重新附加调试器Debugger.Launch()之后,转到第三方库代码并分离调试器。

#if DEBUG
bool debuggerAttached = Debugger.IsAttached;
if(debuggerAttached)
{
    Debugger.Break(); //Detach the debugger to make the next section faster.
}
#endif

TSqlParser parser = new TSql110Parser(false);
IList<ParseError> errors;
TSqlFragment fragment = parser.Parse(new StringReader(sqltext), out errors);

#if DEBUG
if(debuggerAttached && !Debugger.IsAttached)
{
    Debugger.Launch();
}
#endif

答案 1 :(得分:4)

您无法阻止异常,并且调试器下的第一次机会异常很慢,因为 进程暂停,操作转移到调试器以说明是否要知道它和然后客户端再次重启(直到下一个)。 这就是Win32 Debug Api的工作方式,我担心。

我做了很多ScriptDom的调试,我提出的最好的解决方法是解析形式良好且有效的小脚本。

我尝试将脚本限制为只有有问题的部分。

答案 2 :(得分:2)

实际上,.NET异常并不是很慢,尽管它们并不是速度恶魔。在你失去一生之前,你可以扔掉一万个胖子。事实上,你的调试器速度很慢。它尽职地报告输出窗口中的异常,这非常昂贵。

非常容易修复,在调试时右键单击窗口并取消勾选&#34;异常消息&#34;。您可以使用工具&gt;将该设置设为永久设置。选项&gt;调试&gt;输出窗口。

如果您仍需要等待太长时间,请确保使用小型数据集调试代码,这样您就不必永远等待。代码仅在100,000但未在100个数据项上失败的可能性非常低。您测试应用程序处理大量数据以验证其是否可以很好地扩展,这非常重要非常重要。但是你只能在没有附加调试器的Release版本中这样做。

答案 3 :(得分:1)

如果您有一些引发很多异常的代码,则可以perform very slowly if the debugger is attached

要提高这种方法的速度,可以在顶部添加DebuggerNonUserCode属性。例如:

[DebuggerNonUserCode]
public static bool IsArchive(string filename)
{
    bool result = false;
    try
    {
        //this calls an external library, which throws an exception if the file is not an archive
        result = ExternalLibrary.IsArchive(filename);
    }
    catch
    {

    }
    return result;
}