jvm既 Java Virtual Machine,既然是虚拟机,其必有存储空间,且不同的存储空间,存储特定的数据,如图所示: 虚拟机栈:存储基本数据类型、引用对象的变量、局部变量表等,这是线程私有的,每个线上线程的大小...
<a href="#jvm__1">jvm 说明</a> <a href="#_18">性能调优案例</a>
jvm既 Java Virtual Machine,既然是虚拟机,其必有存储空间,且不同的存储空间,存储特定的数据,如图所示:
虚拟机栈:存储基本数据类型、引用对象的变量、局部变量表等,这是线程私有的,每个线上线程的大小默认为1Mb。 程序计数器:存储字节指令的地地址,如果是本地方法栈,则存储undefined。 本地方法栈:由于java时表层语言,无法直接访问硬件,需要调用第三方语言,比如C、C++来操作硬件,比如创建内核线程,操作文件等。 方法区:存储jvm编译后地字节码文件,静态变量,常量,类信息等。 堆:
这是一块很重要的存储区域,也是我们性能调优重要依据,其用来存储java对象,gc回收地也是这一块数据。其分为老年代和新生代,默认数据大小为2 :1。 新生代又分为Eden区,s0区,s1区,默认数据大小为8 : 1 : 1。 新创建一个对象,首先判断能否放到Eden区,如果Eden区满了,会触发mirrorGc「所有的 Minor GC 都会触发“全世界的暂停(stop-the-world)”,停止应用程序的线程,但这段时间可以忽略不计」。此时Eden区和s0区中存活的对象移至s1区,并标志对象的分代年龄,eden区和s0区清空,如果此时对象还无法放置eden区,则直接放置老年代。反之亦然。 分代年龄存储到java对象头中。如果old区满了,会触发fullGc,我们尽量避免fullGc「fullGc暂停所有正在执行的线程(Stop The World),来回收内存空间,这个时间需要考虑地」。
因而,我们所说的性能调优,那么就是堆中的性能调优。
假设,现在有亿级流量电商的抢购活动,活跃用户为500万,付费转化率未10%。活跃时间在抢购的前几分钟,假设每秒产生1000单,而每台Tomcat的最高并发支持数为500,现有三台服务器,均为4核8g,每台服务器均部署Tomcat,使用nginx做负载均衡,有300单落在服务器1上,每单所在堆空间大小为1Kb,每秒大约产生300Kb的堆对象。可以使用lucene来动态计算javabean所在堆空间的大小。下单还会产生其他对象,比如优惠券、库存、积分等,此时放大20倍,也就是每秒产生6000Kb的对象。假设还会有订单查询的操作,此时再放大10倍,也就是每秒产生约58MB的对象。如图所示:
此时,堆初始值大小和最大值大小均为3072MB,老年代大小为2048MB,新生代大小为1024MB,Eden区大小为819MB,s0和s1区大小均为102MB。819Mb / 58Mb = 14秒,大约14秒Eden区爆满,触发mirrorGc,此时停止应用程序的线程。因而,此时需要调整JVM的配置参数,老年代大小为1024MB,新生代大小为2048MB,Eden区大小为1638MB,s0和s1区大小均为204MB。1638Mb/ 58Mb = 28秒,这样会减少mirrorGc,从而达到优化的效果。但更多的优化可根据实际线上jvm运行情况来看。
本站为非盈利网站,如果您喜欢这篇文章,欢迎支持我们继续运营!
本站主要用于日常笔记的记录和生活日志。本站不保证所有内容信息可靠!(大多数文章属于搬运!)如有版权问题,请联系我立即删除:“abcdsjx@126.com”。
QQ: 1164453243
邮箱: abcdsjx@126.com