GC浅析之三-性能调优经验总结

性能调优经验总结

问题的出现:

在日常环境下,以某server 为例,该机器的每秒的访问量均值在368左右,最大访问量在913。对外提供服务的表现为每两三个小时就有秒级别的时间客户端请求超时,在访问量增大的情况下用户请求超时频率明显增多。

现象的直接分析:

通过监控GC发现该现象,GC中比较频繁的出现promotion failed和concurrent mode failure。由于promotion failed产生的直接原因为在发送YGC时,old区因为碎片、可用空间不够,造成无法晋升对象。在某server这个case下:由于线上配置了XX:+UseCMSCompactAtFullCollection,使用CMS回收old区内存时进行碎片压缩。猜测promotion failed的原因应该就是old区内存不够而不是碎片引起的。有太多对象,太频繁地被晋升成为到了old区,或者old区的对象一直没有被回收,引发晋升到old区不成功。

根据现象对被测server猜测:

server长轮询功能前:server服务的请求类型有如下几种
1)sdk各种查询、发布
2)client短轮询
3)client同步获取配置
server端中内存中的对象根据生命周期长度可以分以下2类
1)响应服务而创建的临时变量
2)监控数据订阅者数量和被订阅配置个数的一个数据结构
其中前者的数量会远远超过后者,所以在-XX:NewSize=2g -XX:MaxNewSize=2g -XX:SurvivorRatio=10的配置下,只有很少的对象被晋升到old区。
从监控的数据中也可以看到长轮询发布以前server的Minor GC和CMS GC的次数统计
-  Minor GC的次数和QPS有关
- CMS 平均每天只发生 0.几次

server长轮询功能发布后:server服务的请求类型有如下几种
1)sdk各种查询、发布
2)client短轮询
3)client长轮询
4)client同步获取配置
server端中内存中的对象根据生命周期长度可以分以下3类
1)响应服务而创建的临时变量 [一次请求的RT]
2)响应长轮询而创建的变量 [长轮询hold时间30s]
3)监控数据订阅者数量和被订阅配置个数的数据结构[一直活着]
4)监控长轮询客户端数量和订阅配置个数的数据结构[一直活着]
猜测结论长轮询引发。原因随着长轮询的请求量越来越大,在JVM内存配置不变和总QPS不变的情况下,系统每次Minor GC可以回收的空间会越来越少。每次Minor GC,copy到survivor区的对象会变多,并且配置2G新生代+SurvivorRatio=10的情况下,长轮询使用的内存至少存活30s,造成了很多对象被晋升到old区。最终造成了promotion failed、concurrent mode faliure的发生。

真实情况模拟验证猜测:

  1. 测试环境准备:

硬件信息:

实体机一台:16核心。主频:2.27。Linux iSearch006030.sqa.cm4 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux。内存:24G。

软件信息:

服务器:某 server

主要启动参数配置: -Xms4g -Xmx4g -XX:NewSize=2g -XX:MaxNewSize=2g -XX:PermSize=128m -XX:MaxPermSize=256m -XX:SurvivorRatio=10 -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/***/logs -verbose:gc -Xloggc:/home/nami.zft/****/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Djava.awt.headless=true -Dsun.net.client.defaultConnectTimeout=10000 -Dsun.net.client.defaultReadTimeout=30000 -Dsun.security.ssl.allowUnsafeRenegotiation=true

  1. 数据分析与准备:

将日常环境server端的所有数据拉下来,数据中419个group,32,787 个dataId,大小为151 MB。将数据整理,发布到server,确保测试server 的cache 与日常环境一致。

经过统计长轮询与端轮询的比例大约是1:1.5,长短轮询post占总请求操作的90%,其中并且get请求占10%。为了加快现象的发生,长轮询的每秒存活数量在1500,短轮询每秒的请求数量在1000,change config每秒在200,get config在200。

  1. 测试开始以及结果:

图一 在10个并发下,用户请求的qps 变化图

图二jvm old区内存使用率

图三GC时间

性能分析:在前面所述的压力下,8分钟就开始重现日常环境的现象。由于关于服务器的各项性能指标来看,cup,load,磁盘使用,服务器内存全部磁盘io没有到达瓶颈,所以就不一一给图分析。在10个并发下成功的tps在15.48分的时候开始下跌,并且呈现不稳定状况,如图一。可以从图二看到Old区从压力开始的2分钟后开始直线状增加,开始的11分钟开始old区利用率到达100%并且维持住,证明old区必定有些对象一直没被释放掉。于是在图三就出现了Full 的时间越来越长。

原因定位:通过dump heap发现确实有一个对象存活的时间特别长,占住old区导致old 区不能被释。定位于66.3%的对内存耗费在org.apache.catalina.session.StandardManager对象上,参考Tomcat容器中的实现,认定内存耗费在session对象上,并且发现这个session存活的时间味哦30分钟。参考blog http://ddupnow.iteye.com/blog/621619。于是导致了YGC晋升失败。

解决方案:缩短session时间

结果验证

