Android P环境 bootchart使用

1. 功能说明

bootchart 是通过采集/proc中的数据,将系统启动过程记录下来,通过host端工具将其解析为可视化图表的工具;

会收集如下信息(code实现很简单,看一眼就清楚了):

  1. CPU 负载:/proc/stat
  2. 磁盘吞吐:/proc/diskstats
  3. 各个进程的启动过程:/proc/$pid/stat
    需要注意,上述bootchart开始录制是在init.rc所以主要分析的是android启动阶段(对于linux来讲则是init进程后的信息);

2. 使用说明

2.1 录制:

android P中已经内置了bootchart工具(data/bootchart目录存在),在存在enabled文件的情况下,在init.rc启动时开始,bootcomplete时结束:

bootchart [start|stop]
Start/stop bootcharting. These are present in the default init.rc files,
but bootcharting is only active if the file /data/bootchart/enabled exists;
otherwise bootchart start/stop are no-ops.

则我们需要做的就是:添加enabled文件,然后重启
adb shell touch /data/bootchart/enabled
adb shell reboot

2.2 工具解析

  1. 使用 grab-bootchart.sh 将上述收集到的log打包压缩:
    • adb push grab-bootchart.sh /sdcard/
    • adb shell “chmod 777 /sdcard/grab-bootchart.sh”
    • adb shell “sh ./sdcard/grab-bootchart.sh”
    • adb pull /sdcard/bootchart.tgz d:\
  2. 使用工具 bootchart.jar 将上述生成的压缩包生成图片
    • 方式1:java -jar ./bootchart.jar ./bootchart.tgz(jar包可以在官网抓取源码编译,也可以在网上找别人编好的)
    • 方式2:在ubuntu上安装标准bootchart工具直接执行即可:bootchart bootchart.tgz(可能需要先安装为sudo apt install pybootchartgui)
  3. 可以使用 compare-bootcharts.py 脚本做前后对比;

ps:这里使用的是bootchart.jar 解析的方式,下载源码 ant编译后使用(源码直接搜压缩包的name:bootchart-0.9.tar.bz2)
这里附上本人build的jar过程以及可用的jar包资源:https://blog.csdn.net/xiaoqiaoq0/article/details/106737886

2.3 示例图片

bootchart
bootchart生成的图片主要对于启动过程中各个service的时间有个直观的了解,并且在做开机时间优化时,可以做个前后对比;

3. Android P 中相关 code

bootchart 的源码以及工具目录:/system/core/init/
code位置

3.1 在init.rc中默认打开和关闭bootchart功能

  1. 打开:
# Start bootcharting as soon as possible after the data partition is
# mounted to collect more data.
mkdir /data/bootchart 0755 shell shell
bootchart start
    
    
static Result<Success> do_bootchart_start() {
    // We don't care about the content, but we do care that /data/bootchart/enabled actually exists.
    std::string start;
    if (!android::base::ReadFileToString("/data/bootchart/enabled", &start)) {
        LOG(VERBOSE) << "Not bootcharting";
        return Success();
    }

    g_bootcharting_thread = new std::thread(bootchart_thread_main);
    return Success();
}
  1. 关闭:
    on property:sys.boot_completed=1
    bootchart stop

3.2 bootchart.cpp源码查看

  1. 入口:参数是start则启动,并且有检测到/data/bootchart/enabled,才会新创建线程取数据;
Result<Success> do_bootchart(const BuiltinArguments& args) {
    if (args[1] == "start") return do_bootchart_start();
    return do_bootchart_stop();
}
//参数为start则调用do_bootchart_start()

static Result<Success> do_bootchart_start() {
    // We don't care about the content, but we do care that /data/bootchart/enabled actually exists.
    std::string start;
    if (!android::base::ReadFileToString("/data/bootchart/enabled", &start)) {
        LOG(VERBOSE) << "Not bootcharting";
        return Success();
    }

    g_bootcharting_thread = new std::thread(bootchart_thread_main);
    return Success();
}

