5

假设有一个 C# 程序,它被用作 Windows 服务。让我们假设服务变得疯狂并且疯狂地消耗 CPU 和内存。它需要尽快重新启动,因为它是一个生产系统。所以我没有太多时间来收集运行时信息。也许快速浏览一下任务管理器......就是这样。

之后,我只有 log4net 日志文件和用于事后分析的 Windows 事件日志。

假设我找到了问题的原因。其他人修复了它,也许程序员添加了一些额外的日志记录,这样我下次可以更快地找到类似的问题。尽管如此:我仍然依赖于日志文件的质量,并希望下次出现问题时会以某种方式在日志中显示出来。

还有其他方法可以进行事后分析吗?也许像线程转储(如在 java 中)、内存转储或其他可能有助于事后分析的东西?也许一些内置的 .NET 框架工具可以提供帮助?

我对真实的项目经验以及您将如何尝试解决这个维护问题非常感兴趣,我认为这对大多数程序员来说都是非常真实的。

4

5 回答 5

2

您可以使用 .NET 进行故障转储,并使用 windbg / sos(和 sosassist)查看它们。不简单,但它有效。但相当铁杆。搜索“+windbg +.NET”应该会很有趣。

除此之外 - 资源计数器?日志文件?您可能会看到很多可以相当容易地启用的东西。

于 2009-01-18T13:33:01.523 回答
2

正如 Marc 所说,WinDbg + SoS 将让您调试很多问题,您无法在 Visual Studio 中真正解决。这个博客有一些很棒的教程。

对于内存问题,您还可以查看 Perfmon 中的 .NET 性能计数器。您可以查看对象的位置(哪一代)以及垃圾收集花费了多少时间。这应该会给你一些有用的信息。如果您想知道为什么没有收集对象,WinDbg 和 SoS 是您的最佳选择。为了引导您完成一个简单的会话,步骤如下:

  1. 使用 检查堆!dumpheap -stat,查找大量实例。您可能对在任何给定时刻会在堆上找到什么有所了解,所以如果有什么不寻常的地方,请调查一下。

  2. 选择随机实例并对实例!gcroot的地址执行操作。这将告诉您为什么没有收集对象。

  3. 重复

使东西保持比应有的时间更长的可能候选者是:事件、静态和终结器队列等等。

您可能还想查看我对这个问题的回答,以了解更多 WinDbg 内容。

于 2009-01-18T13:59:16.400 回答
1

使用 WinDbg 和 SOS 进行事后分析的一个很好的资源是 Tess Ferrandez 关于该主题的一系列博客文章

编辑:链接已更新

于 2009-01-18T13:56:17.730 回答
1

不幸的是,我不得不做很多这样的事情——我遇到的最好的工具是 sdk 附带的 cordbg(你需要正确的 .net 版本)。http://msdn.microsoft.com/en-us/library/a6zb7c8d.aspx了解详情。

附加到 cordbg (a <[pid]>) 中正在运行的进程,附加到每个正在运行的线程 (t <[tid]>),然后转储每个线程 (w) 的堆栈。

使用一个小的 vb 脚本自动执行此任务,然后转储到文件中,您可以多次运行此工具,将输出捕获到文件中。比较所有线程堆栈可以让您很好地了解应用程序将时间花在哪里。

这种方法的好处是,尤其是自动转储,您可以非常快速地获取所有信息并在最短的时间内重新启动您的流程。

于 2009-01-18T15:18:18.720 回答
0

如果该过程仍然存在,那么您可以针对它运行托管堆栈资源管理器以快速了解它正在做什么。您可以在没有显式安装的情况下运行它。

除此之外,完整的转储 + windbg + SOS 可以为您提供最多的信息,但获得它并非易事。

于 2009-01-18T14:09:55.317 回答