Anaconda ClickHouse Scala Java开发手册 resultMap 人工智能 reactjs authentication mysqli enums node ios4 webkit vue滑动事件 网赚教程下载 广告投放系统源码 鼠标进入和离开事件 jquery删除子元素 oracle分页关键字 oracle限制查询条数 windows杀进程命令 python命令 python抛异常 java变量 java编程学习入门 java读取文件数据 java集合框架图 java的特性 linux镜像安装 简体中文语言包 苹果手机老是自动重启 max电池容量 java语言程序设计 识别音乐的软件 刷声望 netreflector 算法笔记 视频md5修改器 坐标标注插件 男网红头像
当前位置: 首页 > 学习教程  > 编程语言

JVM 性能调优之内存优化(四)

2020/9/19 15:36:33 文章标签:

今天我们进行JVM 性能优化:
JVM 调优是一个系统而又复杂的过程,但我们知道,在大多数情况下,我们基本不用去调整 JVM 内存分配,因为一些初始化的参数已经可以保证应用 服务正常稳定地工作了。在应用服务的特定场景下, JVM 内存分配不合理带来的性能表现并不会像内存溢出问题这么突出。一般你没有深入到各项性能指标中去,是很难发现其 中隐藏的性能损耗。
 
1、压测工具 AB
Ab(ApacheBench) 测试工具是 Apache 提供的一款测试工具,具有简单易上手的特点,在测试 Web 服务时非常实用。
ab 一般都是在 Linux 上用。 安装非常简单,只需要在 Linux 系统中输入 yum-y install httpd-tools 命令,就可以了。
安装成功后,输入 ab 命令,可以看到以下信息:

 

ab 工具用来测试 post get 接口请求非常便捷,可以通过参数指定请求数、并发数、请求参数等
测试 get 请求接口 ab -c 10 -n 100 http://www.test.api.com/test/login?userName=test&password=test
测试 post 请求接口
ab -n 100 -c 10 -p 'post.txt' -T 'application/x-www-form-urlencoded' 'http://test.api.com/test/register'
post.txt 为存放 post 参数的文档,存储格式如
usernanme=test&password=test&sex=1
参数的含义:
-n :总请求次数(最小默认为 1 );
-c :并发次数(最小默认为 1 且不能大于总请求次数,例如: 10 个请求, 10 个并发,实际就是 1 人请求 1 次);
-p post 参数文档路径( -p -T 参数要配合使用);
-T header 头内容类型(此处切记是大写英文字母 T );
输出中,性能指标参考
 
Requests per second :吞吐率,指某个并发用户数下单位时间内处理的请求数;
Time per request :上面的是用户平均请求等待时间,指处理完成所有请求数所花费的时间 / (总请求数 / 并发用户数);
Time per request :下面的是服务器平均请求处理时间,指处理完成所有请求数所花费的时间 / 总请求数;
Percentage of the requests served within a certain time :每秒请求时间分布情况,指在整个请求中,每个请求的时间长度的分布情况,例如有 50% 的请求
响应在 8ms 内, 66% 的请求响应在 10ms 内,说明有 16% 的请求在 8ms~10ms 之间。
 
 
2、JVM 堆内存分配
JVM 内存分配的调优案例
一个高并发系统中的抢购接口,高峰时 5W 的并发请求,且每次请求会产生 20KB 对象(包括订单、用户、优惠券等对象数据)。
我们可以通过一个并发创建一个 1MB 对象的接口来模拟万级并发请求产生大量对象的场景,具体代码如下:
 
 
3、AB 压测
对应用服务进行压力测试,模拟不同并发用户数下的服务的响应情况:
1 10 个并发用户 /10 万请求量 ( )
2 100 个并发用户 /10 万请求量 ( )
3 1000 个并发用户 /10 万请求量 ( )
ab -c 10 -n 100000 http://127.0.0.1:8080/jvm/heap
ab -c 100 -n 100000 http://127.0.0.1:8080/jvm/heap
ab -c 1000 -n 100000 http://127.0.0.1:8080/jvm/heap
 
4、服务器信息
我本机起一台 Linux 虚拟机,分配的内存为 2G ,处理器数量为 2 个。具体信息如下图:
 
