论坛首页 Java企业应用论坛

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

浏览 56177 次
精华帖 (17) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (9)
作者 正文
   发表时间:2008-11-06  
helloboy9527 写道
sdh5724 写道
  我觉得他这个是设计问题, 为什么要cache 3g的数据, 这个本身就值得思考。 另外, 尽管GC参数能调整一些问题, 但是, 都无法解决这么庞大的FULL GC问题。
  我一直都不赞成使用JAVA作大规模的数据CACHE, 这个会导致严重的GC问题, 以前我们的系统就是把好几百M的文件读到系统里, 这个很容易造成系统的不稳定, 有时候会造成严重的JVM CRASH, 可能新版本的JVM会好点。
  我建议你把系统的CACHE的数据MODEL说出来, 大家给你参考下, 光是靠JVM的调整, 我直接可以告诉你, JVM是作不到完美的。 我们作多很多测试, 在以后大量对象的规模下,  FULL GC无法达到一个令人满意的停顿平滑。

你可以加我MSN SDH5724@163。COM  我帮你看看, 我也在调整我们应用的GC参数。 今天计算了下, GC 用了5%的CPU时间, 有点恐怖的。


对于很多高性能的互联网系统来说,别说3G,300G的cache都是很有可能的。大量cache,大量对象已经是不可避免的了,在这个前提下再看看怎样调GC,或者现在的JVM根本无法满足此种应用的需要?现在我正在苦恼着这个事情。如果实在不能满足,以后此类应用就只能交由C/C++开发了,因为觉得这样还不应该到服务器的瓶颈所在。对于几百M的文件读进系统,基本上是不太可能造成系统不稳定的,那简直和吃生菜差不多。



哥们, 俺就是作互联网应用的。 流量也算可以吧,有些事情, 等你做过了, 就会有想法的。 虽然, 我承认, 基本JAVA能做所有的互联网应用, 但是, 在服务端高内存设计就是一个愚蠢的办法, 曾经, 我们公司以前的设计就是这样, 每次装载好几百M的数据到内存里, 造成了很多的问题, 这些东西如果没有亲自去实验过, 光靠想象,很难明白。   JAVA的问题在于, 不是用多少内存, 而是, 系统中有对多少对象的问题。 如果你有1000万的 Integer的对象, 一样会造成严重的内存收集停顿。  但是, 为什么JAVA能做一些比较性能高的数据库呢, 而且也能开上很大的内存, 这个问题, 是因为, 数据库的设计上, JAVA使用了内存PAGE的概念, 并不会一次载入无数的对象做CACHE, 而是, 把内存按一页一页分配, 大规模的减少的对象数量。有兴趣的可以去读读java如何实现索引等等代码, 保证你拍案叫绝。
2 请登录后投票
   发表时间:2008-11-06  
Trustno1 写道
Quake Wang 写道
helloboy9527 写道
对于很多高性能的互联网系统来说,别说3G,300G的cache都是很有可能的。大量cache,大量对象已经是不可避免的了,在这个前提下再看看怎样调GC,或者现在的JVM根本无法满足此种应用的需要?现在我正在苦恼着这个事情。如果实在不能满足,以后此类应用就只能交由C/C++开发了,因为觉得这样还不应该到服务器的瓶颈所在。对于几百M的文件读进系统,基本上是不太可能造成系统不稳定的,那简直和吃生菜差不多。

大部分的互联网应用cache并不是放在JVM中的,而是利用第3方cache server,比如memcached。
你可以试试看将程序中的cache机制改写到第3方的cache server试试看。

我觉得把数据Cache到内存里,唯一的用处就是利用数组来实现内存的随机高速访问.这点对运算密集型的应用来说至关重要,如果是这样的情况memcache这样通过Hash表实现的cache不光是线性查找还有网络传输的消耗,当然可以考虑在程序里再做二级cache.但是一来复杂度高二来取决于cache传输和运算两边的速度,如果运算远快于传输那么我估计二级cache也不会小到哪里去.

嗯,得看他遇到的是什么情景,但是运算密集型的应用也有一些办法运用外部cache来提高性能和避免GC,他在主题贴中没有描述清楚。
现在经济不景气,不提供免费建议了:
Ruby+Java性能调优咨询,收费标准:6000火星币/天,报朋友的名字...也是不打折的
0 请登录后投票
   发表时间:2008-11-06  