static Result<Success> do_bootchart_stop() {
    if (!g_bootcharting_thread) return Success();

    // Tell the worker thread it's time to quit.
    {
        std::lock_guard<std::mutex> lock(g_bootcharting_finished_mutex);
        g_bootcharting_finished = true;
        g_bootcharting_finished_cv.notify_one();
    }

    g_bootcharting_thread->join();
    delete g_bootcharting_thread;
    g_bootcharting_thread = nullptr;
    return Success();
}

  1. 核心线程,就是把proc下的数据copy了过来
static void bootchart_thread_main() {
  LOG(INFO) << "Bootcharting started";

  // Open log files.
  auto stat_log = fopen_unique("/data/bootchart/proc_stat.log", "we");
  if (!stat_log) return;
  auto proc_log = fopen_unique("/data/bootchart/proc_ps.log", "we");
  if (!proc_log) return;
  auto disk_log = fopen_unique("/data/bootchart/proc_diskstats.log", "we");
  if (!disk_log) return;

  log_header();

  while (true) {
    {
      std::unique_lock<std::mutex> lock(g_bootcharting_finished_mutex);
      g_bootcharting_finished_cv.wait_for(lock, 200ms);
      if (g_bootcharting_finished) break;
    }

    log_file(&*stat_log, "/proc/stat");
    log_file(&*disk_log, "/proc/diskstats");
    log_processes(&*proc_log);
  }

  LOG(INFO) << "Bootcharting finished";
}

3.3 bootchart部分readme介绍

参照/system/core/init中readme,有比较详细的介绍:

Bootcharting
------------
This version of init contains code to perform "bootcharting": generating log
files that can be later processed by the tools provided by <http://www.bootchart.org/>.

On the emulator, use the -bootchart _timeout_ option to boot with bootcharting
activated for _timeout_ seconds.

On a device:

    adb shell 'touch /data/bootchart/enabled'

Don't forget to delete this file when you're done collecting data!

The log files are written to /data/bootchart/. A script is provided to
retrieve them and create a bootchart.tgz file that can be used with the
bootchart command-line utility:

    sudo apt-get install pybootchartgui
    # grab-bootchart.sh uses $ANDROID_SERIAL.
    $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh

One thing to watch for is that the bootchart will show init as if it started
running at 0s. You'll have to look at dmesg to work out when the kernel
actually started init.


Comparing two bootcharts
------------------------
A handy script named compare-bootcharts.py can be used to compare the
start/end time of selected processes. The aforementioned grab-bootchart.sh
will leave a bootchart tarball named bootchart.tgz at /tmp/android-bootchart.
If two such barballs are preserved on the host machine under different
directories, the script can list the timestamps differences. For example:

Usage: system/core/init/compare-bootcharts.py _base-bootchart-dir_ _exp-bootchart-dir_

    process: baseline experiment (delta) - Unit is ms (a jiffy is 10 ms on the system)
    ------------------------------------
    /init: 50 40 (-10)
    /system/bin/surfaceflinger: 4320 4470 (+150)
    /system/bin/bootanimation: 6980 6990 (+10)
    zygote64: 10410 10640 (+230)
    zygote: 10410 10640 (+230)
    system_server: 15350 15150 (-200)
    bootanimation ends at: 33790 31230 (-2560)

基本上前文中记录的内容都已经将这部分readme包含在内了;

4. 附录

  1. android 全部版本都支持么?
    在androidM之前此工具需要重新build打开才能使用,在之后变成现在的样子;
  2. 以前有使用过可以添加参数的bootchart,主要是设置timeout时间,现在不行了?
    从code实现来看,android中内置的工具是不支持时间配置的,不过可以做个简单的处理,去除init.rc中的stop标志,改为手动停止;
  3. linux是否支持此工具?
    这个工具最开始就是设计给到linux使用的,只是android也集成了而已;
  4. 核心网址
描述网址
bootchart官网http://www.bootchart.org/
android源码网站http://androidxref.com/9.0.0_r3/xref/system/core/init/bootchart.cpp
bootchart 源码下载https://sourceforge.net/projects/bootchart/
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值