性能剖析 profiler
- 下面介绍app的性能剖析一些列tools。
- TProfiler
- 淘宝开发的,还是比较好,可以直接剖析app的业务方法。
- 官网很久没更新了,文档细节不全,看下面的实践,应用到最新jdk1.8 run不起来。
- 需要关注实现原理,方便调试与解决问题。
- 关注更新的 https://github.com/mccxj/TProfiler
- 作者自己更新的:https://github.com/andrexuDeveloper/TProfiler
- BTrance
- 非常方便自定义处理script
- 推荐使用
- jvisualvm
- JDK 自带的tools,难用。 http://www.51testing.com/html/38/n-3724238.html
-
Perf4J
-
MyPerf4J
- JProfile
- 一个收费的性能剖析工具很强大,喜欢图像界面的朋友自己去试。
- https://www.cnblogs.com/AmilyWilly/p/7272160.html?utm_source=itdadao&utm_medium=referral
- 所有的Profile工具都依赖instrument,ASM这两种技术,建议先浏览下它们的原理。
Java性能监控系列 [java.lang.instrument]
-
java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态,替换和修改类定义等。 Java SE5中使用JVM TI替代了JVM PI和JVM DI。提供一套代理机制,支持独立于JVM应用程序之外的程序以代理的方式连接和访问JVM。Instrumentation 的最大作用就是类定义的动态改变和操作。在 Java SE 5 及其后续版本当中,开发者可以在一个普通 Java 程序(带有 main 函数的 Java 类)运行时,通过 – javaagent 参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动 Instrumentation 的代理程序
java -javaagent:agent_jar_path[=options] java_app_name
-
agentmain方式
- Java SE6开始,提供了在应用程序的VM启动后在动态添加代理的方式,即agentmain方式。 与Permain类似,agent方式同样需要提供一个agent jar,并且这个jar需要满足:
- 在manifest中指定Agent-Class属性,值为代理类全路径
- 代理类需要提供public static void agentmain(String args, Instrumentation inst)或public static void agentmain(String args)方法。并且再二者同时存在时以前者优先。args和inst和premain中的一致。
- 不过如此设计的再运行时进行代理有个问题——如何在应用程序启动之后再开启代理程序呢? JDK6中提供了Java Tools API,其中Attach API可以满足这个需求。
TProfiler原理
- 网络上对TProfiler原理分析:https://blog.csdn.net/y461517142/article/details/26269529
TProfiler的问题
- 参考了老旧版本的TProfiler使用文档,就是跑不出数据,tprofiler.log打印=号。
- 我们分析下为什么只是打印等号。DataDumpThread.dumpProfileData,DataDumpThread是控制打印采集数据的Thread,Profiler.threadProfile是已线程为单位,存储采集数据的容器。dumpProfileData就是输出采集数据到tprofiler.log。看完下面的代码应该明白就是没有采集数据。所以打印只有"=";
- =号是eachProfIntervalTime 是每次间隔导出Profile数据的输出分隔符。
private void dumpProfileData() {
ThreadData[] threadData = Profiler.threadProfile;
for (int index = 0; index < threadData.length; index++) {
ThreadData profilerData = threadData[index];
if (profilerData == null) {
continue;
}
ProfStack<long[]> profile = profilerData.profileData;
while (profile.size() > 0) {
long[] data = profile.pop();
StringBuilder sb = new StringBuilder();
// thread id
sb.append(index);
sb.append('\t');
// stack number
sb.append(data[1]);
sb.append('\t');
// method id
sb.append(data[0]);
sb.append('\t');
// use time
sb.append(data[2]);
sb.append('\n');
fileWriter.append(sb.toString());
}
fileWriter.flushAppend();
profilerData.clear();
}
fileWriter.append("=\n");
fileWriter.flushAppend();
}
- 我们应该把目光转移到,是否加载method前后植入字节吗。
- 还是先看下大神写的TProfile 实现分析吧,https://blog.csdn.net/y461517142/article/details/26269529
- com.taobao.profile.Profiler Start,End方法就是APP每个业务方法前后需要编织的代码。
- 先介绍idea debug agent方法的。
- VM option 设置需要加载agent
- 选择main类,点击debug,简单设置可以直接在断点处,将suspend改成Thread
- 在Start,End方法里添加debug日志。我屏蔽了transform4Mysql的注入,貌似有些问题。
- 在pom文件加入下面:
<dependency>
<groupId>com.taobao</groupId>
<artifactId>tprofiler</artifactId>
<version>1.0.1</version>
</dependency>
- 在idea的ApplicaitonMain启动起来。TProfile需要一定的流量才会有profile分析,笔者采用kafka消费服务,流量不成问题。
- DataDumpThread的run在开启profile后,在eachProfUseTime秒后会关闭,如果你在debug状态,或者调用第三方服务期间应该把eachProfUseTime设置长点,这是笔者踩的坑。
DataDumpThread
public void run() {
try {
while (true) {
if (Manager.instance().canDump()) {
Manager.instance().setProfileFlag(true);
TimeUnit.SECONDS.sleep(eachProfUseTime);
Manager.instance().setProfileFlag(false);
// 等待已开始的End方法执行完成
TimeUnit.MILLISECONDS.sleep(500L);
dumpProfileData();
dumpMysqlData();
}
TimeUnit.SECONDS.sleep(eachProfIntervalTime);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
Manager.instance().setProfileFlag(false);
if (fileWriter != null) {
fileWriter.closeFile();
}
// 等待已开始的End方法执行完成
try {
TimeUnit.MILLISECONDS.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
Profiler.clearData();
}
}
TProfiler实践
- 一些client使用方法参考:https://blog.csdn.net/defonds/article/details/52605670
- profile结果
=
27 0 582 5
27 1 1505 3
27 2 581 3
27 3 127 3
27 0 158 1099
27 1 165 15
27 1 162 1081
27 0 419 13
27 0 348 5258
27 1 346 487
27 1 346 481
27 1 346 487
27 1 346 483
27 1 346 483
27 1 346 482
27 1 346 488
27 1 346 440
27 1 346 365
27 1 346 1041
27 0 342 58
27 1 344 58
27 2 1101 6
27 0 973 2
27 0 560 192
27 1 879 191
27 2 559 191
27 3 118 191
27 0 571 3
27 1 736 2
27 2 570 2
27 3 125 2
192 0 382 475
192 1 378 414
=
- 公司有apm agent,TProfile agent 能一起应用吗?
-
笔者已测试过了可以添加多个javaagent,如下:
java -javaagent:/Users/andrexu/test/Agent-infra-alarm-sentry-exec/Agent/agent-bootstrap.jar -javaagent:/Users/andrexu/test/lib/tprofiler-1.0.1.jar -Dprofile.properties=/Users/andrexu/test/lib/profile.properties -jar infra-alarm-sentry-exec.jar
参考文档
- 请使用我的master 分支 https://github.com/andrexuDeveloper/TProfiler