liuruncheng 写道
Java有RTS(Real Time System)规范,要做实时系统还是用这个做比较靠谱
我们的认证系统是纯C开发的,8台16CPU、32G内存的机器分两组集群,每台缓存超过10G内存,虽然不会有任何停顿,
但是内存泄漏同样是个梦魇,每年都在查内存泄漏,几乎成了无法避免的任务了



    这么庞大的内存使用, 如果不把数据实现自己的内存分配管理, 一样因为目前操作系统的内存分配的机制造成严重的内存后果。 实际上, 你把这个话题说出来, 就很有趣味了。
   对于操作系统来说, 应用需要内存, 就会找一个位置, 分配合适的内存大小。 很大的一个问题就会造成, 如果2块内存之间的未使用的碎片很小, 就再也无法被是使用了。 这个对于计算,内存分配密集型的应用也同样造成严重的内存泄漏的假象。 比如, 一个C/C++写的搜索引擎, 就会遇见这样的内存泄漏的假象。
   所以, 对于大规模使用内存, 自己不管理内存的应用, 都会在成内存问题, 只不过表现的方式不一样。

   如果把firefox一直运行,不要关闭他, 估计没有几天就挂了。。。。
0 请登录后投票
   发表时间:2008-11-06   最后修改:2008-11-06
Trustno1 写道
Quake Wang 写道
helloboy9527 写道
对于很多高性能的互联网系统来说,别说3G,300G的cache都是很有可能的。大量cache,大量对象已经是不可避免的了,在这个前提下再看看怎样调GC,或者现在的JVM根本无法满足此种应用的需要?现在我正在苦恼着这个事情。如果实在不能满足,以后此类应用就只能交由C/C++开发了,因为觉得这样还不应该到服务器的瓶颈所在。对于几百M的文件读进系统,基本上是不太可能造成系统不稳定的,那简直和吃生菜差不多。

大部分的互联网应用cache并不是放在JVM中的,而是利用第3方cache server,比如memcached。
你可以试试看将程序中的cache机制改写到第3方的cache server试试看。

我觉得把数据Cache到内存里,唯一的用处就是利用数组来实现内存的随机高速访问.这点对运算密集型的应用来说至关重要,如果是这样的情况memcache这样通过Hash表实现的cache不光是线性查找还有网络传输的消耗,当然可以考虑在程序里再做二级cache.但是一来复杂度高二来取决于cache传输和运算两边的速度,如果运算远快于传输那么我估计二级cache也不会小到哪里去.

直接做本地memchached即可,何必网络访问,相当于本地机器的内存原本是Java占用的缓存空间,换成其他缓存机制占用。

缓存都上3G了,就不应该再用JVM来管理了,也没必要管理,缓存机制有自己的管理方式,不需要全局的垃圾回收。
0 请登录后投票
   发表时间:2008-11-06  
Quake Wang 写道


Ruby+Java性能调优咨询,收费标准:6000火星币/天,报朋友的名字...也是不打折的

请问火星币咋挣?土星币收不收?
0 请登录后投票
   发表时间:2008-11-06   最后修改:2008-11-06
可以考虑用ObjectPool改造一下。从Pool中borrow对象,用完了还给Pool。这样可以大大减少临时对象的生成和回收。JVM对很多Object是不回收的,放在Pool中清零,等待交给下一个租借者。

控制好new Object()和 clazz.newInstance()的位置(包括隐式的调用)。Object主要来自两个方向,前端Action产生的和ORM层从Database返回的一些Bean。特别是从Database 批量搜索出结果后,组装成大量的对象。而这些对象都是临时使用的。这完全可以用Object Pool来优化。

在配置合理的情况下,新生代数量大大减少。
10 请登录后投票
   发表时间:2008-11-06  
把对象池化 其实本质上就是抛弃GC而使用自己的内存策略。或许在这里就是成本最低的选择。
如果逻辑简单而仅仅是访问量大的话,还是用本地代码吧。
0 请登录后投票
   发表时间:2008-11-06  
timerri 写道
把对象池化 其实本质上就是抛弃GC而使用自己的内存策略。或许在这里就是成本最低的选择。
如果逻辑简单而仅仅是访问量大的话,还是用本地代码吧。

这个在GOF设计模式里也有提到的。我觉得可以一试。
0 请登录后投票
   发表时间:2008-11-06   最后修改:2008-11-06
池化绝对是个坏主意,增加了复杂性,1.5g的新生代的回收每10秒占用0.3秒,我觉得这个比例还可以接受,从优化的角度看可以设置新生代小,因为CMS的回收策略不允许新生代平行回收,但CMS在1.6默认支持老年代的平行回收.
主要两点:
   1.控制好缓存对内存的占用
   2.加快新生代回收

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


1) 分开...至少2jvm, cache的做cache, 应用的做应用, 省得相互影响.
2) 分开后, 对cache处理做进一步代码优化(如果还是慢的话). cache方案有很多,opensource产品也多, 不过, 你最好结合你的业务特点, 依据变的程度, 不同jvm处理不同cache.

触发gc的原因是堆不够用, gc过程耗时长的原因是堆过大(另外,对象引用的判断也耗时)
很明显,在你的这个应用中,靠调参去减少堆或增加的堆的大小是没用的.唯一的办法是,分开处理.

业务这一块,堆小一点, gc速度快, 就算经常gc,也没问题.
cache这一块, 堆大一点, 很难很难触发一次gc, 也没问题
0 请登录后投票
论坛首页 Java企业应用版

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