怎样通过优化JVM参数配置从而提升性能
怎样通过优化JVM参数配置从而提升性能?针对这个问题,今天小编总结这篇有关sortx参数使用的文章,希望能帮助更多想解决这个问题的朋友找到更加简单易行的办法。
1 内存构成
年老代 | 年轻代 |
Eden | |
S1 | |
S2 |
如图,Java虚拟机的内存,也就是常说的堆,主要分为年轻代和年老代两个部分。年轻代存放生命周期很短的对象,年老代存放长期存活的对象。例如,经过几次垃圾回收之后,一个对象仍然存活,那么这个对象就会从年轻代进入年老代。
年轻代又分为3个区:Eden、Survivor 1、Survivor 2(以下简称Eden、S1、S2)。Eden存放新对象,S1和S2交替使用,用来存放垃圾回收时存活的对象。
2 回收策略
Java虚拟机的垃圾回收策略很复杂,这里我们只关心最影响性能的几种情况。
Java的垃圾回收分为两种:Full GC和minor GC,前者是对年老代的回收,一般会很慢,后者是针对年轻代的回收,这个很快。我们调优的目标就是尽量避免频繁的Full GC。那么什么情况会触发Full GC呢?上面说了,新对象会存放在Eden区,而当Eden区满了的时候就会触发minor GC,此时Eden区的垃圾对象会被清除,而存活下来的有用对象则会往S1或S2区复制,从而完成一次回收过程。在这个过程中,如果S1或S2区装不下Eden里幸存的对象了,就会把幸存的对象保存到年老代,而如果年老代也没有空间了,就会触发Full GC。
简述就是,Survivor区装不下年轻代的幸存对象时,会造成年老代的增长,随着年老代不断增长,Full GC必然会被触发。
3 sortx 时的内存使用
我们知道sortx函数有个参数n,n是缓冲区条数,表示每次从游标中取出来的记录条数。那么n取什么值最合适呢?
显然n不能取值太大,否则会造成内存溢出,根本无法使用。
那么再不断尝试取小点,经过几次尝试后,会发现可以用了,不会溢出了。但这时不一定是最优取值,如果n取值占用的内存大于Eden,且正好把年老代占用的差不多了,则每次取出的数据都会送进年老代,等到下一次取数的时候,就触发Full GC,而这种频繁触发是最耗时的。
所以,从Java的分配和回收策略来看,最理想的情况是,n的取值占用的内存,略小于Eden的大小。这是因为sortx这类运算的特点是"取出即用,用完就扔",很少有对象会常驻内存。
那么如何知道Eden区的大小然后估算n呢?
4 内存分配
在 IDE 的启动配置里可以看到,参数 -Xmx 用来指定分配给 java 的堆内存的大小。例如 -Xmx10g 就表示分配了 10G 内存给 Java。那么 Java 如何把这 10G 分配给这几个区呢?
默认的情况下,各区比例大概是这样的:
年轻代 : 年老代 = 3 : 7
Eden : S1 : S2 = 8 : 1 : 1
有了比例,很容易算出来各区大小,年老代占 7G,年轻代占 3G,其中 Eden 占 2.4G,S1 和 S2 各占 0.3G。据说这个默认比例是 jdk 的开发人员统计得出的,认为在大部分应用中,幸存对象占全部对象的 1/10。然而这个比例不一定适合所有情形,至少在 sortx 时就不太合适。
5 结论
n的取值原则:使用 sortx 时,在不溢出的前提下,n 的取值并不是越大越好,而是(根据 Eden 大小)估算一个合适值,这个值不引起频繁 Full GC。
验证 n 值是否合适的办法如下:
1 添加参数 -XX:+PrintGC。
2 运行 sortx。
3 观察控制台,如果频繁出现 [Full GC (Allocation Failure)……] 信息则调小 n,重试。
4 如果只出现很多 [GC (Allocation Failure)……] 信息,则认为 n 的值是合适的。
5 如果出现很多 [GC (Allocation Failure)……] 信息的同时,偶尔出现 [Full GC (Allocation Failure)……] 信息,则也可以认为 n 的值是合适的。
6 确保临时文件不能太小。
6 调参
一般来说通过调整n,就基本可以满足sortx的性能了,如果还想进一步追求性能,就需要调参了。默认分配的年轻代只占堆的3/10,而年老代那7/10的内存在sortx这种计算时显得作用不大。如果想调整这个比例,又允许sortx使用一个专门的启动配置,则可以使用参数-XX:NewSize进行调整。
例如,-XX:NewSize=5g,就指定年轻代的大小是5G。
提示一下,调整的时候,年老代的空间也不能留的太少,占整个堆的1/5是合适的。这是因为Java的分配策略还有很多复杂情况,比如总空间够但不连续时,仍会直接把对象装入年老代。类似的情况还有一些,不再赘述。
同样地,Eden和S1、S2的比例也会影响性能,如果想调整这个比例也可以使用参数-XX:SurvivorRatio。例如-XX:SurvivorRatio=1表示Eden:S1:S2 = 1:1:1。-XX:SurvivorRatio=8表示Eden:S1:S2 = 8:1:1。
一般来说,Survivor区越大,对象进入老年代的概率就越小,所以在做sortx时,倾向于配置为-XX:SurvivorRatio=1。
7 其它
参数的配置没有一致的准则,需要根据计算的类型来调整,有时候年老代大一些好(比如大维表需要常驻内存的),有时候则是年轻代大一些好。
看完这篇文章,你们学会通过优化JVM参数配置从而提升性能了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读。