25

Systrace 的原理、流程及定制

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzI3NzA5MzUxNA%3D%3D&%3Bmid=2664607932&%3Bidx=1&%3Bsn=02f4e4d5d34e7b99c20b5c982c51f0ad
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一、原理和基本流程

Systrace是android性能调试优化的常用工具,它可以收集进程的活动信息,如界面布局、UI渲染、binder通信等;也可以收集内核信息,如cpu调度、IO活动、中断等;这些信息会统一时间轴,在Chrome浏览器中显示出来,非常方便工程师性能调试、优化卡顿等工作。

简易的流程图如下,systrace是基于ftrace实现的,而ftrace 是 Linux 内核中的调试跟踪机制。

J3Iviir.png!web

  1. 首先systrace指定抓取trace的类别等参数,然后触发手机端的/system/bin/atrace 开启对应文件节点的信息记录,接着atrace会读取 ftrace 的缓存,生成只包含ftrace信息的atrace_raw。

  2. Systrace会进一步收集系统的ps、task等信息,这些信息是为了协助解析atrace_raw中的ftrace信息,比如ps信息可以得到进程的名称,而不是难记的pid号。处理后的ftrace信息将和systrace目录下的prefix.html、systrace_trace_viewer.html、suffix.html整合为一体,成为单个的html文件。

  3. 当浏览systrace信息时,Chrome浏览器借助systrace解析器(通过chrome://tracing访问),解析上面生成的trace.html文件,把其中原始的ftrace信息分门别类,再按照时间轴聚合排列,绘制出不同色块,简洁可观的显示在html页面上。

二、具体实现

Systrace是怎么把系统多种多样的信息都整合进ftrace中的呢?请看下图:

VFvU7vZ.png!web

Systrace抓取的trace数据,总体上可以分为两类,一类是Java和Native在用户层发生的函数调用,一类是内核态的事件信息。

用户层的函数调用,其实最终事件记录都是同一个文件节点/sys/kernel/debug/tracing/trace_marker。

此节点允许用户层写入字符串,ftrace会记录该写入操作时的时间戳,当用户在上层调用不同函数时,写入不同的调用信息,比如函数进入和退出分别写入,那么ftrace就可以记录跟踪函数的运行时间。

atrace在处理用户层的多种trace类别时,仅仅是激活不同的TAG,如用户选择了Input类别,则激活ATRACE_TAG_INPUT;选中Graphics则激活ATRACE_TAG_GRAPHICS,记录调用的流程都是一样的,最终都是记录到trace_marker。

内核态的事件信息,则不是统一的,需要激活各自对应的事件节点,让ftrace记录下不同事件的tracepoint。例如激活进程调度信息记录,需要激活如下相关节点:

events/sched/sched_switch/enable

events/sched/sched_wakeup/enable

内核在运行时,根据节点的使能状态,会往ftrace缓冲中打点记录事件。

最终,上述两类事件记录都汇集到同一缓冲中,然后atrace工具会回读抓取,保存下来就是原始的systrace信息。

三、显示定制信息

Systrace的参数设置和使用方法,网络上内容已经不胜枚举,就不再累述。下面讲解一下较少阐述的显示定制信息功能。

一般情况下,默认的systrace各种trace类别已经涵盖了系统的各个方面,足够工程师分析调试了。但某些特定情况下,工程师需要增加自定义的trace类别,并同样集成到systrace中。比如工程师需要观察到内核各个run queue的队列深度,那么他应该怎么做呢?

1.新加定制的trace类别

既然原有的systrace trace不能满足,需要新增一项。可以去frameworks/native/cmds/atrace/atrace.cpp中增加一类category, 如

QJ3yEvv.png!web

2.内核增加对应的tracepoint

Systrace是基于ftrace的,那么上面的类别需要在内核中增加对应节点。

在新建的sched_rq_running event中实现输出新增的trace类别的信息,通过上面的1、2两个步骤,在抓取systrace时选中新建类别kernel_runqueue, 则抓取的trace.html将包含sched_rq_running的信息。

假设新的信息如下:

UjQJnim.png!web

3.显示出sched_rq_running的信息

如果sched_rq_running.html 在 chrome里面打开,我们并没能发现自定义的任何信息显示出来。这个是由于默认的chrome://tracing 解析器并不知道如何解析sched_rq_running的信息。

Systrace能够解析显示出进程调度的sched_wakeup、sched_switch等信息,那是因为chrome://tracing 解析器知道如何解析进程调度信息,如下面格式的内容。

e6BBfe6.jpg!web

但是并不知道如何解析自定义的sched_rq_running信息。

这时候,我们就需要寻根溯源了,我们先找到systrace的生母,谷歌开源项目https://chromium.googlesource.com/catapult。

正是catapult生成了systrace及其解析器的工具。在catapult中,谷歌采用javascript实现了一个跨平台的trace解析工具,我们可以参考tracing/tracing/extras/importer/linux_perf目录下的各种解析器,比如sched_parser.html是用于解析进程调度信息的,power_parser是用于解析cpu频率等信息的,学以致用生成自己定制的sched_rq_running_parser.html。

Catapult的各种解析器,可以理解为先按照trace的类型分类处理,然后加入各个时段的采样值。

如tracing/tracing/extras/importer/linux_perf/power_parser.html

实现了如何解析出cpu频率信息:

<idle>-0     (-----) [001] d.Hb   948.300084: cpu_frequency: state=1344000 cpu_id=2

1)power_parser.html注册了cpu_frequency信息由函数cpuFrequencyEvent处理

2) cpuFrequencyEvent分解cpu_frequency信息

JVbAZjy.png!web

3) 把cpu频率采样值加入Clock Frequency信息栏

2EJfAzN.png!web

在我们加入额外的sched_rq_running_parser.html解析器之后,需要使用tracing/tracing_build/generate_about_tracing_contents.py重新生成about_tracing.html和tracing.js(这里需要改名,使之和about_tracing.html中的script脚本名称相同)。

然后使用about_tracing.html作为新的systrace解析器,代替默认的chrome://tracing,这时再把sched_rq_running.html放进来解析,我们就终于可以看到自定义的systrace信息了。

fiyiiav.png!web

参考文献

1、android源代码

2、catapult源代码

vQviiiA.gif

长按关注

内核工匠微信

Linux 内核黑科技 | 技术文章 | 精选教程


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK