诊断.Net生产应用程序中的失控CPU

时间:2009-11-10 23:50:32

标签: .net performance cpu

有没有人知道一个工具可以帮助我找出为什么我们在托管应用中看到失控的CPU?

寻找:

  1. Process explorer,它有这个很棒的功能,可以让你看到每个线程的CPU,但你没有得到托管堆栈跟踪。此外,它需要一个相当熟练的用户。

  2. Windbg + SOS,它可能用于通过抓取一堆转储来弄清楚发生了什么。但是,对于自动化而言,这是非常重要的。

  3. 完全成熟的分析器(如dottrace或redgate),许可很复杂,并且该工具是一种过度杀伤,需要相当大的安装。

  4. 我在寻找:

    1. 一个简单的exe(没有安装程序)我可以发送给客户。在运行10分钟后,它会生成一个他们发送给我的文件。该文件包含有关在此期间消耗最多CPU及其堆栈跟踪的线程的详细信息。
    2. 从技术上讲,我知道可以创建这样的工具(使用ICorDebug),但如果已存在这样的工具,则不想随时投资。

      那么,有谁知道这样的事情?

10 个答案:

答案 0 :(得分:14)

基本解决方案

  1. 获取每个托管主题的托管堆栈跟踪。
  2. 为每个托管线程(用户模式和内核时间)抓取basic thread statistics
  3. 等一下
  4. 重复(1-3)
  5. 分析结果并找到消耗最大CPU使用量的线程,向用户显示这些线程的堆栈跟踪。
  6. 管理的比赛无人堆栈跟踪

    托管和非托管堆栈跟踪之间存在很大差异。托管堆栈跟踪包含有关实际.Net调用的信息,而非托管堆栈跟踪包含非托管函数指针的列表。由于.Net是jitted,因此在诊断托管应用程序的问题时,非托管函数指针的地址很少用。

    managed stack not that useful

    如何获得任意.Net进程的非托管堆栈跟踪?

    two ways您可以获得托管应用程序的托管堆栈跟踪。

    • 使用CLR分析(又名ICorProfiler API)
    • 使用CLR调试(又名ICorDebug API)

    什么是更好的生产?

    CLR调试API与分析API相比具有非常重要的优势,它们允许您附加到正在运行的进程。在诊断生产中的性能问题时,这可能至关重要。由于一些意外的代码分支执行,经常在应用程序使用几天后弹出失控的CPU。在那个时间点重新启动应用程序(以便对其进行分析)不是一种选择。

    CPU-analyzer.exe

    所以,我写了一个没有安装程序的小工具,并使用ICorDebug执行上面的基本解决方案。它基于mdbg source,它全部合并为一个exe。

    在可配置的时间间隔内(默认为1000毫秒),所有托管线程都需要一个可配置(默认为10)的堆栈跟踪数。

    以下是示例输出:

    C:\>cpu-analyzer.exe evilapp
    ------------------------------------
    4948
    Kernel Time: 0 User Time: 89856576
    EvilApp.Program.MisterEvil
    EvilApp.Program.b__0
    System.Threading.ExecutionContext.Run
    System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal
    System.Threading._ThreadPoolWaitCallback.PerformWaitCallback
    
    ... more data omitted ...
    

    随意给工具一个机会。可以下载from my blog

    修改

    Here is a thread显示我如何使用cpu-analyzer在生产应用中诊断此类问题。

答案 1 :(得分:5)

分析器可能是正确答案。

如果你不想像DotTrace这样的“完全成熟的探查器”,你可能想尝试SlimTune。它工作得很好,完全免费(和开源)。

答案 2 :(得分:2)

听起来你需要一个真正的探查器,但我想我只是把它扔出去:PerfMon。它带有窗口,您可以设置一个可以发送给用户的perfmon配置文件,它们可以捕获并向您发送日志。

每次我需要一个perfmon复习时,我都会保留几个链接: TechNet magazine from 2008a post from the Advanced .NET Debugging blog

答案 3 :(得分:1)

我很幸运Red Gate Ants profiler。但是它确实需要安装。我很确定他们没有远程选项。

答案 4 :(得分:1)

我知道您明确表示您不想采用复杂的转储并使用WinDbg + Sos来分析这些转储。

然而,这可能没有必要。无论如何我建议使用WinDbg,但是当你看到失控的线程时,只需附加到进程,而不是使用转储。然后你需要做的就是运行!runaway命令。这将为您提供每个线程的总运行时间。失控的线程将位于列表的顶部。现在你所要做的就是为顶线程(或者它可能是线程)运行!clrstack。

E.g。如果线程4是您的主要嫌疑人,请执行~4e!clrstack以获取该线程的托管堆栈。这应该告诉你失控的线程正在做什么。

我同意WinDbg并不是最容易使用的工具,但实际上这可能很简单,所以我希望你能原谅我发布的东西并不是真的。

如果WinDbg仍然无法解决,请随时发表评论。

答案 5 :(得分:1)

使用SysInternals ProcDump获取小型转储和windbg + sos进行分析。

ProcDump实用程序可在此处获取:http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx

只需将exe发送给用户并告诉他。运行(例如):

ProcDump MyProgram.exe -c 90 -s 10

如果超过90%的CPU消耗超过10秒

,这将转储进程

答案 6 :(得分:1)

使用托管调试器。以前帮过我。只需要几个文件。您可能只是看到发生了什么(可能是异常处理陷入循环)。

答案 7 :(得分:0)

如果您使用托管代码代替值得使用的分析器,我发现在代码中抛出日志消息对于发现无限循环和一般多线程进程非常有用。

step 1 msg
step 2 msg

线程现在100%而没有第3步msg = bug。

答案 8 :(得分:0)

我认为您应该查看内存和磁盘使用情况。如果机器内存不足并需要开始使用虚拟内存(在磁盘驱动器上),您将看到CPU和磁盘活动的峰值。在这种情况下,看起来像CPU瓶颈实际上是一个内存瓶颈。

答案 9 :(得分:0)

问题越严重,this technique就越容易找到。

你可以得到一个名为Stackshot的工具,它可能会对你的情况有所帮助。 看herehere