今天和同事调试一个Gallery的动画性能问题。一上来还是老套路,上systrace。可是systrace并没有提供足够多的信息,只能看到从dispatchInputEvent()到最后的draw()花去了几百毫秒。于是改用traceview,意外地发现android sdk中自带了一个名叫dmtracedump的工具,配合traceview一起使用,功能强大且使用方便,可以帮助迅速地定位性能问题。
传统的traceview界面包括两个panel, timeline panel和profile panel。timeline 按照时间轴显示出所有的函数调用,profile panel按照函数花费的时间进行排列。
traceview本身提供了丰富的调试信息,包括各个函数的执行次数,时间,以及函数之间的调用关系。只是profile panel的排列方式比较单一,于是程序员经常需要在函数之间反复的跳转,比较,寻找导致程序性能低下的真正元凶。好在,Android SDK提供了dmtracedump的工具,从traceview中导出其他格式的报告。
生成HTML报告
dmtracedump可以将trace转换成html格式。首先在/tmp目录下找到traceview生成的trace文件,然后使用dmtracedump生成html报告
$> <path_to_android_sdk>/tools/dmtracedump -h /tmp/ddmsXXXXXX.trace > output.html
在html的report中,dmtracedump生成了4个表格,
Exclusive profile: 按照函数“自己”(去除被它调用的其他函数的执行时间)所执行的时间进行排列。
Inclusive profile: 这个和traceview中profile panel的原始的排列方式是一样的。
Class profile: 按照类(的函数成员)执行时间进行排列。统计时间按Exclusive time计算
Method profile: 按照函数的执行时间排列,包括native的函数,统计时间按Exclusive time计算
在这个练习中,我们可以很快地发现BitmapFactory.nativeDecodeStream(在Exclusive profile中排在第一位)被不必要地多次执行,导致了在动画播放的前段造成卡顿。
生成调用关系图谱
除了HTML report,dmtracedump也支持生成函数调用关系的图谱。
$> <path_to_android_sdk>/tools/dmtracedump -g /tmp/output.png /tmp/ddmsXXXXXX.trace
如果在执行过程中遇到问题,可以尝试通过安装graphviz解决
$> sudo apt-get install graphviz
在生成的结果中,每个函数的表达方式为:
[inclusive_time_rank]function_name(total_inclusive_time, total_exclusive_time, execute_times)