我有这个循环
// 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方法有什么问题?
答案 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垃圾回收越高,应用程序的速度就越慢。
但这只是我的粗略猜测。