【发布时间】:2017-04-19 12:13:18
【问题描述】:
我有一个生产 CPU 问题,经过几天的常规活动后,CPU 突然开始达到峰值。我已保存转储文件并运行 !runaway 命令以获取 CPU 耗时最高的线程列表。输出如下:
用户模式时间
线程时间
21:110 0 天 10:51:39.781
19:f84 0 天 10:41:59.671
5:cc4 0 天 0:53:25.343
48:74 0 天 0:34:20.140
47:1670 0 天 0:34:09.812
13:460 0 天 0:32:57.640
8:14d4 0 天 0:19:30.546
7:d90 0 天 0:03:15.000
23:1520 0 天 0:02:21.984
22:ca0 0 天 0:02:08.375
24:72c 0 天 0:02:01.640
29:10ac 0 天 0:01:58.671
27:1088 0 天 0:01:44.390
如您所见,输出显示我有 2 个线程:21 和 19,它们总共消耗了 20 多个小时的 CPU 时间,我能够像这样跟踪其中 1 个线程的调用堆栈:
~21s
!CLRStack此时的输出无关紧要,我们称它为“X callstack”
我想要的是关于 !runaway 命令输出的解释。据我了解,转储文件是应用程序当前状态的快照。所以我的问题是:
- 当转储过程只用了几秒钟时,runaway 命令如何显示线程 21 的 10:51 小时值?
- 这是否意味着我使用 !CLRStack 命令找到的 X 调用堆栈的特定“实例”已挂起超过 10 小时?或者这是 21 个线程执行他的整个 X 调用堆栈执行的总时间?如果是这样,那么负责执行这么多 X 调用堆栈的 21 个线程似乎很奇怪。据我所知,起源是一个网络请求(运行时应该为每个调用分配一个随机线程)
我有一个推测可以回答这两个问题:
也许windbg通过获取线程调用堆栈的实际时间并将其除以转储过程的范围来计算时间,因此,例如,如果X调用堆栈的具体执行耗时1秒,整个转储过程耗时3秒( 33%),当进程运行总共 24 小时时,输出将显示:
8 小时(24 小时的 33%)
我是对的,还是完全弄错了?
【问题讨论】:
-
!runaway命令仅显示线程自创建以来所花费的 CPU 时间量。在进行转储时,它可能与调用堆栈有任何关系,也可能没有任何关系。如果您想查看调用树中每个函数花费的时间,您需要use a profiler。 (顺便说一句,您可以通过!runaway 7收集更多关于 CPU 与墙时间的信息。) -
用户时间和内核时间是从内核模式结构成员 kthread 复制到转储的,当您转储时,它会在一定的时间间隔内更新,最后一次更新的时间被 windbg 复制并显示,windbg 只显示这些东西
标签: performance cpu windbg