背景
还记得之前我们开发和调试内核,面对内核错综复杂的代码,还有无数条潜在的运行路径,有点茫然不知所措。之前在内核加个代码,一不小心就会造成内核崩溃。
现在好了,谷歌在Android q版本上已经集成好了bcc工具。该工具的加入,对于Android手机开发方面,无论是稳定性还是性能优化工作,都有巨大的效率提升。
我们发现如果会巧妙地运用该工具的话,不仅仅是内核,驾驭整个操作系统的能力会比以前有大大的提升。
bcc工具介绍
简介
bcc全称为(BPF Compiler Collection),bcc工具是一整套基于Linux - ebpf接口开发的工具包。
工具主页:https://github.com/iovisor/bcc
该工具的设计动机是为了媲美之前Solaris系统上的Dtrace工具,做到不仅仅是内核,整个操作系统层面的程序运行行为都可以进行监控跟踪。
该工具包不仅有很多现成已做好的可以用来高效跟踪内核,调试应用程序的ebpf工具,而且还提供了一套基于ebpf接口的快速简易开发环境。
该开发环境对Linux系统的ebpf接口做了二次封装,目的是让ebpf接口对开发者友好并简单易用。
工作原理
BPF是运行在内核态的一种虚拟机语言,bcc工具在用户态通过一些编译器把Python,c语言写的程序编译成BPF目标码,然后通过加载器loader(bcc/perf/iproute2)将BPF目标码通过bpf()系统调用加载到内核当中。
然后在内核的虚拟机里面安全地运行前面用户态定制的各种程序。
辅助Android开发的优点
1: 比现有的性能调试工具强
提供了很多现成的针对内核cpu,内存和存储三大领域进行监控调试的工具。这些工具是基于ebpf接口做的,需要指出的是,跟以前的监控工具(ps, top, vmstat等)相比,
在Android性能监控,稳定性调试领域会有质的提升,下面会介绍的。
2: 比Android平台现有的systrace强
提供了python开发接口,这样可以在ebpf程序中使用到Python强大的各种资源库,比如字典,hash等。可以更方便直观地对监控内核时产生的数据做各种统计处理工作,
比如计算内核某模块性能方面的平均耗时,最大最小耗时,还能绘制出耗时的直方图,这一点systrace是没有的。
还有不需要再费劲加trace语句了,一个工具到手,不需要再修改并编译代码,直接登录到Android系统上,随时内核各个地方都可以监控到。
3: 比kprobe,systemtap强
该工具的工作思路跟kprobe,systemtap一样,可以以钩子函数的方式动态插入内核,对内核进行行为修正和跟踪调试。但是比这两个工具更强悍的一点是使用时会更加安全,bcc工具会保证钩子函数的插入不会给内核带来崩溃,
hung或者其他负面效应。
4: 比Android上的simpleperf强
和simpleperf一样,可以用来对系统做profile跟踪。但是perf工具的缺点是时间计算在用户态才聚合,不如用bcc工具直接用ebpf在内核台聚合显得更加准确性。
另外在程序的offcputime跟踪方面,perf工具会产生过重的overhead,这样产生的性能数据会不准确。而bcc工具进行这方面跟踪时,产生的overhead则比较少了。
估计bcc工具进行Android系统性能跟踪,比systrace跟踪产生的overhead也少。
5: 之前的ftrace, tracepoint, kprobe, uprobe, systemtap和perf工具有的功能优点它都有,而且还做了有效的整合。
所以它集成了以前的这些工具的优点后,不仅可以用来做内核态的跟踪调试,用户态也能派上用场。
6: 简单易学,轻松可以上手
bcc工具提供了方便快捷地ebpf开发环境,甚至c语言不熟练的也可以用来做内核ebpf开发(当然了最好要慎重写代码),因为你编写的程序会被放到沙盒里面,不会对内核有负面影响的。
还有如果是写代码犯了内存越界等错误,在bcc模块插入内核之前,就会被自动检测出来。另外还提供了详细地bcc开发配套学习资料。
现有的ebpf工具优点
现有的ebpf工具都在:https://github.com/iovisor/bcc/tree/master/tools 里面。
下面结合我的性能工作经历,总结了Android开发过程中,最有用的一些bcc工具。介绍如下:
通用方面
argdist
可以用来在系统运行时,动态打印出kernel中任意某个函数(静态函数除外)的入参和出参值。
funclatency
可以用来跟踪显示内核函数运行的耗时状况。可以对整个系统进行trace,也可以对单个进程进行trace。并且函数耗时状况能以直方图的形式显示出来。
syscount
如果想了解整个系统或者单个进程在某段时间内都干了事情,即workload状况,可以用这个工具。
trace
该工具是对内核kprobe接口的增强封装。基本上可以像以前操作kprobe接口一样,来使用这个工具,从而取代prink调试手法,随时随地对进行内核感兴趣的信息进行动态跟踪过滤输出。
也可以完美替代Linux平台传统的strace工具,对系统调用进行跟踪。
cpu方面
cpudist
可以绘制出系统或者某进程的oncputime和offcputime的耗时分布直方图。
可以用来跟踪某进程运行时的task context切换次数。比如用来跟踪zip解压缩线程时,通过输出的task context切换次数,可以知道该线程是否上下文切换频繁。切换频繁的话,肯定会影响到zip解压缩性能。
该工具是通过监控内核里面函数:finish_task_switch,捕捉prev的task_struct信息来做到有效监控的。
offcputime
可以用来进行进程的offcputime解析。通过该工具输出的信息,知道该进程的offcputime耗时原因,耗时最多的在内核什么地方。
比如之前的zip解压缩性能分析用这个工具可以很容易地知道offcputime耗时最多的地方在哪。
llcstat
这个对分析程序执行时的cpu cache miss很有帮助。
存储方面
fileslower
这个工具经过简单改造下,就可以用来解析整个系统或者单独某进程运行时的产生的IO workloader状况。是做了顺序读写 or 随机读写,操作了哪些文件,IO传输的字节数,direct io or buffer io,这些都可以看出来。
biosnoop, biolatency
可以用来跟踪块设备层的IO 请求排队及存储芯片端处理耗时状况。
bsp稳定性方面
criticalstat
有时候在Android系统反应非常缓慢时,可以用该工具对内核的atomic critical sections进行跟踪,输出系统变慢的原因是否是因为spinlock, 抢占被关闭或者处理中断太多。
上面是对各个工具的简单介绍,更详细地使用方法和优点介绍可以到下面网址上看看:
https://github.com/iovisor/bcc/blob/master/tools/XXXX_example.txt
更强的优势
bcc工具提供了一整套简单易用的ebpf开发环境,让开发者根据不同的业务场景,定制出自己的ebpf工具,关键是有了配套工具后,可以大大提升工作效率。
存储性能优化场景举例
我在做androbench跑分性能优化工作时,常常要打开内核ftrace开关,去分析海量的ftrace log,从这些log中提取到当前androbench测试时产生的IO workload状况,从而或者去定位性能问题,或者做性能优化调研。
分析ftrace log太痛苦了。
现在有了ebpf工具,让一切事情变得简单起来。
因为能够最大程度地解析出我们的业务场景产生的IO workload状况,对于解决存储问题,是很有帮助的。现在不需要看ftrace了,直接用我做的ioworkload_analysis和biosnoop工具,
可以很方便地看出来某进程在vfs层, 块设备层和存储bsp层产生的IO workload状况。详细我的另外一篇文档总结:
手机IO workload解析
这样可以很方便地知道存储性能耗时是在文件系统层,块设备层,还是bsp层。