1 回答
TA贡献1845条经验 获得超8个赞
我想捕捉调试这个过程作为答案。
REStop / htop只是在进程级别告诉您内存的情况。GODEBUG="gctrace=1" 让您更深入地了解内存的处理方式。
使用 gctrace set 的简单运行给出以下结果
root@localhost ~ # yes "12345678901234567890123456789012" | GODEBUG="gctrace=1" go run badcase.go
starting...
allocating
initializing mystruct arr1...
initializing mystruct arr2...
gc 1 @0.050s 0%: 0.19+0.23+0.068 ms clock, 0.58+0.016/0.16/0.25+0.20 ms cpu, 7629->7629->7629 MB, 7630 MB goal, 8 P
done initializing ...
gc 2 @0.100s 0%: 0.070+2515+0.23 ms clock, 0.49+0.025/0.096/0.24+1.6finished allocating..1000000000 1000000000
ms cpu, 15258->15258reading from stdin...
->15258 MB, 15259read 0 lines...
MB goal, 8 P
gc 3 @2.620s 0%: 0.009+0.32+0.23 ms clock, 0.072+0/0.20/0.11+1.8 ms cpu, 15259->15259->15258 MB, 30517 MB goal, 8 P
read 1000000 lines...
read 2000000 lines...
read 3000000 lines...
read 4000000 lines...
....
read 51000000 lines...
read 52000000 lines...
read 53000000 lines...
read 54000000 lines...
这是什么意思 ?
如您所见,gc 已经有一段时间没有被调用了。这意味着所有从 reader.ReadString 生成的垃圾还没有被收集和释放。
为什么垃圾收集器不收集这些垃圾?
来自go gc
相反,我们提供了一个称为 GOGC 的旋钮。该值控制相对于可达对象大小的堆的总大小。默认值 100 意味着总堆大小现在比上次收集后可达对象的大小大 100%(即两倍)。
由于未设置 GOGC - 默认值为 100%。因此,只有在达到 ~32GB 时它才会收集垃圾。(因为最初这两个数组为您提供 16GB 的堆空间 - 只有当堆加倍时才会触发 gc )。
我怎样才能改变这个?尝试设置 GOGC=25。
GOGC 为 25
root@localhost ~ # yes "12345678901234567890123456789012" | GODEBUG="gctrace=1" GOGC=25 go run badcase.go
starting...
allocating
initializing mystruct arr1...
initializing mystruct arr2...
gc 1 @0.051s 0%: 0.14+0.30+0.11 ms clock, 0.42+0.016/0.31/0.094+0.35 ms cpu, 7629->7629->7629 MB, 7630 MB goal, 8 P
done initializing ...
finished allocating..1000000000 1000000000
gc 2 @0.102s reading from stdin...
12%: 0.058+2480+0.26 ms clock, 0.40+0.022/2480/0.10+1.8 ms cpu, 15258->15258->15258 MB, 15259 MB goal, 8 P
read 0 lines...
gc 3 @2.584s 12%: 0.009+0.20+0.22 ms clock, 0.075+0/0.24/0.046+1.8 ms cpu, 15259->15259->15258 MB, 19073 MB goal, 8 P
read 1000000 lines...
read 2000000 lines...
read 3000000 lines...
read 4000000 lines...
....
read 19000000 lines...
read 20000000 lines...
gc 4 @6.539s 4%: 0.019+2.3+0.23 ms clock, 0.15+0/2.1/12+1.8 ms cpu, 17166->17166->15258 MB, 19073 MB goal, 8 P
如您所见,触发了另一个 gc。
但是 top/htop 显示它稳定在 ~20 GB 而不是计算的 16 GB。
垃圾收集器不必“必须”将其返回给操作系统。它有时会保留它以供将来有效使用。它不必不断从操作系统中获取并回馈 - 在再次询问操作系统之前,额外的 4 GB 位于可用空间池中以供使用。
- 1 回答
- 0 关注
- 136 浏览
添加回答
举报