go runtime/metrics: CPU metrics update at a relatively low rate

ig9co6j1  于 6个月前  发布在  Go
关注(0)|答案(8)|浏览(65)

目前,它们每隔GC周期更新一次。要使它们"连续"更新应该是很简单的,因为大多数(全部?)都是实时累积的。

nwwlzxa7

nwwlzxa71#

https://go.dev/cl/487215提到了这个问题:runtime/metrics: make CPU stats real-time

s4chpxco

s4chpxco2#

在重构之后,还需要哪些功能来实现按需CPU统计?

z9gpfhce

z9gpfhce3#

我遇到的主要问题是 user 时间的单调性问题。这是因为 user 时间是通过从计算出的 total 中减去其他所有内容来计算的。例如,如果在我们进行测量时有一个飞行中的标记辅助(但尚未完成),并且在一小段时间内(小于总标记辅助时间)再进行一次测量(用户时间似乎会突然上升,然后下降)。更具体地说:标记辅助需要 10μs。我们在测量时花费了 5μs。在那一个CPU上,那 5μs 的时间将归属于 user 时间。然后,5μs 后,当它完成时,我们再次进行测量。现在它归属于标记辅助,所以 user 时间可能会看起来倒退。
这个问题很复杂,但我们需要像 https://cs.opensource.google/go/go/+/master:src/runtime/mgclimit.go;l=208;drc=70fbc88288143c218fde9f905a38d55505adfb2b;bpv=1;bpt=1 这样更完整的东西。虽然不是不可能,但可能需要大量的工作。

dw1jzc5e

dw1jzc5e4#

感谢您的解释。在理想解决方案实施之前,正如您所说,这会变得很复杂。那么,在实现理想解决方案之前,我们可以采用一个中间解决方案,让我们大部分时候都能达到目标吗?

  • 如果我们能检测到标记辅助正在进行中,就不要更新。
  • 可选地,为了防止标记辅助(如果它们可以永远连续进行)导致统计数据饥饿(不确定它们是否可以),设置一个位,以便在锁定之前强制下一个标记辅助更新统计数据。

这样一来,指标就不会完全按需生成,但仍能保持单调性(这对指标很重要),并且比目前的状态更新要少一些陈旧。

kuhbmx9i

kuhbmx9i5#

要明确的是,标记辅助示例仅仅是一个示例(也许是一个糟糕的示例;我们实际上今天已经可以处理那个了...)。还有其他几个案例,比如GC工作人员积极运行。等待他们完成运行并不是特别有用,因为这相当于等待垃圾回收标记阶段结束。

az31mfrm

az31mfrm6#

等待他们运行结束并不是特别有用,因为这相当于等待垃圾回收标记阶段结束。我不建议这样做。我的建议是,如果这是情况的话,提供最后一个快照:

GCWorker1     ---==----------------------
GCWorker2     --------------====---------
MetricsPoller ---||---------||||----------

其中有一个条形图( | ),指标轮询器只会看到最后更新的值。当没有工作线程忙于更新时,按需指标将重新开始。

zfciruhq

zfciruhq7#

在实践中,我们真的非常努力地让专用的垃圾回收工人坚持他们的P和线程。我认为我们不太可能找到任何宁静。
同样,这不仅仅是垃圾回收工人的问题。我们需要确保没有任何未完成的事件,以便它能够正常工作。这基本上是一个STW(停顿时间优化)。

pexxcrt2

pexxcrt28#

我再次遇到了这个问题( (*) ),在尝试比较Go处理时间与内核处理时间时。基本上:

(/cpu/classes/total - /cpu/classes/idle - /cpu/classes/gc/pause) 
---------------------------------------------------------------
                              rusage.ru_utime

我知道度量包建议不要将内核和Go度量进行比较,但在这种情况下,我想观察两者之间的显著差异。回答问题:当Go认为它消耗了X秒/秒,而内核给它的(要少得多)是多少?虽然大多数时候这个比例只是略高于1,但我观察到了一些显著的异常值(例如15倍的比例)。我想排除这种可能性是由于等待GC周期完成后再更新度量所固有的延迟。
我不是说这绝对是必要的,可以通过其他方式获得类似的信息,但会变得混乱。这只是一种用途。
(*)至少,我认为我做到了。

相关问题