如何驯服java GC导致暂停? 使用16GiB以上heap

How to tame java GC pauses? Surviving 16GiB heap and greater. | Javalobby

大意如下:
内存(条)是便宜,很不幸,垃圾回收机制导致的暂停会严重影响系统性能,好像JVM内存最多支持2G,作者花费大量时间精力使用32G来提高系统性能,这篇是其心得。

GC微调是非常和应用有关,该篇的目标要求是:使用10G更大Heaps和严格的响应时间(毫秒级别),(吞吐量和延迟性是一对矛盾,这次GC微调主要是追求低延迟)。作者项目特点是:

1.Heap用于在内存中储存数据结构
2.Heap大小超过10G
3.请求时间要求更快
4.事务是短的(几百毫秒) 一个事务可以包括几个请求
5.内存中数据修改频率和面积低,不会一秒内修改整个10G内存,每秒更新10M即可。

此处省略垃圾回收机制原理介绍.....

总体来说,banq注:JVM分新生代和旧生代,新创建在新生代,通过新生代垃圾回收,如果不能被回收,将逐步转入旧生代,旧生代内存可以实现缓存In-memeory数据,显然新旧两代的垃圾回收算法最好不一样,新生代需要频繁,而旧生代不需要频繁,如果我们内存缓存控制得好,旧生代就不会启动垃圾回收机制,这样就不会导致系统暂停。

该文介绍如何来进行新生代大小调节,防止垃圾回收机制频繁启动,先使用XX:MaxNewSize=<n> -XX:NewSize=<n> 指定新生代大小,使用-XX:+PrintGCDetails -XX:+PrintTenuringDistribution -XX:+PrintGCTimestamps)输出GC诊断结果。

有几个数据需要计算一下:
新生代收集期间值,整个分配情况,短生命对象的分配大小,长生命对象的分配情况,中等生命对象分配。

我个人更喜欢使用psi-Probe安装在tomcat下,一目了然,如附件图:

原文还提到CMS(Concurrent Mark Sweep)激活会导致暂停等等。

针对不同应用特点进行算法配置,在线事务处理将耗费响应时间,而批处理将产生大量垃圾,这些都要用不同JVM来处理。

配置恰当的缓存Cache策略来解决GC问题也相当重要,我们提倡基于内存的领域对象编程,大量数据都在缓存中in-memory,如何保证他们的生命周期和JVM的垃圾回收机制不冲突,也是一种实际问题,文章提出下面几点:
1.为缓存增加失效期,让新生代的GC期间要长于缓存的失效期,也就是缓存中对象数据失效后,正好GC启动后可以回收这些失效对象。

2.增加延长新生代的GC期间。

3.在缓存中使用弱引用。缓存产品自己的事,和我们应用者无关。

4.增加缓存大小,我个人经验尽可能将数据库数据以领域对象方式都加载到内存中。

JVM首先分配所有对在新生代,然后将幸存对象(一般是缓存中对象)再分配到旧生代,或再分配到新生代,这些对象的拷贝将耗费时间导致新生代收集暂停,两种选择:
1.在第一次收集时,就将对象复制到旧生代
2.第二次收集时,将对象复制到旧生代。

第一种办法将导致一些短生命周期对象复制到旧生代,第二种办法需要注意新生代垃圾收集的频度和长生命周期对象是否小。

对于一个巨大的heap,新生代垃圾收集暂停主要是在空间扫描和复制幸存对象上,在新生代大小上需要取得一个平衡,旧生代大小足够放入应用的数据,比如jivejdon一天下来缓存的大小是200K左右(每天启动的情况下),只要旧生代大小大于这个值即可,不能太大,也不能太小。

增加新生代大小要增加整个JVM大小,否则就会降低旧生代的内存大小。

可以配置CMS短期暂停:–XX:CMSWaitDuration –设置收集暂停的最大间隔时间,越大你的应用将被暂停,类似死机没有反应。XX:+CMSScavengeBeforeRemark 可以避免在收集期间同时扫描。

[该贴被banq于2011-06-29 09:59修改过]


相关文章:

JVM高级性能调试

曾经有一个知名企业DBA出身的面试官面试Java应用程序员,要求他们能够贡献出JVM微调的技巧,结果未如愿以偿,在微博中抱怨:专业有分工,学无边界啊。

通过以上JVM微调这些文章可以看出,JVM微调本身是很讲究的,很专业的,不是普通Java应用程序员随便去微调的,就是他学无边界,也不如专业负责Java架构的架构师去实现要稳妥,因为首先JVM微调有一个架构目标,你是要高吞吐量还是低延迟性?两个都要如何平衡?你的应用中有多少使用JTA事务?有多少使用批处理,是否使用基于内存缓存的机制?等等,这些都不是普通Java应用程序员能够掌握,也不是他们应该掌握的,他们只要根据OO面向对象原则编好自己的程序,然后将这些对象交由JVM去管理即可,至于JVM如何管理这些对象最优,是架构师职责。

