TProfiler使用总结

TProfiler是阿里开源的一个java性能分析工具,实现原理和部署配置可看wiki

关于TProfiler中的以下几个关键配置,官方wiki描述的不是很清楚:

  • startProfTime = 9:00:00 开始profile的时间点
  • endProfTime = 11:00:00 结束profile的时间点
  • eachProfUseTime = 5 profile时间长度(单位秒)
  • eachProfIntervalTime = 50 两次profile的时间间隔(单位秒)

TProfiler对函数调用情况的采样调度是在类 com.taobao.profile.thread.DataDumpThread 中实现的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public void run() {
try {
while (true) {
if (Manager.instance().canDump()) {
Manager.instance().setProfileFlag(true); // 疯炎疯语#1: 打开采样开关
TimeUnit.SECONDS.sleep(eachProfUseTime); // 疯炎疯炎#2: 采样期间,记录函数调用情况
Manager.instance().setProfileFlag(false);
// 等待已开始的End方法执行完成
TimeUnit.MILLISECONDS.sleep(500L); // 疯炎疯语#3: 简单的等待已经Start的函数End返回

dumpProfileData();
}
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从startProfTime开始第一次函数调用情况采样(打开采样开关),此时被关注的函数调用时就会被记录执行信息,
经过eachProfUseTime时间后,采样开关会被关闭(采样停止)。
在采样停止后,线程会等待500毫秒的时间,然后再将采样到的数据输出到文件中,并重置程序中的相关状态。

函数调用情况的采样由类 com.taobao.profile.Profiler 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
com.taobao.profile.Profiler

/**
* 方法开始时调用,采集开始时间
*
* @param methodId
*/
public static void Start(int methodId) {
if (!Manager.instance().canProfile()) {
return;
}
... // 记录采样数据
}

/**
* 方法退出时调用,采集结束时间
*
* @param methodId
*/
public static void End(int methodId) {
if (!Manager.instance().canProfile()) {
return;
}
... // 记录采样数据
}

只有函数执行完之后触发了上边的End调用后,采样的数据才有可能会被输出。
如果一个函数时间执行过长,以致于在采样停止后500毫秒内还没有返回,那么这个函数的调用将无法被记录。
例如:函数执行的时间超过 “eachProfUseTime+500”。

所以,如果你设置的eachProfUseTime时间过短,那么你将无法通过TProfiler来发现执行时间超过这个时间的慢函数,
也就是无法通过TProfiler来发现这样存在严重性能问题的函数。

因此,设置eachProfUseTime时需要估计你的程序中函数可能执行的最慢时间是多少,然后设置一个比这个数稍大的时间。
但是,因为每次eachProfUseTime期间记录的采样信息是在本次采样结束时才输出到文件中的,
如果设置的eachProUseTime过长的话,那么TProfiler对内存的使用会上升,这还取决于采样函数执行的频率高低。

虽然TProfiler存在这样的问题,不过在系统访问压力的不大的情况下(例如在功能测试而非性能测试的时候),
也可以用来分析程序中哪些函数调用的频率比较高,或者平均调用时间比较长,从而做出针对性的调优。

至于 eachProfIntervalTime 则控制了2次采样之间的时间间隔,把这个数调大可以降低对应用程序的性能影响,
但是过大的话则采样数据可能不准。