在测试环境保证与上一步骤保持一致的前提下,缩短session时间。同样的性能场景回放。Jvm的使用率在11%左右,full GC在两个小时内只进行了一次full GC,结果如下图所示。进一步验证是通过提高并发数到200个并发以及性能测试的时间时间加大到2天,。TPS保持在稳定1k左右,Full GC的次数为1,old区也最终趋于稳定。

时间: 2024-08-09 06:21:05

GC浅析之三-性能调优经验总结的相关文章

java 性能调优工具

1.jstack 用法jstack [option] pid -l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况 -m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法) 找出进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid printf "%x\n" pid 得到pid的

书讯 —《产品级性能调优与故障诊断分析》

<产品级性能调优与故障诊断分析> 封面巨照 作者简介 郑健,2006~2009连任三届<微软最有价值专家>,荣获<DevWOW微软博客达人>优胜奖,荣获微软<最有影响力开发者>奖项,通过微软[MCSA/MCSE]认证,公司性能优化专家,CSDN 博客专家,著有[庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术]一书,目前在北京用友软件做产品优化方面的工作. Email: [email protected] 本书主要内容 一个运行中的系统会受到到很多

图书 —《产品级性能调优与故障诊断分析》

<产品级性能调优与故障诊断分析> 封面巨照 作者简介 郑健,2006~2009连任三届<微软最有价值专家>,荣获<DevWOW微软博客达人>优胜奖,荣获微软<最有影响力开发者>奖项,通过微软[MCSA/MCSE]认证,公司性能优化专家,CSDN 博客专家,著有[庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术]一书,目前在北京用友软件做产品优化方面的工作. Email: [email protected] 本书主要内容 一个运行中的系统会受到到很多

成为Java GC专家(5)—Java性能调优原则

这是"成为Java GC专家"系列的第五篇文章.在第一篇深入浅出Java垃圾回收机制中,我们已经学习了不同的GC算法流程.GC的工作原理.新生代(Young Generation)和老年代(Old Generation)的概念.你应该了解了JDK7中5种GC类型以及各种类型对应用程序的影响. 在第二篇如何监控Java的垃圾回收中,阐述了JVM是怎样实际执行垃圾回收的,我们怎样去监控GC以及哪些工具能让这个过程更高效. 第三篇如何如何优化Java垃圾回收机制中展示了一些基于真实案例的最佳

[RAC性能调优] gc buffer busy acquire 处理

 RAC性能调优] gc buffer busy acquire 处理          分类: troubleshooting RAC 2014-04-21 20:02 255人阅读 评论(0) 收藏 编辑 删除 目录(?)[+] RAC性能调优 gc buffer busy acquire 处理  [RAC性能调优] gc buffer busy acquire 处理 event 解释: gc buffer busy acquire是当session#1尝试请求访问远程实例(remo

java 性能调优和GC

JAVA 性能调优和GC http://blog.csdn.net/gzh0222/article/details/7663181 JAVA GC调优手记 http://blog.csdn.net/firecoder/article/details/7225654 JAVA GC 日志详解 http://blog.csdn.net/alivetime/article/details/6895537 JAVA 内存参数设置 http://heipark.iteye.com/blog/1356113

性能调优攻略

关于性能优化这是一个比较大的话题,在<由12306.cn谈谈网站性能技术>中我从业务和设计上说过一些可用的技术以及那些技术的优缺点,今天,想从一些技术细节上谈谈性能优化,主要是一些代码级别的技术和方法.本文的东西是我的一些经验和知识,并不一定全对,希望大家指正和补充. 在开始这篇文章之前,大家可以移步去看一下酷壳以前发表的<代码优化概要>,这篇文章基本上告诉你--要进行优化,先得找到性能瓶颈! 但是在讲如何定位系统性能瓶劲之前,请让我讲一下系统性能的定义和测试,因为没有这两件事,后

JVM调优经验分享

前言 一.JVM调优知识背景简介 二.JVM调优参数简介 三.JVM调优目标 四.JVM调优经验 结束语 <br/> 本次分享探讨的JVM调优是指server端运行的JVM调优,适应版本为[1.6– 1.7], 不涉及最新的1.8版本. 假设线程池.连接池.程序代码等都已经做过优化,效果(系统吞吐量.响应性能)仍然不理想,我们就可以考虑JVM调优了. <br/> 一. JVM调优知识背景简介 1.堆与栈的概念 堆和栈是程序运行的关键:栈是运行时的单位,而堆是存储的单位. 栈解决程序

Spark日志分析项目Demo(9)--常规性能调优

一 分配更多资源 分配更多资源:性能调优的王道,就是增加和分配更多的资源,性能和速度上的提升,是显而易见的:基本上,在一定范围之内,增加资源与性能的提升,是成正比的:写完了一个复杂的spark作业之后,进行性能调优的时候,首先第一步,我觉得,就是要来调节最优的资源配置:在这个基础之上,如果说你的spark作业,能够分配的资源达到了你的能力范围的顶端之后,无法再分配更多的资源了,公司资源有限:那么才是考虑去做后面的这些性能调优的点. 问题: 1.分配哪些资源? 2.在哪里分配这些资源? 3.为什么