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

Sam*_*ron 10 .net cpu performance

有没有人知道一个工具,可以帮助我弄清楚为什么我们在托管应用程序中看到失控的CPU?

想要的:

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

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

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

我在找什么:

  1. 一个简单的exe(没有安装程序)我可以发送给客户.在运行10分钟后,它会生成一个他们发送给我的文件.该文件包含有关在此期间消耗最多CPU及其堆栈跟踪的线程的详细信息.

从技术上讲,我知道可以创建这样的工具(使用ICorDebug),但如果已经存在这样的工具,则不想随时投资.

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

Sam*_*ron 14

基本解决方案

  1. 获取每个托管线程的托管堆栈跟踪.
  2. 抓住基本线程统计每个托管线程(用户模式和内核时间)
  3. 等一会儿
  4. 重复(1-3)
  5. 分析结果并找到消耗最大CPU使用量的线程,向用户显示这些线程的堆栈跟踪.

管理的比 无人堆叠痕迹

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

托管堆栈没那么有用

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

两种方法可以为托管应用程序获取托管堆栈跟踪.

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

什么是更好的生产?

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

CPU-analyzer.exe

所以,我写了一个没有安装程序的小工具,并使用ICorDebug执行上面的基本解决方案.它基于mdbg源,它全部合并为一个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 ...

随意给工具一个机会.它可以从我的博客下载.

编辑

这是一个线程,显示我如何使用cpu-analyzer在生产应用程序中诊断此类问题.

  • 我已经分叉@SamSaffron的代码来通过Nuget(MDbgEngine)添加所需的依赖项:https://github.com/jitbit/cpu-analyzer/blob/master/readme.md以前的mdbg版本不适用于.NET 4.0 (2认同)

Ree*_*sey 5

分析器可能是正确的答案.

如果您不想像DotTrace这样的"完全成熟的分析器",您可能想尝试SlimTune.它工作得很好,完全免费(和开源).