写这么多技术之外废话,无非是希望从事软件行业的所谓高手或低手都变得专业一些,知识渊博是好事,能否擅长做到又是一回事,切忌三脚猫,当然,小公司喜欢三脚猫除外。

2011年06月29日 10:10 "@banq"的内容
小公司喜欢三脚猫除外 ...

没有人喜欢三脚猫,他们也可能是退而求其次吧.

banq 老师,我想详细的了解下有关java缓存、jvm细节的这些东西,有什么好的资料或者图书吗

2011年06月29日 15:22 "@snmp001"的内容
有关java缓存、jvm细节的这些东西 ...

这么主要又容易忽视的问题怎么会有中文书籍,不过外文应该有,还是看看本站,我在Jdon喊了这么多年的缓存:
本站缓存专题

相关主题:
使用设计模式后的副作用


InfoQ最新一篇文章,Twitter迁移到JVM,主要是因为性能和封装,具体提高性能的办法就是使用缓存和JVM微调。

可见Cache+JVM微调是Java核心竞争力,也是最容易被大家忽视的。

因为很多使用Java只是当作SQL语句的包装器来使用,负载主要集中在数据库上,而没有使用In-memory Cache(JavaEE 7新标准核心)。包括Spring最近才加入Spring支持,这一步已经晚了落后了,JdonFramework一开始就集成了Cache。
[该贴被banq于2011-07-06 08:45修改过]

在In-Memery Cache一文中,banq提到:
"Java内存模型优点:基于内存的并发模型,多线程机制,大量线程安全型库包支持基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁。"
这句话如何理解?

2011年07月13日 14:50 "@jonathanks"的内容
这句话如何理解 ...

提倡尽量使用内存锁替代数据库锁机制,当然多线程自身特点改变不了其锁争夺的本质问题,追求更高性能寄希望于Scala等这些Actor模型语言。

2011年07月13日 16:22 "@banq"的内容
追求更高性能寄希望于Scala等这些Actor模型语言 ...

感觉从一个问题引向了另一个问题了。
在Java技术领域内的内存锁和基于缓存的数据库锁,在灵活度上该如何比较?如何才能深入理解?

2011年07月13日 16:26 "@jonathanks"的内容
在Java技术领域内的内存锁和基于缓存的数据库锁,在灵活度上该如何比较 ...

内存锁实际是Java语言自身的锁机制,锁的粒度和对象粒度相同,这样你可以根据DDD等基于业务设计不同的对象,比如订单中价格如果经常变化,可以把价格单独作为一个对象,这样不至于因为修改价格将整个订单锁住,关键是对象的边界划分很灵活方便,而数据表结构改变涉及面广。

2011年07月13日 16:41 "@banq"的内容
比如订单中价格如果经常变化,可以把价格单独作为一个对象 ...

那么在数据库端的话就是一个关联表的形式咯。
这样以来,基于业务设计的对象,在数据库层面会在某种程度上去冗余化,关联表增加,那么对于互联网应用来说,这种表的增加可能会带来数据库的压力。可以这样理解吗?

2011年07月13日 17:47 "@jonathanks"的内容
那么对于互联网应用来说,这种表的增加可能会带来数据库的压力。可以这样理解吗? ...

表的增加带来数据库压力,只是一个量变,不是关键原因,关键原因造成数据库压力的是:系统中所有请求访问直接导向到数据库端。

而基于内存的领域对象方式则将所有请求在Java等语言服务器内解决了,内存不够,增加内存,轻松使用16G或32G甚至更多,这种性能扩展性相比数据库的切分等要轻松 简单 方便,这就体现了良好的可伸缩性Scalable。

2011年06月29日 15:25 "@banq"的内容
1顶一下banq 老师,我想详细的了解下有关java缓存、jvm细节的这些东西,有什么好的资料或者图书吗 ...
sun出过一本关于虚拟机的(大概是深入JVM,具体不清楚了),很不错,不过现在当当好像已经缺货了。不过可以去淘宝看看。

Should server applications limit themselves to 4 GB? | Javalobby

服务器应用应该限制在4GB吗?在如今移动手机都配2到4G的内存情况下,你还给你的服务器内存配置4G吗?典型的服务器应用应该是100G。

最简单办法:有一个巨大deJVM年轻态Eden的容量,这只会提高临时垃圾回收机制,而不会延长服务器中断时间。

Twitter的 JVM性能微调:Everything I Ever Learned About JVM Performance Tuning :
http://www.slideshare.net/aszegedi/everything-i-ever-learned-about-jvm-performance-tuning-twitter

[该贴被banq于2011-10-31 16:14修改过]

高!
[该贴被hsia2009于2011-09-29 14:52修改过]

C++将源代码编译了一遍,机器执行效率自然高;java也编译的一半(半编译,半解释),不过和C++这么小差距倒是没有想到;C刷信誉java的;剩下一大片都是解释性语言,边解释边执行,自然耗资源。
不过,编译本身也耗资源,只是执行时无需再编译,而表面上看就非常完美