GOGCTRACE和垃圾回收时间

huangapple go评论81阅读模式
英文:

GOGCTRACE and collection time

问题

Go支持GOGCTRACE环境变量,并在每次运行时打印收集统计信息。然而,它不会打印GC发生的时间。例如:

>gc6231(8): 0+1+0 ms, 10 -> 5 MB 89540 -> 5294 (520316701-520311407) objects, 9(80) handoff, 32(404) steal, 288/168/37 yields

我如何将收集行与其发生的时间相关联?

英文:

Go supports a GOGCTRACE environment variable, and prints collection statistics on each run. However it doesn't print when the GC occurred. Example:

>gc6231(8): 0+1+0 ms, 10 -> 5 MB 89540 -> 5294 (520316701-520311407) objects, 9(80) handoff, 32(404) steal, 288/168/37 yields

How do I correlate a collection line, with the time it occurred?

答案1

得分: 7

跟踪不显示绝对时间,而是相对于输出的时间。
当出现该行时,GC发生在0 + 1 + 0毫秒前。

请参考代码中的相应输出行

如果你在stdout上的每一行前面加上一个时间戳,你就可以得到GC运行的时间
(时间戳 - 毫秒时间 = GC运行的时间)。

示例:

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

如果你只想知道GC运行发生的时间,精确到秒,那么这是完全足够的。输出很可能不会滞后太多,
即使滞后,你仍然可以通过时间戳获取正确的时间。

另一种解决方案是使用runtime/debug中的ReadGCStats
它会给你一个GCStats结构体,其中有一个
类型为time.TimeLastGC字段,保存了最后一次GC运行的绝对时间。
或者你可以使用runtime.ReadMemStats
它提供了更多的信息。

当然,你仍然需要知道何时发生了垃圾回收。为此,你可以在一个对象上使用finalizer,
你只需为此目的创建一个对象,并在其上应用runtime.SetFinalizer
在finalizer中,你可以读取LastGC时间并打印它。

示例(在play上):

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) // 给GC运行的时间
	}
}
英文:

The trace does not show an absolute time but one relative to the output.
When the line occurs the GC happened 0 + 1 + 0 ms ago.

See the corresponding output line in the code for reference.

If you prefix each line on stdout with a timestamp you then get the time of the GC run
(timestamp - time in milliseconds = time the GC ran).

Example:

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

If you just want to have a feeling when a GC run happened with accuracy of seconds
then this is totally sufficient. The output will most likely not lag behind much and
even if it does, you'd still have the timestamps to get the correct time.

Another solution would be to use ReadGCStats from runtime/debug which gives you
the GCStats struct, which in turn has a
field LastGC of type time.Time, holding the absolute time of the last GC run.
Alternatively you can use runtime.ReadMemStats, which gives you even more information.

Of course you would still need to know when a garbage collection happened. For this you could
use a finalizer on a object which you create solely for the purpose of being garbage
collected and apply runtime.SetFinalizer on it.
In the finalizer you would then read the LastGC time and print it.

Example (on play):

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
	}
}

huangapple
  • 本文由 发表于 2013年6月26日 11:10:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/17310899.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定