使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码 (jvm性能调优)
技术交流群:233513714
本文是《JVM 性能调优实战之:一次系统性能瓶颈的寻找过程》 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍),并准确定位系统瓶颈:我们应用里静态对象不是太多、有大量的业务线程在频繁创建一些生命周期很长的临时对象,代码里有问题。那么问题来了,如何在海量业务代码里边准确定位这些性能代码?本文将介绍如何使用阿里开源工具 TProfiler 来定位这些性能代码,成功解决掉了 GC 过于频繁的性能瓶颈,并最终在上次优化的基础上将 TPS 再提升了4 倍,即提升到 100。
1. TProfiler 的下载安装
1.1. 下载
访问 TProfiler 的 GitHub 主页,点击 Clone or download 按钮的打开下载选项,点击该选项下的 Download ZIP 按钮将 TProfiler-master.zip 下载到本地。笔者上传了一份截至 20160920 最新 TProfiler-master.zip 到 CSDN 资源,读者朋友也可以去这里下载:http://download.csdn.net/detail/defonds/9635731。
1.2. 安装
SSH 登录需要监控的远程服务器主机,为 TProfiler 新建安装路径:
$ mkdir /opt/tprofiler
本地将下载后的 TProfiler-master.zip 解压缩,将 dist 目录下的 profile.properties 以及 dist/lib 目录下的 tprofiler-1.0.1.jar ftp 上传到远程服务器 /opt/tprofiler 目录下。
最后将远程服务器 /opt/tprofiler 目录及其下所有文件的所有者改为启动 Weblogic 进程的用户及其所在用户组。
2. TProfiler 的配置部署
2.1. TProfiler 配置
编辑服务器 /opt/tprofiler/profile.properties 文件内容如下:
#log file name
logFileName = tprofiler.log
methodFileName = tmethod.log
samplerFileName = tsampler.log
#basic configuration items
startProfTime = 9:00:00
endProfTime = 23:00:00
eachProfUseTime = 5
eachProfIntervalTime = 50
samplerIntervalTime = 20
port = 30000
debugMode = false
needNanoTime = false
ignoreGetSetMethod = true
#file paths
logFilePath = ${user.home}/logs/${logFileName}
methodFilePath = ${user.home}/logs/${methodFileName}
samplerFilePath = ${user.home}/logs/${samplerFileName}
#include & excludes items
excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader
includePackageStartsWith =com.caucho;com.defonds;com.fasterxml;com.sun.jersey;com.sun.jmx;org.apache;org.codehaus;org.jdbcdslog;org.mybatis;org.quartz;org.springframework
excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject
红色部分是我们修改后的内容,其它部分使用默认值。
2.2. Weblogic 启动参数配置
在 Weblogic JVM 启动参数里加入:
-javaagent:/opt/tprofiler/tprofiler-1.0.1.jar -Dprofile.properties=/opt/tprofiler/profile.properties
之后重启 Weblogic。
3. TProfiler 的远程操作
使用启动 Weblogic 进程的用户 SSH 远程登录正在进行压测的机器。
3.1. 查看 TProfiler 当前状态
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.client.TProfilerClient 127.0.0.1 30000 status
running
得到这个结果证明 TProfiler 正在进行采集工作。
3.2. 将 TProfiler 停止,以释放其占用的系统资源
随时关闭 TProfiler:
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.client.TProfilerClient 127.0.0.1 30000 stop
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.client.TProfilerClient 127.0.0.1 30000 status
stop
随时启动以继续采集:
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.client.TProfilerClient 127.0.0.1 30000 start
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.client.TProfilerClient 127.0.0.1 30000 status
running
3.3. 刷出数据
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.client.TProfilerClient 127.0.0.1 30000 flushmethod
会将数据刷出到 ~/logs/ 目录下:
4. TProfiler 对性能方法的采集
4.1. 普通方法、线程统计
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.analysis.SamplerLogAnalysis ~/logs/tsampler.log ~/logs/method.log ~/logs/thread.log
4.2. top 统计
$ java -cp /opt/tprofiler/tprofiler-1.0.1.jar com.taobao.profile.analysis.ProfilerLogAnalysis ~/logs/tprofiler.log ~/logs/tmethod.log ~/logs/topmethod.log ~/logs/topobject.log
方法执行时间统计:这个非常非常重要,这个是 TProfiler 最最重要的 feature,是其能够傲视所有其他性能测试类(包括 jvm 性能测试类)软件的关键所在,我们将会不止一次地在关键的时候受益于 TProfiler 的这一非常有用的特性。
上述命令刷出的 topmethod.log 部分结果如下:
com/defonds/core/ppts/common/support/JsonUtils:object2jsonString:123 13519 154 2083584
com/caucho/hessian/client/HessianURLConnection:sendRequest:156 15894 130 2072565
com/defonds/rest/core/client/proxy/ResourceJsonInvocationHandler:invoke:39 8123 113 921340
com/defonds/core/ppts/cache/service/impl/MerBankCfgServiceImpl:selectMerBankCfgByParams:72 54213 15 799322
com/defonds/core/ppts/incomes/biz/sinopay/service/impl/SinoPayBankReturnServiceImpl4Json:updateOrderSuccess:792 2495 176 438542
com/defonds/core/ppts/common/support/framework/bean/Message:<init>:76 6219 26 163741
com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer:serializeContents:107 51883 3 145556
com/defonds/core/ppts/cache/biz/cims/impl/AccountPrdAndBankCacheImpl:selectBasicProductCfg:144 16131 8 137029
格式说明:方法信息 执行次数 平均执行时间(单位:ms) 全部执行时间(单位:ms)
5. 性能方法的优化
根据 topmethod.log 统计结果,我们拿到了热点方法 top10:
| 方法名 | 被调用次数 | 平均执行时间(ms) | 采样内总执行时间(ms) |
|---|---|---|---|
| com/defonds/core/ppts/common/support/JsonUtils:object2jsonString:123 | 13519 | 154 | 2083584 |
| com/caucho/hessian/client/HessianURLConnection:sendRequest:156 | 15894 | 130 | 2072565 |
| com/defonds/rest/core/client/proxy/ResourceJsonInvocationHandler:invoke:39 | 8123 | 113 | 921340 |
| com/defonds/core/ppts/cache/service/impl/MerBankCfgServiceImpl:selectMerBankCfgByParams:72 | 54213 | 15 | 799322 |
| com/defonds/core/ppts/incomes/biz/sinopay/service/impl/SinoPayBankReturnServiceImpl4Json:updateOrderSuccess:792 | 2495 | 176 | 438542 |
| com/defonds/core/ppts/common/support/framework/bean/Message:<init>:76 | 6219 | 26 | 163741 |
| com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer:serializeContents:107 | 51883 | 3 | 145556 |
| com/defonds/core/ppts/cache/biz/cims/impl/AccountPrdAndBankCacheImpl:selectBasicProductCfg:144 | 16131 | 8 | 137029 |
| com/defonds/core/ppts/common/jms/retrieve/listener/DefaultMessageListener:handleMessage:64 | 2981 | 46 | 136180 |
| com/fasterxml/jackson/databind/ser/BeanPropertyWriter:serializeAsField:573 | 53892 | 2 | 112553 |
这是压测时根据多次采样结果,拣选出的一次比较有代表性的一次。红色部分值得我们去重点关注并优化一下,因为极有可能就是应用瓶颈所在。这些代码要么是导致平均响应时间低下的一些点,要么是导致大量临时对象产生的一些点。
对于上篇博客中的结论,这些代码的调优原则是:临时对象能改成静态对象进行复用就改成公用对象否则要想方设法缩短其生命周期;高频访问代码提高响应速度。根据 jvm gc 日志发现很多 young gc 之后堆内存已用空间不仅下降反而上升至最大使用量导致 full gc,临时对象如果可以和其它线程复用的话改成静态对象以减少大量线程 local 对象的产生。
以排名第一的热点方法 com/defonds/core/ppts/common/support/JsonUtils:object2jsonString:123 为例,看看如何来进行调优。
- import org.codehaus.jackson.map.ObjectMapper;
- public static <T> String object2jsonString(T t) {
- try {
- ObjectMapper objectMapper = instanceObjectMapper();
- return objectMapper.writeValueAsString(t);
- } catch (JsonParseException e) {
- log.error(e.getMessage(), e);
- throw new SysException(e);
- } catch (JsonMappingException e) {
- log.error(e.getMessage(), e);
- throw new SysException(e);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- throw new SysException(e);
- }
- }
- public static ObjectMapper instanceObjectMapper() {
- JsonFactory jf = new JsonFactory();
- jf.configure(Feature.WRITE_NUMBERS_AS_STRINGS, true);
- return new ObjectMapper(jf);
- }
该热点方法的优化建议:
这个方法平均调用时间在 154ms,如果在低并发时可能比这要小得多。但是高并发时可能要等待 GC 的堆内存释放、GC 作业时对业务线程造成的暂停时间等因素影响,这个时间会被无限放大。
5.1. 临时对象改成静态对象
object2jsonString 方法的 objectMapper 对象,instanceObjectMapper 方法的 jf 对象;
5.2. json 处理由 jackson 改为 fastjson
jackson 和 spring 整合的很好,提供的功能点很多很强大。但是其性能未必靠得住。
比如我们原来用过谷歌的 Gson 进行 json 处理,某个大对象的 json 解析使用 gson 是 100 多秒,而换成 fastjson 解析后是 900 多毫秒。上百倍的性能差距呀,这还是在单用户操作、不能存在 CPU 和内存等资源限制及竞争的情况下拿到的数据。在此向贡献出 fastjson 的阿里人致敬~
5.3. 频繁 GC 的瓶颈已不复存在
针对 TProfiler 帮我们在海量业务代码中定位到的 top5 性能代码进行优化后,部署重新压测,50 个用户并发两个小时左右,我们拉了几次快照,上篇博客中定位的频繁 GC 的性能瓶颈已不复存在,TRT 也由上篇博客优化到的 2.5 下降到 0.5,TPS 基本能稳定在 100 个。问题圆满解决。
6. 需要注意的一些问题
6.1. TProfiler 端口号是否已被占用
为 TProfiler 选取端口号之前要先检测一下该端口号是否已被占用:
$ netstat -an | grep 30000
6.2. TProfiler 配置里 includePackageStartsWith
一定要根据你自己的系统进行实际更改,不然就会遇到《TProfiler.log的内容为空 #33》的问题,截图如下:
6.3. 几个命令配合使用
在压测的时候,结合使用 start、stop、flushmethod、ProfilerLogAnalysis topmethod 等几个命令,以拿到关键性的结果。如果能再结合 Weblogic、LoadRunner 的启动、停止,效果最佳。不然的话,如果 JVM 已经跑了很多天,拿到的数据可能不是你想要的,反而会误导你南辕北辙。
7. 后记
总体来讲,TProfiler 配置部署、远程操作、日志阅读都不太复杂,操作还是很简单的。但是其却是能够起到一针见血、立竿见影的效果,帮我们解决了 GC 过于频繁的性能瓶颈。
TProfiler 最重要的特性就是能够统计出你指定时间段内 JVM 的 topmethod,这些 topmethod 极有可能就是造成你 JVM 性能瓶颈的元凶。这是其他大多数 JVM 调优工具所不具备的,包括 JRockit Mission Control。JRokit 首席开发者 Marcus Hirt 在其私人博客《Low Overhead Method Profiling with Java Mission Control》下的评论中曾明确指出 JRMC 并不支持 TOP 方法的统计:
最后再次向具备开源精神的阿里技术团队致敬~
参考资料
使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码 (jvm性能调优)的更多相关文章
- JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码
本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...
- ifeve.com 南方《JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码》
https://blog.csdn.net/defonds/article/details/52598018 多次拉取 JStack,发现很多线程处于这个状态: at jrockit/vm/Al ...
- 性能优化 | JVM性能调优篇——来自阿里P7的经验总结
VM 调优概述: 性能定义: 吞吐量 - 指不考虑 GC 引起的停顿时间或内存消耗,垃圾收集器能支撑应用达到的最高性能指标. 延迟 - 其度量标准是缩短由于垃圾啊收集引起的停顿时间或者完全消除因垃圾收 ...
- JVM常用调优工具介绍
前言 王子在之前的JVM文章中已经大体上把一些原理性问题说清楚了,今天主要是介绍一些实际进行JVM调优工作的工具和命令,不会深入讲解,因为网上资料很多,篇幅可能不长,但都是实用的内容,小伙伴们有不清楚 ...
- MySQL性能分析、及调优工具使用详解
本文汇总了MySQL DBA日常工作中用到的些工具,方便初学者,也便于自己查阅. 先介绍下基础设施(CPU.IO.网络等)检查的工具: vmstat.sar(sysstat工具包).mpstat.op ...
- JVM 自带性能监测调优工具 (jstack、jstat)及 JVM GC 调优
1. jstack:占用最多资源(CPU 内存)的Java代码 https://www.cnblogs.com/chengJAVA/p/5821218.html https://blog.csdn.n ...
- <JVM下篇:性能监控与调优篇>03-JVM监控及诊断工具-GUI篇
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
- <JVM下篇:性能监控与调优篇>01-概述篇-02-JVM监控及诊断工具-命令行篇
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
- JVM调优工具锦囊
Arthas线上 分析诊断调优工具 以前我们要排查线上问题,通常使用的是jdk自带的调优工具和命令.最常见的就是dump线上日志,然后下载到本地,导入到jvisualvm工具中.这样操作有诸多不变,现 ...
随机推荐
- vos2009如何设置客户自助密码
1. VOS2009 账户管理——>网关管理——>密码:就是客户的自助登陆密码 2. VOS3000 Vos3000里配置密码和自助密码分开 3. 登陆测试 浏览器输入http:// ...
- VC++ MFC类库基础(55讲全)
视频保存在播音员 网盘中内容简介: 本部分是您成为VC++软件工程师必备的阶段,如果您没有任何基础,学习C++能快速让您进入编程领域,建议配合书籍<C++入门经典> 关键词: VC++.V ...
- GitLab 的安装及汉化
系统环境:CentOS7 切记:安装GitLab 时会自动安装GitLab自带的Nginx,为了避免冲突,部署环境时先不要安装Nginx. 官网安装及汉化安装 官网安装最新版GitLab:https: ...
- 【洛谷4717】【模板】快速沃尔什变换(FWT模板)
点此看题面 大致题意: 有两个长度为\(2^n\)的数组\(A,B\),且\(C_i=\sum_{j⊕k==i}A_jB_k\)分别求出当\(⊕\)为\(or,and,xor\)时的\(C\)数组. ...
- 缓存头Cache-Control的含义和使用
首先Cache-Control有哪些特性呢?一个是可缓存性 可缓存性 public: 代表这个http请求返回的内容所经过的任何路径中,包括一些中间的http的代理服务器,以及发出这个请求的客户端浏览 ...
- 2017.9.18 HTMl学习总结----input标签的额type
2.1.3 HTML表单标签与表单设计 (1)表单的组成:文本框(text),密码框(password),多行文本框(Multiline text box). 单选按钮框(Single - rad ...
- 20145238-荆玉茗 《Java程序设计》第9周学习总结
20145238第九周<Java学习笔记> 第十六章 整合数据库 JDBC入门 ·数据库本身是个独立运行的应用程序 ·撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 ...
- Token的概念
转载自:https://ninghao.net/blog/2834 最近了解下基于 Token 的身份验证,跟大伙分享下.很多大型网站也都在用,比如 Facebook,Twitter,Google+, ...
- 第39章 ETH—Lwip以太网通信—零死角玩转STM32-F429系列
第39章 ETH—Lwip以太网通信 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...
- js复习,预编译
注意:函数声明整体提升.变量 声明提升 1.imply global 暗示全局变量:即任何变量,如果变量未声明就赋值,此变量就为全局对象所有 ==> eg: a = 122;==> e ...

