设置GODEBUG=gctrace=1
会导致Go垃圾回收器发出一行关于标准错误的单行,有关每个GC循环的内部信息。假设我有以下输出:
gc 1 @0.021s 0%: 0.15+0.37+0.25 ms clock, 3.0+0.19/0.39/0.60+5.0 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 2 @0.024s 0%: 0.097+0.94+0.16 ms clock, 0.29+0.21/1.3/0+0.49 ms cpu, 4->4->1 MB, 5 MB goal, 48 P
gc 3 @0.027s 1%: 0.10+0.43+0.17 ms clock, 0.60+0.48/1.5/0+1.0 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 4 @0.028s 1%: 0.18+0.41+0.28 ms clock, 0.18+0.69/2.0/0+0.28 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 5 @0.031s 1%: 0.078+0.35+0.29 ms clock, 1.1+0.26/2.0/0+4.4 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 6 @0.032s 1%: 0.11+0.50+0.32 ms clock, 0.22+0.99/2.3/0+0.64 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 7 @0.034s 1%: 0.18+0.39+0.27 ms clock, 0.18+0.56/2.2/0+0.27 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 8 @0.035s 2%: 0.12+0.40+0.27 ms clock, 0.12+0.63/2.2/0+0.27 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 9 @0.036s 2%: 0.13+0.41+0.26 ms clock, 0.13+0.52/2.2/0+0.26 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 10 @0.038s 2%: 0.099+0.51+0.20 ms clock, 0.19+0.56/1.9/0+0.40 ms cpu, 4->5->0 MB, 5 MB goal, 48 P
gc 11 @0.039s 2%: 0.10+0.46+0.20 ms clock, 0.10+0.23/1.3/0.005+0.20 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 12 @0.040s 2%: 0.066+0.46+0.24 ms clock, 0.93+0.40/1.7/0+3.4 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 13 @0.041s 2%: 0.099+0.30+0.20 ms clock, 0.099+0.60/1.7/0+0.20 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 14 @0.042s 2%: 0.095+0.45+0.24 ms clock, 0.38+0.58/2.0/0+0.98 ms cpu, 4->5->0 MB, 5 MB goal, 48 P
gc 15 @0.044s 2%: 0.095+0.45+0.21 ms clock, 1.0+0.78/1.9/0+2.3 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
gc 16 @0.045s 3%: 0.10+0.45+0.23 ms clock, 0.10+0.70/2.1/0+0.23 ms cpu, 4->5->0 MB, 5 MB goal, 48 P
gc 17 @0.046s 3%: 0.088+0.40+0.17 ms clock, 0.088+0.45/1.9/0+0.17 ms cpu, 4->4->0 MB, 5 MB goal, 48 P
.
.
.
.
gc 6789 @9.998s 12%: 0.17+0.91+0.24 ms clock, 0.85+1.8/5.0/0+1.2 ms cpu, 4->6->1 MB, 6 MB goal, 48 P
gc 6790 @10.000s 12%: 0.086+0.55+0.24 ms clock, 0.78+0.30/4.2/0.043+2.2 ms cpu, 4->5->1 MB, 6 MB goal, 48 P
documention中有这些值的定义:
gc # @#s #%: #+#+# ms clock#+#/#/#+# ms cpu, #->#-># MB, # MB goal, #P
where the fields are as follows:
gc # the GC number, incremented at each GC
@#s time in seconds since program start
#% percentage of time spent in GC since program start
#+...+# wall-clock/CPU times for the phases of the GC
#->#-># MB heap size at GC start, at GC end, and live heap
# MB goal goal heap size
# P number of processors used
我真正感到困惑的是#->#-># MB heap size at GC start, at GC end, and live heap
。
是正确的吗,GC在每个回合中都会向OS释放一些未使用的(垃圾)内存,这必须减小堆大小吗?如果是,那为什么堆的某些值会增加?例如:4-> 5-> 0。 在GC启动之前,我们有4MB的内存(包括垃圾)。那么,从中清除垃圾后如何获得5MB的内存呢?
第三个值是活动堆大小。常规堆大小之间有什么区别?我想这是没有垃圾的堆。
目标堆大小是如何计算的?正确,这是GC希望在清理后达到的堆大小吗?那么为什么这个值大于GC启动之前的堆大小?
答案 0 :(得分:1)
每次通过GC都会清除一定数量的垃圾。它不一定将它发布到OS(如果认为它只需要在短时间内再次请求它)。如果确实如此,则操作系统不一定会回收它(直到另一个进程的内存不足,操作系统可能会将该内存分配给您的进程,以防再次需要)。
活动堆大小是活动堆的使用量,减去任何无效对象和可用堆空间以备将来分配。目标堆大小是GC认为需要从操作系统获取多少内存来持续处理您的进程的分配,而不必不断从OS请求更多的内存(即,有多少个活动内存+在GC之间分配和丢弃了多少内存)运行)。
GC的目标是清理堆中的死对象,和保持足够的可用堆空间来处理大多数分配,而不必从操作系统请求更多内存(这很慢),同时也不保留过多的可用内存(以便操作系统仍可以分配给其他进程)。