为什么使用Debug语句会使代码运行速度变慢?

时间:2011-03-17 04:59:38

标签: .net performance debugging trace

我有这个循环

        // go through each alumni
        foreach (esDL.Alumni currAlumni in allAlumnis)
        {
            ... loop logic

        }

这几乎是不稳定的。

当我输入跟踪或调试语句时......

        foreach (esDL.Alumni currAlumni in allAlumnis)
        {
            ... same loop logic

            Trace.WriteLine("hi");
            Trace.Indent();
            Trace.WriteLine("written");

        }

这会大大减慢速度。 Trace或Debug

为什么?有办法防止这种情况吗?

我只附加了默认侦听器。

编辑 - 经过更多的测试,我发现Trace.Indent让它变得更快,更慢。但只有WriteLine仍然会大大降低性能。 Indent方法有什么问题?

2 个答案:

答案 0 :(得分:1)

任何调试量都可能会使程序速度变慢,甚至达到以十分之一的速度运行。它必须向你的听众发送消息(你似乎没有)和默认的监听器,它将它转发给Debugger.Log和Win32 OutputDebugString - 难怪它会慢一点: - )

至于为什么缩进可能会产生很大的影响,你实际上是不是在那个循环中的某个地方?如果你不是,并且你有2000件物品(根据你在其他地方的评论),当你接近末端时,每条线的前面会有相当大的空间(每条线平均有1000个压痕)有问题)。

答案 1 :(得分:1)

我假设您在不调用Trace.Unindent()的情况下为每一行调用Trace.Indent(),这使得缩进级别不断增加。

假设您有2000行要处理,并且您当前正在处理第1000行,这使得IndentLevel 1000.假定的缩进由'\ t'表示为unicode字符(假设UTF-16,每个字符2个字节)。然后,此时,要创建调试跟踪,必须为迭代中的特定跟踪分配大约2KB的内存。分配该内存大小并不是便宜的操作,实际上您在每次迭代中增加了跟踪条目的大小。

此外,我不清楚何时通过垃圾收集释放内存。换句话说,当底层调试基础设施将使用内存完成时。由于您经常创建长跟踪条目,因此可能会很快耗尽Gen1堆。当垃圾收集器启动并且某些跟踪线未被调试基础结构处理时,它们也将移动到Gen2堆。这将增加您的流程的工作集大小,这可能再次降低您的流程。

您可能需要检查应用程序的.NET性能计数器。我会检查Gen1,Gen2,Gen3堆的大小,总堆大小,Gen1,Gen2,Gen3垃圾收集的#。应用程序执行的Gen垃圾回收越高,应用程序的速度就越慢。

但这只是我的粗略猜测。