OpenHarmony上使用火焰图
作者:陈迅
一般来说,我们发现程序卡顿,排除其他程序问题和硬件问题,那一定是自身程序中某个位置运行时,消耗的时间过长导致。
性能问题分析方式
要找到耗时的代码段,才能有针对性的进行优化,那第一个问题就是如何找到耗时的代码段。
首先我们能想到,在程序中可能存在问题的地方,加入计算时间差的代码,然后不断缩小范围,找到最终耗时的点。includesystime。huint64tGetTimeStampUS(){structtimevaltv;gettimeofday(tv,NULL);returntv。tvsec1000000tv。tvusec;}。。。。。voidFuncA(){uint64tt1GetTimeStampUS();FuncB();uint64tt2GetTimeStampUS();FuncC();uint64tt3GetTimeStampUS();printf(FuncBcost:llu,FuncCcost:llu,t2t1,t3t2);}
这种方式最终也能解决问题,但是会有一些缺点:
对于大型项目来说,要经过大量的【编译,执行验证,添加代码】迭代,消耗大量时间。
排查到问题后,需要把测试代码删除,下次排查时又要重新添加代码。
通过查看文本log方式分析,不直观。
下面我们看看如何使用bytrace来分析问题。
在OpenHarmony中使用Bytrace
在BUILD。gn中添加对bytrace的依赖:externaldeps〔bytracestandard:bytracecore,〕
添加头文件:includebytrace。h
添加打点代码:voidFuncA(){StartTrace(BYTRACETAGGRAPHICAGP,funcB);funcB();FinishTrace(BYTRACETAGGRAPHICAGP);}
代码部分完成了,编译更新到开发板,然后使用下面命令来抓取log:hdcshellbytracet10b8192graphiclogslog。ftrace
参数说明:
t10:从运行命令行开始,抓取10秒时间(非必要参数,默认5秒)
b8192:使用8192kb(8M)内存来缓存数据(非必要参数,默认2048kb)
graphic:抓取graphic类型的trace,对应上面代码中的BYTRACETAGGRAPHICAGP
最后把抓取的结果保存到log。ftrace这个文件中(文件后缀名非限定,txt也行),通过文本编辑器打开查看。
到目前为止,看起来跟加入时间差代码的方式差不多,还是打点看log,接着往下看。
优化打点
把bytrace的打点代码封装起来,xtrace。h:includestringincludebytrace。hclassXTrace{public:XTrace(std::stringfname);XTrace();};
xtrace。cpp:XTrace::XTrace(std::stringfname){StartTrace(BYTRACETAGZCAMERA,fname);}XTrace::XTrace(){FinishTrace(BYTRACETAGZCAMERA);}
这样我们用起来就更方便了:voidFuncB(){XTracetrace1(func);}voidFuncA(){{XTracetrace1(func);FuncB();{XTracetrace2(func);FuncC();}}
函数开始,创建XTrace对象时,构造函数调用StartTrace。函数结束或离开作用域,栈中的对象会自动释放,析构函数调用FinishTrace。
当然这种方式也可以用于时间差打点。
可视化看log
链接如下:https:ui。perfetto。dev
这个网站需要科学方法访问,首次访问后有了缓存,后续就可以离线访问了。
我这边把网页保存下来了,在本地开web服务,通过127。0。0。1也可以使用。
首先点击左上角Opentracefile打开log。ftrace,右边会显示出函数调用的火焰图,点击其中一个函数,在下方可以看到准确的执行时间。
基本操作:键盘w,s:时间轴缩放键盘a,d:左右移动
可视化看时间轴就非常直观了,横条越长,消耗时间越多。
OpenHarmony对bytrace的集成
我们在OpenHarmony使用bytrace,除了以上的便利以外,最重要的是OpenHarmony的代码中已经大量使用了bytrace。
下面是我整理的已经集成bytrace的模块:
对于以上模块的性能问题,我们就能直接使用对应tag来抓取。
其他
对于一个较大的模块代码,我们需要理解他的执行流程,函数调用关系,会比较头疼。
所以我编写了一个脚本,扫描所有的。cpp文件,在所有函数开头自动添加:XTracexxx(func);
在可视化界面分析log,可以清晰的看到函数执行的,不同的线程,函数的调用栈,能快速的梳理代码的执行流程。
第四点中的图,是我对foundationaceaceengineframeworks这个目录下2000个左右cpp文件中的函数全部添加XTrace后,得到的应用启动流程火焰图。