Jollen 的 Android Booting 解析, #3: 製作 Android Bootchart

jollen 發表於 August 3, 2010 11:15 AM

前一則日記提到的 Bootchart 是典型的開機量測工具,主要能進行開機過程以及開機時間的量測。由於 Bootchart 的原理是取代 init process 或是內建在 init process 裡,所以只能取得 initial script 的開機過程報告。不過,這已經很有幫助了。

關於 Android Bootchart

以下是一份使用 Bootchart 所製作的 Android 開機流程圖。過去有一些以 C 重寫 Bootchart 的專案,而 Android 也有一份 C re-implementation,放置於 [system/core/init/bootchart.c]。由此可知,Android init 已經內建一份 C re-implement 的 Bootchart。

android bootchart
圖一:使用 Bootchart 製作的 Android 開機流程圖

以下說明如何製作 Android Bootchart。

1. 編譯 Android Bootchart

Android 的 init process 雖然已內建 Bootchart,但編譯系統預設並不會將 Bootchart 編譯至 init 裡。因此,需要重新編譯 init.c 才能加入 Bootchart:

jollen@android:~/try/mokoid_elcair-20100511$ touch system/core/init/init.c
jollen@android:~/try/mokoid_elcair-20100511$ . build/envsetup.sh 
including vendor/aosp/vendorsetup.sh
jollen@android:~/try/mokoid_elcair-20100511$ m INIT_BOOTCHART=true PRODUCT-dma6410xp-eng -j 8
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.1-update1
TARGET_PRODUCT=dma6410xp
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=ECLAIR
============================================

完成後,使用 Android 模擬器開啟製作好的 image file。

2. 設定 Bootchart Timeout 時間

要讓 Bootchart 在「下一次開機」時開始運作,以進行取樣並紀錄開機過程,需要指定 Timeout 時間:

$ adb shell 'echo 120 > /data/bootchart-start'
$ adb shell 'mkdir /data/bootchart'

重新啟動模擬器。對 /data 目錄進行的變動,「可以」寫回 userdata.img 裡。這裡指定 Timeout 時間為 '120' 秒;實際測試時,可以視情況自由調整。

3. 取得 Bootchart 紀錄檔

在 Android 系統裡的 /data/bootchart 取得開機紀錄檔:

linux@android:~/android/mokoid$ adb shell
# ls -l /data/bootchart
-rw-rw-rw- root     root          389 2010-07-28 11:06 header
-rw-r--r-- root     root            0 2010-07-28 11:06 kernel_pacct
-rwxr-xr-x root     root       589824 2010-07-28 11:08 proc_diskstats.log
-rwxr-xr-x root     root      2293760 2010-07-28 11:08 proc_ps.log
-rwxr-xr-x root     root       196608 2010-07-28 11:07 proc_stat.log
# 

接下來,必須取出這幾個檔案,並製作成漂亮的統計圖檔。貼心的 Android 已經幫我們準備好一個 script 檔了,因此,先切換到 system/core/init 目錄下,直接執行 grab-bootchart.sh:

linux@android:~/android/mokoid$ cd system/core/init/
linux@android:~/android/mokoid/system/core/init$ ./grab-bootchart.sh 
7 KB/s (389 bytes in 0.048s)
1439 KB/s (405771 bytes in 0.275s)
2014 KB/s (3861856 bytes in 1.872s)
1936 KB/s (979391 bytes in 0.493s)
look at bootchart.tgz

最後的統計報告存放於 /tmp/android-bootchart/bootchart.tgz。

4. 製作精美 Bootchart 報告

Bootchart 包含一個以 Java 寫成的圖表製作工具,因此,還是必須取得原始的 Bootchart 套件。在 Ubuntu 環境下,可以用 apt 直接安裝:

$ sudo apt-get install bootchart

接著,將 bootchart.tgz 製作成圖檔:

$ java -jar /usr/share/bootchart/bootchart.jar /tmp/android-bootchart/bootchart.tgz
Parsing /tmp/android-bootchart/bootchart.tgz
Wrote image: ./bootchart.png

最後,得到如圖一的精美報告。接下來的工作,就是對 Bootchart 的內容進行分析。

延伸閱讀

