Java 垃圾回收调优

鉴客 发布于 2010/06/09 13:23
阅读 228
收藏 2

在Java中,通常通讯类型的服务器对GC(Garbage Collection)比较敏感。通常通讯服务器每秒需要处理大量进出的数据包,需要解析,分解成不同的业务逻辑对象并做相关的业务处理,这样会导致大量的临时对象被创建和回收。同时服务器如果需要同时保存用户状态的话,又会产生很多永久的对象,比如用户session。业务越复杂的应用往往用户 session包含的引用对象就越多。这样在极端情况下会发生两件事情,long gc pause time 或 out of memory。

一,要解决long pause time首先要了解JVM中heap的结构 java gc heap Java Heap为什么要分成几个不同的代(generation)? 由于80%-98%的对象的生存周期很短,大部分新对象存放在young generation可以很高效的回收,避免遍历所有对象。 young与old中内存分配的算法完全不同。young generation中由于存活的很少,要mark, sweep 然后再 compact 剩余的对象比较耗时,干脆把 live object copy 到另外一个空间更高效。old generation完全相反,里面的 live object 变化较少。因此采用 mark-sweep-compact更合适。

二,Java中四种垃圾回收算法 Java中有四种不同的回收算法,对应的启动参数为 –XX:+UseSerialGC –XX:+UseParallelGC –XX:+UseParallelOldGC –XX:+UseConcMarkSweepGC

1. Serial Collector

大部分平台或者强制 java -client 默认会使用这种。 young generation算法 = serial old generation算法 = serial (mark-sweep-compact) 这种方法的缺点很明显,stop-the-world, 速度慢。服务器应用不推荐使用。

2. Parallel Collector

在linux x64上默认是这种,其他平台要加 java -server 参数才会默认选用这种。 young = parallel,多个thread同时copy old = mark-sweep-compact = 1

优点:新生代回收更快。因为系统大部分时间做的gc都是新生代的,这样提高了throughput(cpu用于非gc时间)

缺点:当运行在8G/16G server上old generation live object太多时候pause time过长

3. Parallel Compact Collector (ParallelOld) young = parallel = 2 old = parallel,分成多个独立的单元,如果单元中live object少则回收,多则跳过优点:old old generation上性能较 parallel 方式有提高缺点:大部分server系统old generation内存占用会达到60%-80%, 没有那么多理想的单元live object很少方便迅速回收,同时compact方面开销比起parallel并没明显减少。

4. Concurent Mark-Sweep(CMS) Collector young generation = parallel collector = 2 old = cms 同时不做 compact 操作。

优点:pause time会降低, pause敏感但CPU有空闲的场景需要建议使用策略4.

缺点:cpu占用过多,cpu密集型服务器不适合。另外碎片太多,每个object的存储都要通过链表连续跳n个地方,空间浪费问题也会增大。

几条经验:

1. java -server

2. 设置Xms=Xmx=3/4物理内存

3. 如果是CPU密集型服务器,使用–XX:+UseParallelOldGC, 否则–XX:+UseConcMarkSweepGC

4. 新生代,Parallel/ParallelOld可设大于Xmx1/4,CMS可设小,小于Xmx1/4

5. 优化程序,特别是每个用户的session中的集合类等。我们的一个模块中session中曾经为每个用户使用了一个 ConcurrentHashMap, 里面通常只有几条记录,后来改成数组之后,每台机大概节约了1~2G内存。

不过总的说来,Java的GC算法感觉是业界最成熟的,目前很多其他语言或者框架也都支持GC了,但大多数都是只达到Java Serial gc这种层面,甚至分generation都未考虑。JDK7里面针对CMS又进行了一种改进,会采用一种G1(Garbage-First Garbage Collection)的算法。实际上Garbage-First paper(PDF) 2004年已经出来了,相信到JDK7已经可以用于严格生产环境,有时间也会进一步介绍一下G1。另外在今年的Sun Tech Days上Joey Shen讲的Improving Java Performance(PDF)也是一个很好的Java GC调优的入门教程。

加载中
0
张林
张林

1.6up16似乎就支持G1了,我自己用了用(在Netbeans里)感觉没什么太大变化,可能由于应用少的缘故

返回顶部
顶部