我有一个生产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个线程的callstack,如下所示:
〜-21
!CLRStack此时输出无关紧要,我们将其称为“X callstack”
我想要的是关于!runaway命令输出的解释。根据我的理解,转储文件是应用程序当前状态的快照。所以我的问题是:
我猜测可以回答这两个问题:
也许windbg通过获取线程callstack实际时间并将其除以转储过程的范围来计算时间,因此,例如,如果X调用堆栈的特定执行需要1秒,整个转储过程需要3秒( 33%),当过程总共运行24小时时,输出将显示:
8小时(24小时的33%)
我是对的,还是完全弄错了?
答案 0 :(得分:2)
这个答案旨在让OP易于理解。它无意纠正所有位和字节。
[...]并将其除以倾销程序的范围[...]
这种理解可能是所有邪恶的根源:转储流程只会及时为您提供某个点的流程状态。转储进程的持续时间为0.0秒,因为在操作期间所有线程都被挂起。 (所以,你的过程的相对时间,没有任何变化,时间停滞不前;当然,挂钟时间会发生变化)
您正在考虑将流程转储为在较长时间内对其进行监控,但事实并非如此。转储进程只需要时间,因为它涉及磁盘活动等。
所以不,没有"范围"因此,你不能(它真的很难)衡量崩溃转储的性能问题。
失控命令如何显示线程21的[...]
的10:51小时值
如果你的计时器事件每秒都会触发,你的C#程序怎么知道程序运行了多长时间?答案是:它使用变量并增加值。
大致是Windows如何做到这一点。 Windows负责线程调度,每次重新调度线程时,它都会更新包含线程时间的变量。
编写崩溃转储时,很久以前OS已收集的信息已包含在崩溃转储中。
[...]当倾销过程只花了几秒钟?
由于崩溃转储是由WinDbg的一个线程占用的,因此该时间被计入该线程。您需要调试WinDbg并在WinDbg线程上执行!runaway
以查看花费的CPU时间。可能是一个很好的练习和.dbgdbg
(调试调试器)命令可能对你来说是新的;除此之外,这个特殊情况并没有多大帮助。
这是否意味着具体的"实例"我用!CLRStack命令找到的X callstack挂起超过10个小时?
没有。这意味着在您创建故障转储的时间点,执行了该特定方法。不是更多,而不是更少。
此信息与!runaway
无关,因为该主题可能在很长一段时间内完全不同,但刚刚结束。
或者它是21个线程执行整个X个callstacks执行的总时间?
没有。故障转储不包含此类详细的性能数据。你需要像JetBrains这样的性能分析器dotTrace来获取这些信息。探查器会经常查看callstack,然后聚合相同的调用堆栈并导出每个调用堆栈的CPU时间。