论坛首页 Java企业应用论坛

JVM的GC-生命不能承受之重

浏览 56176 次
精华帖 (17) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (9)
作者 正文
   发表时间:2008-11-05  
我们有一个要求非常高性能的应用,其实也是部署在一台普通的PE2850上面。4CPU,内存8G,JVM的heap开了5G,其中新生代为1.5G。在高峰期每秒超过5000次调用,约3秒就需要minor GC一次,每次停顿约0.3秒。隔十分钟左右就要Full GC一次,需要停顿约10秒。有点受不了。这样相当于每隔3秒应用就要停顿0.3秒,每隔10分钟就要停顿10秒。也改成CMS试过,Full GC的停顿会减少,但minor GC照样。这样的效果,对于一些高性能的应用来算,GC可能真是无法承受之重,而如果用C++来开发,这个停顿的问题将会消除,不过当然开发成本会大很多。有个疑问,不知道GC算法何时可以做到完全不停顿,其实已经有4个CPU了,能否用一个CPU不断地在GC,另外三个CPU不断地在服务,一刻也不停顿。否则这样下去,这种高性能的应用可能只能转用C++来开发了。
   发表时间:2008-11-05  
个人浅见,感觉此应用不适合用java来做.既然CMS也用过还不行的话。。
再深入没研究过了。
1 请登录后投票
   发表时间:2008-11-05  
对于这种调用如此频繁的来说,我想如果能减少对象的创建,可能会有些效果
1 请登录后投票
   发表时间:2008-11-05   最后修改:2008-11-05
三点:

1、GC这么频繁也很有可能是代码质量问题。我们前段时间一个服务用Java写的,刚上线也是GC极其频繁,2分钟就Full GC一次,每次FullGC要2-3秒,后来进行了代码优化,把频繁申请释放的资源进行了缓存,负载立刻降低,2个多小时才Full GC一次,每次FullGC只要0.3秒。

2、你的Heap开得太大了,GC无可避免的要很慢,Heap建议最大就2GB,不要再大了。

3、如果你内存和CPU资源比较空闲,更好的办法是启动多个JVM进程做个垂直群集。这样每个JVM进程的负载会被分散,Heap也不用开的那么大了,GC也仅仅打断当前进程,而其他进程照样正常处理请求。所以说鸡蛋不必都放在一个篮子里面。
3 请登录后投票
   发表时间:2008-11-05  
俺补充下俺的观点
1、heap肯定大了,调小
2、肯定要采用cms
3、适当增大新生代的比例
4、设置XX:MaxTenuringThreshold,这个参数用来设置新生代对象撑过多少轮minor gc才进入年老代,默认是0,也就是说直接进入年老大,触发full gc的频率大大增加。
1 请登录后投票
   发表时间:2008-11-05  
robbin 写道
三点:

1、GC这么频繁也很有可能是代码质量问题。我们前段时间一个服务用Java写的,刚上线也是GC极其频繁,2分钟就Full GC一次,每次FullGC要2-3秒,后来进行了代码优化,把频繁申请释放的资源进行了缓存,负载立刻降低,2个多小时才Full GC一次,每次FullGC只要0.3秒。

2、你的Heap开得太大了,GC无可避免的要很慢,Heap建议最大就2GB,不要再大了。

3、如果你内存和CPU资源比较空闲,更好的办法是启动多个JVM进程做个垂直群集。这样每个JVM进程的负载会被分散,Heap也不用开的那么大了,GC也仅仅打断当前进程,而其他进程照样正常处理请求。所以说鸡蛋不必都放在一个篮子里面。


代码质量我们都经过了严格的审计过了,基本上没有太大问题,这个应用本身不是特别复杂,逻辑挺简单的,只是调用量和数据量都非常大,因此会产生非常多的对象,尤其是minor GC这一块,基本上是很难优化了。

Heap开大也是逼不得已,因为应用要作非常非常多的缓存,计算清楚后就是需要用到约3G左右,由于都是缓存,这一块肯定是被放进老一代的区里面的。

同一台机器部署多个JVM组成集群也是可以的,可能会降缓GC的影响,但是部署也会复杂一些。

只是最不爽的一个事情就是,为何GC一定要暂停整个应用程序?我宁愿GC可以耗多点CPU,他完整地占着我的一个CPU来做GC也可以,那另外3G个CPU还是可以处理的。我相信如果是用C++来改写这个程序,应该是完全不需要停的。
1 请登录后投票
   发表时间:2008-11-05  
helloboy9527 写道
robbin 写道
三点:

1、GC这么频繁也很有可能是代码质量问题。我们前段时间一个服务用Java写的,刚上线也是GC极其频繁,2分钟就Full GC一次,每次FullGC要2-3秒,后来进行了代码优化,把频繁申请释放的资源进行了缓存,负载立刻降低,2个多小时才Full GC一次,每次FullGC只要0.3秒。

2、你的Heap开得太大了,GC无可避免的要很慢,Heap建议最大就2GB,不要再大了。

3、如果你内存和CPU资源比较空闲,更好的办法是启动多个JVM进程做个垂直群集。这样每个JVM进程的负载会被分散,Heap也不用开的那么大了,GC也仅仅打断当前进程,而其他进程照样正常处理请求。所以说鸡蛋不必都放在一个篮子里面。


代码质量我们都经过了严格的审计过了,基本上没有太大问题,这个应用本身不是特别复杂,逻辑挺简单的,只是调用量和数据量都非常大,因此会产生非常多的对象,尤其是minor GC这一块,基本上是很难优化了。

Heap开大也是逼不得已,因为应用要作非常非常多的缓存,计算清楚后就是需要用到约3G左右,由于都是缓存,这一块肯定是被放进老一代的区里面的。

同一台机器部署多个JVM组成集群也是可以的,可能会降缓GC的影响,但是部署也会复杂一些。

只是最不爽的一个事情就是,为何GC一定要暂停整个应用程序?我宁愿GC可以耗多点CPU,他完整地占着我的一个CPU来做GC也可以,那另外3G个CPU还是可以处理的。我相信如果是用C++来改写这个程序,应该是完全不需要停的。

 

 是否可以考虑用对象池呢?如果同一类型的对象大量生成,而且还会被回收回去,对象池也许能很大的提高性能。。

1 请登录后投票
   发表时间:2008-11-05  
full gc 肯定要stop-the-whole-world的,它要遍历整个对象网络这是所有有垃圾收集器的语言无法避免的问题。据说ibm的jvm的并行垃圾收集算法会有更好的表现。
1 请登录后投票
   发表时间:2008-11-05  
据我的观察好像minor GC也是stop-the-whole-world啊,是否我的理解错了?
0 请登录后投票
   发表时间:2008-11-05  
helloboy9527 写道
据我的观察好像minor GC也是stop-the-whole-world啊,是否我的理解错了?

你没理解错,都需要暂停,采用CMS的好处就是收集年轻代暂停应用程序时会启动多个线程并发收集,而对于年老代是暂停时间缩短,收集跟应用程序并发进行。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics