WinDbg失控命令输出解释

时间:2017-04-19 12:13:19

标签: performance cpu windbg

我有一个生产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命令输出的解释。根据我的理解,转储文件是应用程序当前状态的快照。所以我的问题是:

  1. 当转储过程只用了几秒钟时,失控命令如何显示线程21的10:51小时值?
  2. 这是否意味着我使用!CLRStack命令找到的X callstack的特定“实例”挂起超过10小时?或者它是21个线程执行整个X callstacks执行的总时间?如果是这样,那么21个线程负责执行X调用堆栈的很多事情似乎很奇怪。据我所知,起源是一个Web请求(运行时应为每个调用分配一个随机线程)
  3. 我猜测可以回答这两个问题:

    也许windbg通过获取线程callstack实际时间并将其除以转储过程的范围来计算时间,因此,例如,如果X调用堆栈的特定执行需要1秒,整个转储过程需要3秒( 33%),当过程总共运行24小时时,输出将显示:

    8小时(24小时的33%)

    我是对的,还是完全弄错了?

1 个答案:

答案 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时间。