英文:
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.Time
的LastGC
字段,保存了最后一次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
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论