1、上文案例再分析
2、一个日处理上亿数据的计算系统
MySQL数据库以及其他数据源里提取大量的数据加载到自己的JVM内存里来进行计算处理。
总负载:每分钟大概需要执行500次数据提取和计算的任务
机器配置:使用5台机器,每台机器是4核8G
每台机器负载: 100次/分钟 * 1w条/每次 =100w条/分钟 ,处理1w条数据需要10秒 ,每条数据在1KB
JVM配置:4G内存,新老都是1.5G,Eden:1.2G = 0.15 * 8 ,S1/S2 150M
??1w条数据处理需要10秒,100w条数据处理不是需要1000秒么,怎么是1分钟呢?
答:多线程处理
3、这个系统到底多块会塞满新生代?
总结:计算多久塞满新生代 = Eden区大小/进入Eden的速度 ,1.2G/(100w条/分钟*1KB)=1.2分钟
注意:这里是开启多线程进行处理的,并行度是100/6,即100次提取的数据可以在60秒处里完的,每个线程60秒可以处理6次数据,并行度就是100/6~=16.67 取16
第50秒结束处理 16*5次=80次 任务,占用800M ,数据接入的速度比较快,在不到60秒的时候把新生代赛满了,此时就有200M
4、触发Minor GC的时候会有多少对象进入老年代?
Eden区里有多少对象还是存活的,无法被垃圾回收呢?
假设80个任务执行结束,20个任务还在技术,20*(一个任务=1w条数据 = 10M)=200M,也就是200M存活,S区150M放不下200M存活对象
(垂直+三角形类型,直接进行YoungGC,YoungGC过程中发现S区放不下存活对象,直接把200M对象晋升到老年代)
DSM:新生代所有对象大小>老年代剩余空间前提下,触发老年代的GC有3种情形:1、垂直+三角 2、3两种是中5少横
5、系统运行多久,老年代大概就会填满?
假设每次进入200M到老年代,1.5G,7次YoungGC就1.4了,第八次YoungGC前判断空间担保会失败,也就是说第8分钟结束时进行FullGC
6、这个系统运行多久,老年代会触发1次Full GC?
第8分钟结束时进行FullGC
7、该案例应该如何进行JVM优化?
存在频繁进入老年代的短命对象,此时考虑增大Survivor,让短命对象不要进入老年代,尽量在新生代就被回收。
2GB分配给新生代,1GB留给老年代,默认情况下Survivor区200M,刚好放下。为了留有空余空余考虑调整一下SurvivorRatio为6,这样Survivor区就有250M了
8、如果该系统的工作负载再次扩大10倍呢?
扩大10倍,每秒新增100M,1.6G/100M 16秒左右Eden就满了,此时YoungGC,能回收的1G左右,600M左右直接进入老年代,1G的老年代,第二次就要OldGC了。一分钟要进行2-3次FullGC系统性能造成了巨大的影响,简直是可怕至极
9、使用大内存机器来优化上述场景
计算类的系统,也是非常的吃内存的,所以换成了每台机器都是16核32G的高配置机器。
Eden基本上空间会扩大10倍,比如有16GB,Survivor区2G,这样16G/100M 约两分多钟进行一次YoungGC,每次存活几百M,再次YoungGC时,存活的几百M又会被回收了。这样短命的对象不会进入老年代。完美解决频繁YoungGC和FullGC。
大内存是否都要换成G1呢?对响应时间不敏感的,不直接面向用户的系统,没有必要。
本文是《从 0 开始带你成为JVM实战高手》内容总结,版权问题,特此声明。详细内容:
购买成功后找我返现10元