前言

原问题:https://github.com/apache/rocketmq/issues/1718
rocketMQ的GC选择。

翻译

RocketMQ的NameSrv使用的GC是CMS收集器(运行老年代的GC收集器),RocketMQ的Broker使用的是G1收集器,需要进行切换:

  1. CMS收集器在Java 9.0版本中被废弃移除了。

理解:Java 9 默认的GC收集器是G1,CMS被标记了废弃。原因可能是CMS容易操作STW操作,GC的时候服务运行时间长,造成了严重的内存碎片化操作。

  1. 由于Namesrv使用SMC收集器,不能运行在JDK 11 上面,并且一些CMS的选项被移除了。以后还是主要使用G1
  2. G1收集器能够同时运行在young和old 区域。

不可否认,G1收集器在small heaps的情况下表现不佳。但是,Namesrv使用的堆内存大小是4G,可能不小。此外,当由于空间不足(没有可用的连续区域)而无法分配大量对象(超过区域大小50%的对象)时,将会触发Full GC。

不过,以4G堆内存的Namesrv为例,G1仍然可以很好地运行。根据最佳优化实践(堆内存被划分为大约2000个区域),我们可以设置一个区域2M,使用jmap工具在测试环境(2M-2s-async brokers,2 Namesrv)中获取Namesrv的堆转储文件,使用visualvm工具对文件进行分析,最大的10个对象如下:

image.png

总结,从CMS切换到G1收集器并没有性能损耗。

注:Retained Heap是指对象本身大小(Shallow Heap大小)和其所引用的对象大小之和。
换个说法就是当前对象被GC后,从Heap上总共能释放掉的内存,强调是GC后能释放的。即要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage