Java Metaspace Full GC

时间:2018-11-01 13:00:18

标签: java garbage-collection g1gc

我在使用G1GC时遇到了一些问题。

filepath="weights.best.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
callbacks_list = [checkpoint]
# Fit the model
model.fit(X, Y, validation_split=0.33, epochs=150, batch_size=10, callbacks=callbacks_list, verbose=0)

这花费了很长时间,并且每20-30分钟,元空间就会触发一个完整的gc。 我是这样配置的:

2400.241: [GC concurrent-root-region-scan-start]
2400.241: [Full GC (Metadata GC Threshold) 2400.252: [GC concurrent-root-region-scan-end, 0.0101404 secs]
2400.252: [GC concurrent-mark-start]
 1151M->603M(4356M), 2.6980537 secs]
   [Eden: 0.0B(2558.0M)->0.0B(2613.0M) Survivors: 55.0M->0.0B Heap: 1151.7M(4356.0M)->603.6M(4356.0M)], [Metaspace: 259187K->92248K(1034240K)]
 [Times: user=3.92 sys=0.00, real=2.70 secs] 

但是每次达到256M时,都会触发一个完整的gc。当达到第一个高水位线时,是否应该使其下次变大直到最大尺寸? 此外,元空间上的完整gc会触发旧一代的完整gc吗?我在某处阅读过,但不确定。 这使p99的响应时间比我预期的要长。

1 个答案:

答案 0 :(得分:2)

根据Triggering of gc on Metaspace memory in java 8,需要完整的GC,以减少元空间的使用。

我的理解是,元空间本身不是 垃圾收集。相反,您在普通堆中有保存对元空间对象的特殊引用的对象。收集普通对象后,将释放相应的元空间对象。

  

当达到第一个高水位线时,是否应该使其下次变大直到最大尺寸?

显然不是。 HotSpot收集器的正常策略是这样的:

  1. 分配对象,直到达到当前的堆限制
  2. 运行收集器
  3. 查看回收了多少空间,并在需要的情况下增加(或减少)堆大小。

似乎这里使用了相同的策略。完整的GC导致需要回收足够的元空间,它决定不需要扩展元空间。

临时解决方案是尝试将-XX:MetaspaceSize-XX:MaxMetaspaceSize设置为相同的值,但这只会减少完整GC的频率。

一个真正的解决方案是弄清楚什么消耗了元空间,并对其进行修复。