24 | 如何优化JVM内存分配?
该思维导图由 AI 生成,仅供参考
JVM 内存分配性能问题
- 深入了解
- 翻译
- 解释
- 总结
JVM内存分配调优是提高系统性能的关键一环。频繁的GC表现出内存分配不合理,直接影响系统吞吐量和响应时间。了解对象在堆中的生存周期和JVM堆内存的分配情况是调优的基础。通过观察应用服务的运行情况和分析GC日志,可以发现性能问题并进行调优。调整堆内存大小、优化年轻代和老年代的比例、设置Eden、Survivor区比例等方法都可以有效提高系统性能。JVM内存调优通常与GC调优互补,结合上一讲的内容,可以完成JVM调优。在进行性能压测后,如果没有发现突出的性能瓶颈,可以继续使用JVM默认参数。但在需要优化的情况下,可以根据实际情况调整内存分配,相信会有新的收获。文章还提到了堆外内存在NIO的Socket通信中的应用,期待读者的进一步探讨。
《Java 性能调优实战》,新⼈⾸单¥59
全部留言(36)
- 最新
- 精选
- bro.堆外内存创建有两种方式:1.使用ByteBuffer.allocateDirect()得到一个DirectByteBuffer对象,初始化堆外内存大小,里面会创建Cleaner对象,绑定当前this.DirectByteBuffer的回收,通过put,get传递进去Byte数组,或者序列化对象,Cleaner对象实现一个虚引用(当内存被回收时,会受到一个系统通知)当Full GC的时候,如果DirectByteBuffer标记为垃圾被回收,则Cleaner会收到通知调用clean()方法,回收改堆外内存DirectByteBuffer
作者回复: 回答很全面,赞!
2019-07-22465 - 迎风劲草老师,你的这个抢购场景下我理解是不是新生代越大越好,因为对象都是生命周期较短的对象。尽量在新生代中被回收掉。
作者回复: 也不是越大越好,因为新生代过大,会导致minor gc的停顿时间过长。 我们知道,如果新生代很快就满了,会以担保的方式将新增的对象直接分配到老年代,这样增加了老年代回收的成本,这个成本跟具体的垃圾收集器相关。所以我们需要适当的调大年轻代,将对象尽量留在年轻代回收。 如果调整太大,我们知道每次Minor GC分为对象标记和复制两个阶段,并且都是STW的,如果对象过于庞大,有可能标记时间要大于复制时间,这样反而适得其反。
2019-07-1825 - 天天向上如果你在线上环境或性能测试时,发现频繁的 GC,且是正常的对象创建和回收,这个时候就需要考虑调整 JVM 内存分配了。。有个问题,这个频率多久算频繁呢?
作者回复: 线上正常情况下FullGC出现的频率是非常低的,几天一次,一般FullGC如果出现一天超过一次,就已经算频繁了。 做性能压测的时候,FullGC的频率会高一些,但也是仅限于个位数。
2020-01-04220 - QQ怪盲目增大堆内存可能会让吞吐量不增反减,堆内存大了,每次gc扫描对象也就越多也越需要花费时间,反而会适得其反
作者回复: 对的。合理设置堆内存大小,根据实际业务调整,不宜过大,也不宜过小。
2019-07-1610 - 钱课后思考及问题 1:JVM 内存分配不合理最直接的表现就是频繁的 GC,这会导致上下文切换等性能问题,从而降低系统的吞吐量、增加系统的响应时间。 频繁的GC,GC线程和应用线程会频繁的切入切出,所以,降低了系统的性能。 2:老师好,现在有这么一个问题,我们有一个定时任务跑一次大概会有2亿条数据一条数据大概40kb大小,一次大概7.4TB多的数据,分布式任务50台机器需要刷新2个多小时,我们需要持久化,为了提高性能做了异步发送MQ到另外的机器来持久化,不过MQ积压严重,数据跑一次耗时太长,有什么建议的优化思路嘛?拆分消息会加剧业务处理的复杂度,目前我能想到的是加机器加带宽。请老师给个优化的思考?
作者回复: 优化传输性能,例如使用特定的数据结构序列化与反序列化传输数据(protobuff序列化),并且提高单台服务并行处理能力。
2019-09-1137 - 我又不乱来超哥,有两个疑问。 当第一次创建对象的时候 eden 空间不足会进行一次minor gc把存活的对象放到from s区。如果这个时候from s放不下。会发生一次担保进入老年代吗? 当一次创建对象的时候eden空间不足进入from s区。当第二次创建对象的时候eden空间又不足了,这个时候会把,eden和第一次存在from s 区的对象进行gc 存活的放在 to s区,to s区空间不足,进行担保放入老年代?这样的理解对吗。
作者回复: 对的,细节把握的很好! 前提是老年代有容量这些对象的空间,才会进行分配担保。如果老年代剩余空间小于每次minor gc晋升到老年代的平均值,则会发起一次Full GC。
2019-07-166 - 恰饭哒超哥好,我们经常发现生产环境内存使用超过90%持续3分钟,没有outofmer, dump下来堆没有发现问题,这种情况每不确定几小时就会一次,求解答
作者回复: 你好,某一时间段高峰值的访问可能会有这种情况,JVM会最大可能进行对象的回收,防止内存溢出异常的发生。如果不是内存泄漏,或者瞬时并发量大大超过预期并发量的情况,几乎很少发生内存溢出异常。 建议结合内存持续占用率以及Full GC发生的频率来分析调优。
2019-07-1644 - 考休根据老师的教程,在测试项目中,将年轻代的大小调整为3g,发现的确性能提升了,Mirror GC的次数也大大减少,但是Full GC的次数也明显多了几倍,这个是因为年轻代的空间过大,压缩了老年代的内存大小吗? java -jar -Xms4g -Xmx4g -Xmn3g heapTest-0.0.1-SNAPSHOT.jar
作者回复: 是的
2019-11-1333 - 风轻扬老师,如果允许分配担保机制失败。那即使老年代的空间不足以吃下年轻代的对象。jvm也会冒险进行minor gc的。gc之后,如果老年代还是吃不下对象,这个时候才会Full GC。那关闭这个分配担保机制,感觉好一点啊,反正有Full GC兜底呢😃
作者回复: 打开分配担保机制,是为了避免Full GC过于频繁。
2019-09-103 - -W.LI-老师好!堆外缓存实在FGC的时候回收的吧。 AdaptiveSizePolicy这个参数是不是不太智能啊?我项目4G内存默认开启的AdaptiveSizePolicy。发现只给年轻代分配了136M内存。平时运行到没啥问题,没到定时任务的点就频繁FGC。每次定时任务执行完,都会往老年代推40多M,一天会堆300多M到老年代,也不见它把年轻代调大。用的parNew+CMS。后来把年轻代调整到1G(单次YGC耗时从20ms增加到了40ms),每天老年代内存涨20M左右。
作者回复: 这个会根据我们的内存创建大小合理分配内存,并不仅仅考虑对象晋升的问题,还会综合考虑回收停顿时间等因素。 针对某些特殊场景,我们可以手动来配置调优。
2019-07-163