【全网首发】手机性能优化工具的使用思路比较原创
作者简介
李晓辉(微信名:小辉),一线码农,有多年丰富嵌入式操作系统开发工作经验。先后在南大富士通,某手机大厂和初创小公司任软件工程师,系统架构师等职务。对嵌入式系统开发和os性能优化工作很熟悉。
背景
借助或者研发好的分析工具对系统工程师的工作效率提升很重要
系统分析优化工程师的工作职责跟app工程师有很大的不同,系统工程师需要具备cover住整个系统的能力。
现在的嵌入式系统比如android的代码量有几千万行,而且系统架构搞得相当庞大复杂。搞系统性能优化的,嵌入式产品比如手机上随意出现个性能问题,可能都需要从fwk层(java代码)一直搞到内核底层,然后到存储芯片层也需要熟悉(如果是搞存储性能优化的话)。
所以系统工程师,尤其是搞性能问题解决优化的,需要调研关注的代码量相当庞大,不止linux内核。
所以搞系统性能工作的,往往需要借助或者研发一些高效的工具来提升工作效率。好的工具对于性能工程师的工作质量提升是非常重要的。
嵌入式平台性能工作特点
嵌入式行业更关注系统性能工作
嵌入式行业和互联网行业在性能问题解决优化方面还是有着很大的不同,嵌入式行业比如手机产品,可以说是比互联网公司更关注性能问题的解决优化。
因为互联网公司出性能问题了,可以搞内存或者存储设备扩容,性能不好,再多加块内存条就解决了。
手机产品出厂后,内存和存储容量有限已经定死了,但是随着移动互联网时代的到来,各种app在不断消耗争用着手机的cpu/io/内存资源,所以会产生很多性能问题,会比互联网公司更影响用户体验。
手机系统性能方面工作的关注点
嵌入式行业和互联网行业在性能问题的关注点上也有不同。
1) 嵌入式行业关注点:
嵌入式行业,比如手机很关注特定进程/线程(比如前台app)的工作时延。性能问题的解决和优化,往往围绕着如何减少特定进程/线程的工作时延,使其运行更快一些。这样前台app运行快了,用户操作手机时才不会感到有卡顿。
手机产品里面有相当多的一部分性能工作是做这样事情:
跑特定的性能测试程序(比如手机zip解压缩或者io跑分),需要调查为啥测试机:高通某机型比对比机: mtk某机型慢了2秒,慢2秒是系统的哪部分原因导致的。
如果是软件原因,需要精确到具体是测试机和对比机的android系统(几千万行代码)的哪部分代码差异导致的性能慢2秒。
如果是硬件原因,需要知道高通和mtk机型的哪部分硬件差异导致的性能慢2秒。
2)互联网行业关注点:
互联网行业,由于系统工程师的角色是优化后台服务器集群,所以搞性能工作,首要关注点是查找整个系统的性能瓶颈在哪里,提高整个系统运行任务的吞吐量。优化局部特定重要进程工作时延方面,没有嵌入式行业那么重要迫切。
嵌入式平台性能工具运用特点
由于上面讲了手机和互联网公司在性能工作方面的不同,手机性能优化更关注前台app的工作时延,所以嵌入式平台上性能工具运用也和互联网公司有不同。
会linux下那些经典性能排查工具仅仅是最基本的要求
一谈到操作系统比如linux上的性能问题分析,大家首先会想到要灵活运用各种shell命令和开源性能分析工具(比如free, top, df, vmstat, iostat, strace等)。
典型的就是那个美国性能大师brendangregg的那篇经典博文<十分钟帮你排查出性能问题在哪里>中介绍的性能工具分析问题思路。
但这些都是互联网服务器行业的性能分析套路。手机产品上会运用上面提的这些linux性能分析工具只是最基本的要求,仅仅会这些工具还不能满足嵌入式产品的高性能质量需求。
比如上文提的慢2秒,如果要调查其中原因,会上面提的基本性能排查工具还是查不出慢2秒的原因的。
嵌入式平台(比如手机)性能工具运用思路介绍
1、对于复现概率比较大或者必现的性能问题的调查思路
比如针对前台app卡顿或者操作性能慢这样问题的分析:
1> 首先会用到systrace排查性能问题出现的大致范围地方
systrace就是嵌入式系统性能分析中的倚天剑。
最常用的而且首要分析工具会是systrace,用它来做系统整体分析,也是对性能问题的初步分析。
看看比如上面提的慢2秒这种性能问题大致出现在什么地方,是出在测试机的on cputime还是off cputime耗时。
如果是oncputime耗时,需要关注是cpu频率不够,还是有后台进程干扰,或者是cpu调度问题(都跑大核或者小核)造成的。
或者还需要关注测试程序本身,测试程序自身在很多关键地方代码都加的有systrace tag,这样比较容易看到是哪部分代码导致的耗时。
如果是offcputime耗时,那么需要看看是runable状态耗时,还是D状态耗时。
runable耗时可能是cpu上排队进程太多导致,或者kswapd过于活跃(内存原因)。
D状态耗时可以通过进入D状态前的代码位置,来判断出是锁同步,或者内存/io原因导致的。
这个也可以通过测试程序本身加的关键地方systrace tag,来看出offcputime耗时出现在程序的哪个代码阶段。
总之,上面说的这些导致出性能问题的因素都可以通过systrace看出来,通过systrace可以首先看出性能问题的大致出现范围。
2> 其次会用到simpleperf排查性能问题出现原因对应的详细代码
simpleperf则是性能分析中的屠龙刀。
光systrace工具还不够的,systrace只能看到横向性能分析结果。
比如通过对比测试机和对比机的systrace,看到了慢2秒的性能问题是由于测试机频繁调用了内核里面misc_open函数,而导致耗时的。
这时需要查出为啥测试机会频繁调用misc_open,这就要分析测试程序自身的业务逻辑代码了。
如果分析测试程序涉及代码量很庞大的话,手动分析耗时,往往就要借助simpleperf(嵌入式平台上的perf工具)进行纵向性能分析了。
用simpleperf对测试程序的oncputime/offcputime进行采样,并且附带采样点的栈回溯信息,最后以火焰图形式输出,这样很容易看到是哪部分上层业务代码导致的底层内核的misc_open被频繁带用。
3> 对于存储性能问题还会用到ftrace log分析
如果该性能问题大概率是跟手机存储io性能相关的,那么上面两个排查方法还不一定能看出问题真正原因所在。
因为即使是simpleperf,也只能看出测试程序涉及的各个地方代码的整体耗时分布,类似火焰图效果。但是某些热点函数为什么这么耗时,还需要进一步观测它的参数变化。
如果是内核io方面的热点函数耗时,这个时候就需要开启内核文件系统层,块设备层相关的trace event跟踪事件,同时需要对内核存储io栈代码比较熟悉才行。
这样会进一步详细看出类似上面的测试机慢2秒这种性能问题原因。
这方面解过的问题有:
1) 某测试机Q版本比P版本zip解压缩耗时慢3秒,最后发现是Q版本的文件预读窗口过小(和p版本相比)导致。
2) 某测试机连接u盘,首次播放u盘高清视频卡住必现问题,最后查到是块设备层usbotg设备设置的参数不对,导致bio合并失败引起的性能问题。
4> bcc工具也有很大的用武之地
在实际应用上面提的工具解决性能问题时,会发现还存在一些缺陷和改进:
(1) 存储IO跑分差这类性能问题,用上面提的这些工具都不合适,还是用bcc工具最合适
因为内核io栈分文件系统层,块设备层和存储芯片层。每个层面代码差异都会影响io跑分。
而实际测试场景下,经常会有测试机和对比机的要么文件系统层不一样,要么块设备层代码或者存储芯片有差异,就是这些差异导致的测试机io跑分性能不如对比机。
所以针对这类性能问题,最好用bcc工具,在具体跑分时,能够对上面内核io栈的每个层面的处理耗时数据进行归纳统计,能够计算出每个层面的总耗时,平均耗时还有最大最小耗时等。
这样便能看出来是文件系统层耗时引起的跑分性能差,还是块设备层,或者存储芯片层引起的。
systrace和ftrace log都做不到,perf工具只能在用户态对数据做归纳处理,内核态只是采样或者trace event事件触发收集性能信息直接汇报给用户态。
io跑分需要在内核态直接对性能数据做第一手的归纳处理,这个就是bcc工具最大用武之地了。
怎么用bcc工具处理io跑分类性能问题的,可以看看我的那个存储性能工具介绍文章。
(2) 对内核热点函数进行长时间的性能监控时,perf工具会产生比较大的数据量和性能负荷,并且会有丢事件发生
这个是perf工具的自身缺陷问题,内核态不能做太多的数据过滤和归纳处理,只能采样返回到用户态做数据聚合处理。
自己在调查相机gpu内存泄漏问题时,用simpleperf监控过内核gpu内存分配释放事件活动,内核gpu分配/释放事件是很频繁的,每秒几千次都有。
如果用perf监控时间长,产生的perf.data监控log体积会特别大,达到1G多。并且还会有丢事件发生。
这个时候就需要有一种工具,能够在内核态对性能数据做些业务逻辑方面的过滤,或者直接内核态对数据做归纳处理,最后返回到用户态的只是处理过的精简版的结论数据。
这样便会大大减轻性能监控任务自身产生的负荷,降低对手机使用的影响。
这个工具目前最好的就是ebpf/bcc工具了。
(3)bcc工具还有更大的好处
之前我推广我的存储io跑分工具时,有人曾提疑问,bcc工具操作比较麻烦,还得新增内核配置项,还得望手机data分区push一整套200多M的bcc工具集。
为啥这么费劲,为啥不直接在内核io栈上加些trace event,不也能看出性能问题出现原因吗。
我后来想了想,答复是:
其实也可以不用bcc工具啊,如果直接加trace event,还是不行的,那么产生的数据量大,而且都是raw数据,没有归纳处理。
最好用内核模块+kprobe接口/新增trace event事件,这样自己在内核模块里面手动加代码,计算或者过滤监控数据的处理耗时,在io跑分前,加载该模块开启监控工作。
但是这样有点问题,针对io跑分做个性能监控工具,然后有其他方面性能监控需求时,可能需要再搞个另外的监控程序。这样时间长了,性能监控程序搞的种类多了,还得解决代码复用性问题,版本兼容工作。
这样下来性能监控工作就会开发效率低了。
bcc工具最大好处是:
提供了一整套的性能监控框架,可以使得很方便地快速定制和开发自己的性能监控工具,尤其是自己面临很多方面的性能监控工作需求时。
上面提的那些数据归纳处理过滤,其实bcc工具里面有现成的成熟接口可以调用。
有了bcc工具那个成熟的性能监控框架,开发者可以专注于自己的性能监控业务逻辑开发,不需要理会什么内核代码编写一些坑坑洼洼的工作。
5> 其他的分析方法
除了用上面性能分析工具外,还可以通过用户反馈的log,来看性能问题出现原因的。这些都放到偶现性能问题解决里面来说了。
2、偶现性能问题的调查思路
1>利用Linux内核的task delay数据统计可以看出用户手机端的性能问题是由于cpu,内存还是io三大因素中哪个导致。
这个开启后对用户的嵌入式产品产生的性能负荷很小的,不影响其运行的,但只能看出大致性能原因在哪里。
2>在容易出性能问题的层面加些性能打点log,进一步辅助排查性能问题出在哪里。前提是不影响嵌入式产品正常运行。