5、GC 监控
还有一句话,无监控不调优,所以我们需要监控起来。 JVM 中我们使用 jstat 命令监控一下 JVM GC 情况。
统计 GC 的情况。
jstat-gc 8404 5000 20 | awk '{print $13,$14,$15,$16,$17}
6、堆空间监控
在默认不配置 JVM 堆内存大小的情况下, JVM 根据默认值来配置当前内存大小。
我们可以通过以下命令来查看堆内存配置的默认值:
java -XX:+PrintFlagsFinal -version | grep HeapSize
 
 
7、调整方案二
java -jar -Xms1500m -Xmx1500m -Xmn1000m -XX:SurvivorRatio=8 jvm-1.0-SNAPSHOT.jar
使用 AB 进行压力测试:
ab -c 10 -n 100000 http://127.0.0.1:8080/jvm/heap
 
 
内存优化总结:
一般情况下,高并发业务场景中,需要一个比较大的堆空间,而默认参数情况下,堆空间不会很大。所以我们有必要进行调整。
但是不要单纯的调整堆的总大小,要调整新生代和老年代的比例,以及 Eden 区还有 From 区,还有 To 区的比例。
所以在我们上述的测试中,调整方案二,得到结果是最好的。在三种测试情况下都能够有非常好的性能指标,同时 GC 耗时相对控制也较好。
对于调整方案一,就是单纯的加大堆空间,里面的比例不适合高并发场景,反而导致堆空间变大,没有明显减少 GC 的次数,但是每次 GC 需要检索对象
的堆空间更大,所以 GC 耗时更长。
方案二:调整为一个很大的新生代和一个较小的老年代 . 原因是 , 这样可以尽可能回收掉大部分短期对象 , 减少中期的对象 , 而老年代尽存放长期存活对象。
由于新生代空间较小, Eden 区很快被填满,就会导致频繁 Minor GC ,因此我们可以通过增大新生代空间来降低 Minor GC 的频率。
单次 Minor GC 时间是由两部分组成: T1 (扫描新生代)和 T2 (复制存活对象)。
默认情况: 一个对象在 Eden 区的存活时间为 500ms Minor GC 的时间间隔是 300ms ,因为这个对象存活时间 > 间隔时间,那么正常情况下, Minor
GC 的时间为 : T1+T2
方案一: 整堆空间加大,但是新生代没有增大多少,对象在 Eden 区的存活时间为 500ms Minor GC 的时间可能会扩大到 400ms ,因为这个对象存
活时间 > 间隔时间,那么正常情况下, Minor GC 的时间为 : T1*1.5 Eden 区加大了) +T2
方案二: 当我们增大新生代空间, Minor GC 的时间间隔可能会扩大到 600ms ,此时一个存活 500ms 的对象就会在 Eden 区中被回收掉,此时就不
存在复制存活对象了,所以再发生 Minor GC 的时间为:即 T1*2 (空间大了) +T2*0
可见,扩容后, Minor GC 时增加了 T1 ,但省去了 T2 的时间。
JVM 中,复制对象的成本要远高于扫描成本。如果在堆内存中存在较多的长期存活的对象,此时增加年轻代空间,反而会增加 Minor GC 的时间。如
果堆中的短期对象很多,那么扩容新生代,单次 Minor GC 时间不会显著增加。因此,单次 Minor GC 时间更多取决于 GC 后存活对象的数量,而非 Eden
区的大小。
这个就解释了之前的内存调整方案中,方案一为什么性能还差些,但是到了方案二话,性能就有明显的上升。
 
8、推荐策略
(1) 新生代大小选择
响应时间优先的应用 : 尽可能设大 , 直到接近系统的最低响应时间限制 ( 根据实际情况选择 ). 在此种情况下 , 新生代收集发生的频率也是最小 的。 同时 , 减少到达老年代的对象 .。 吞吐量优先的应用: 尽可能的设置大 , 可能到达 Gbit 的程度 . 因为对响应时间没有要求 , 垃圾收集可以并行进行 , 一般适合 8CPU 以上的应用。 避免设置过小. 当新生代设置过小时会导致 :1.MinorGC 次数更加频繁 2. 可能导致 MinorGC 对象直接进入老年代 , 如果此时老年代满了 , 会触 发 FullGC.
(2) 老年代大小选择
响应时间优先的应用 : 老年代使用并发收集器 , 所以其大小需要小心设置 , 一般要考虑并发会话率和会话持续时间等一些参数 . 如果堆设置小了 , 可 以会造成内存碎 片, 高回收频率以及应用暂停而使用传统的标记清除方式 ; 如果堆大了, 则需要较长的收集时间 . 最优化的方案 , 一般需要参考以下数据获得 : 并发垃圾收集信息、持久代并发收集次数、传统 GC 信息、花在新生代和老年代回收上的时间比例。 吞吐量优先的应用: 一般吞吐量优先的应用都有一个很大的新生代和一个较小的老年代 . 原因是 , 这样可以尽可能回收掉大部分短期对象 , 减少中期的对象 , 而 老年代尽存放长期存活对象。

到此,JVM 性能调优之内存优化分析结束!

 

 


本文链接: http://www.dtmao.cc/news_show_200281.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?