6

Go 支持GOGCTRACE环境变量,并在每次运行时打印收集统计信息。但是,当 GC 发生时它不会打印。例子:

gc6231(8): 0+1+0 ms, 10 -> 5 MB 89540 -> 5294 (520316701-520311407) 个对象, 9(80) 切换, 32(404) 偷窃, 288/168/37 产量

我如何将收集线与它发生的时间关联起来?

4

1 回答 1

7

迹线不显示绝对时间,而是显示相对于输出的时间。当线路发生时,GC 发生在0 + 1 + 0ms 前。

请参阅代码中相应的输出行以供参考。

如果您在标准输出上的每一行前加上时间戳,那么您将获得 GC 运行的时间(时间戳 - 以毫秒为单位的时间 = GC 运行的时间)。

例子:

GOGCTRACE=1 ./myprog 2>&1 | while read line; do echo $(date +%s) $line; done

如果您只是想在 GC 运行以几秒的精度发生时有一种感觉,那么这完全足够了。输出很可能不会落后太多,即使确实如此,您仍然有时间戳来获得正确的时间。

另一种解决方案是使用ReadGCStatsfrom runtime/debugwhich 为您提供GCStats结构,该结构又具有LastGCtype字段time.Time,保存上次 GC 运行的绝对时间。或者,您可以使用runtime.ReadMemStats,它会为您提供更多信息。

当然,您仍然需要知道垃圾收集何时发生。为此,您可以在您创建的对象上使用终结器,该对象仅用于进行垃圾收集并应用于runtime.SetFinalizer该对象。在终结器中,您将读取LastGC时间并打印它。

示例(正在播放):

type Garbage struct{ a int }

func notify(f *Garbage) {
    stats := &runtime.MemStats{}
    runtime.ReadMemStats(stats)

    fmt.Println("Last GC was:", stats.LastGC)

    go ProduceFinalizedGarbage()
}

func ProduceFinalizedGarbage() {
    x := &Garbage{}
    runtime.SetFinalizer(x, notify)
}

func main() {
    go ProduceFinalizedGarbage()

    for {
        runtime.GC()
        time.Sleep(30 * time.Second) // Give GC time to run
    }
}
于 2013-06-26T11:39:40.457 回答