2010.07.28: Jollen 的 Android Booting 解析, #1: 整體開機流程
2010.07.29: Jollen 的 Android Booting 解析, #2: 關於開機的評估
分享您的 Android Bootchart 筆記:Build Android Bootchart

讀者留言 (11)

  • Dig 於 August 11, 2010 14:08:


    For ubuntu 10.04, "bootchart" is a tool written in python. You should do "sudo apt-get install pybootchartgui", and run "bootchart /tmp/android-bootchart/" to get a pretty png file

  • jollen 於 September 18, 2010 14:11:

    Thank you. It works pretty well.

  • banyao 於 September 25, 2010 16:06:

    请问:在ubuntu 10.04中找不到/usr/share/bootchart/bootchart.jar文件。按照Dig的方法出现如下:
    parsing './bootchart.tgz'
    parsing 'header'
    parsing 'proc_stat.log'
    parsing 'proc_ps.log'
    warning: no parent for pid '2' with ppid '0'
    parsing 'proc_diskstats.log'
    parsing 'kernel_pacct'
    merged 0 logger processes
    pruned 44 process, 0 exploders, 2 threads, and 0 runs
    False
    Traceback (most recent call last):
    File "/usr/bin/bootchart", line 23, in
    sys.exit(main())
    File "/usr/lib/pymodules/python2.6/pybootchartgui/main.py", line 137, in main
    render()
    File "/usr/lib/pymodules/python2.6/pybootchartgui/main.py", line 128, in render
    batch.render(writer, res, options, filename)
    File "/usr/lib/pymodules/python2.6/pybootchartgui/batch.py", line 41, in render
    draw.render(ctx, options, *res)
    File "/usr/lib/pymodules/python2.6/pybootchartgui/draw.py", line 282, in render
    draw_chart(ctx, IO_COLOR, True, chart_rect, [(sample.time, sample.util) for sample in disk_stats], proc_tree)
    File "/usr/lib/pymodules/python2.6/pybootchartgui/draw.py", line 201, in draw_chart
    yscale = float(chart_bounds[3]) / max(y for (x,y) in data)
    ZeroDivisionError: float division
    请问怎么解决呢?

  • cheyanshuang 於 May 5, 2011 15:14:

    The same error as banyao. how to slove this problem?

  • loren 於 May 20, 2011 17:27:

    On my ubuntu 10.10, error log...

    /usr/lib/pymodules/python2.7/gtk-2.0/gtk/__init__.py:57: GtkWarning: could not open display
    warnings.warn(str(e), _gtk.Warning)
    parsing '/tmp/android-bootchart/bootchart.tgz'
    parsing 'header'
    parsing 'proc_stat.log'
    parsing 'proc_ps.log'
    Traceback (most recent call last):
    File "/usr/bin/bootchart", line 23, in
    sys.exit(main())
    File "/usr/lib/pymodules/python2.7/pybootchartgui/main.py", line 111, in main
    options.crop_after, options.annotate)
    File "/usr/lib/pymodules/python2.7/pybootchartgui/parsing.py", line 248, in parse
    state = parse_paths(writer, ParserState(), paths)
    File "/usr/lib/pymodules/python2.7/pybootchartgui/parsing.py", line 225, in parse_paths
    state = parse_paths(writer, state, files)
    File "/usr/lib/pymodules/python2.7/pybootchartgui/parsing.py", line 237, in parse_paths
    state = _do_parse(writer, state, name, tf.extractfile(name))
    File "/usr/lib/pymodules/python2.7/pybootchartgui/parsing.py", line 201, in _do_parse
    state.ps_stats = _parse_proc_ps_log(writer, file)
    File "/usr/lib/pymodules/python2.7/pybootchartgui/parsing.py", line 88, in _parse_proc_ps_log
    userCpuLoad, sysCpuLoad = process.calc_load(userCpu, sysCpu, time - ltime)
    File "/usr/lib/pymodules/python2.7/pybootchartgui/samples.py", line 83, in calc_load
    userCpuLoad = float(userCpu - self.last_user_cpu_time) / interval
    ZeroDivisionError: float division by zero

  • jay 於 May 25, 2011 16:20:

    On my ubuntu 10.04, error log.

    jayjqchen@ubuntu:~/Documents$ pybootchartgui -f png bootchart.tgz
    parsing 'bootchart.tgz'
    parsing '.'
    parsing './header'
    parsing './kernel_pacct'
    parsing './proc_diskstats.log'
    parsing './proc_ps.log'
    parsing './proc_stat.log'
    Parse error: empty state: 'bootchart.tgz' does not contain a valid bootchart

    jayjqchen@ubuntu:~/Documents$ java -jar /usr/share/bootchart/bootchart.jar bootchart.tgz
    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/compress/archivers/tar/TarInputStream
    Caused by: java.lang.ClassNotFoundException: org.apache.commons.compress.archivers.tar.TarInputStream
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    Could not find the main class: org.bootchart.Main. Program will exit.

  • jay 於 May 25, 2011 16:22:

    If somebody know the reasons, please let me know.
    Thank you.

    ---jay

    jay.chenjq@qq.com

  • cheyanshuang 於 June 7, 2011 14:47:

    parsing './bootchart.tgz'
    parsing 'header'
    parsing 'proc_stat.log'
    parsing 'proc_ps.log'
    warning: no parent for pid '2' with ppid '0'
    parsing 'proc_diskstats.log'
    parsing 'kernel_pacct'
    merged 0 logger processes
    pruned 44 process, 0 exploders, 2 threads, and 0 runs
    False
    Traceback (most recent call last):
    File "/usr/bin/bootchart", line 23, in
    sys.exit(main())
    File "/usr/lib/pymodules/python2.6/pybootchartgui/main.py", line 137, in main
    render()
    File "/usr/lib/pymodules/python2.6/pybootchartgui/main.py", line 128, in render
    batch.render(writer, res, options, filename)
    File "/usr/lib/pymodules/python2.6/pybootchartgui/batch.py", line 41, in render
    draw.render(ctx, options, *res)
    File "/usr/lib/pymodules/python2.6/pybootchartgui/draw.py", line 282, in render
    draw_chart(ctx, IO_COLOR, True, chart_rect, [(sample.time, sample.util) for sample in disk_stats], proc_tree)
    File "/usr/lib/pymodules/python2.6/pybootchartgui/draw.py", line 201, in draw_chart
    yscale = float(chart_bounds[3]) / max(y for (x,y) in data)
    ZeroDivisionError: float division
    问题已解决,解决办法如下:
    1、将已安装bootchart工具卸载:$sudo apt-get autoremove bootchart
    2、然后安装自主下载.deb文件,自主下载.deb安装包,下载地址http://packages.ubuntu.com/dapper/admin/bootchart
    3、安装.deb文件,不要再输入命令sudo apt-get install bootchart命令,最新版本bootchart工具有问题,安装不全。

  • djstava 於 February 3, 2012 16:44:

    我也碰到了上述各位遇到的错误。cheyanshuang给出的链接已经失效,从http://packages.ubuntu.com/dapper/admin/bootchart下载了个,dpkg -i *.deb后,没有bootchart命令,不知道哪里有下的,我的环境是ubuntu10.10,谢谢。

  • Assyla 於 March 27, 2012 12:36:

    去網路上找舊版的bootchart_0.9-0ubuntu6_all.deb或
    bootchart_0.9-0ubuntu7_all.deb吧
    Ubuntu最新版的pybootchartgui根本無法解析Android的Bootchart,我猜是版本的問題

  • Kate 於 June 6, 2014 15:31:

    請問如果是
    Unable to access jarfile /usr/share/bootchart/bootchart.jar
    這個問題我該如何解決呢?!謝謝你

留言功能維護中。將於近日重新開放。

連絡作者

Jollen Chen,Moko365(仕橙3G教室)講師,熱愛研究 Linux 與 Android 技術。曾為 Motorola、HTC、Foxconn、LG、OPPO、騰迅、廣達電腦、緯創、仁寶等超過 50 家企業講授課程。目前在 MokoVersity 擔任軟體工程師,撰寫 Node.js 程式,也在幾家科技廠兼任 Android Framework 研發顧問。您可透過電子郵件 <jollen (at) jollen (dot) org> 或這裡與我連絡。