Android bootchart(5.1)
1.Bootchart介紹
Bootchart是對GNU / Linux的啟動過程的效能分析和視覺化工具。在開機過程中會收集資源利用和處理資訊,最後這些資訊會呈現在一個PNG,SVG或EPS編碼圖上(官網英文介紹地址:http://www.bootchart.org/).
2.Bootchar除錯
Bootchart程式碼已在Android的原始碼中,需要我們修改對應的配置來啟用bootchart.
system/core/init/Android.mk中,新增如下資訊,開啟BOOTCHART功能:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+INIT_BOOTCHART := true
system/core/init/bootchart.h中定義BOOTCHART:
#ifndef BOOTCHART
-#define BOOTCHART 0
+#define BOOTCHART 1
#endif
touch system/core/init/bootchart.c (更新檔案)
mmm system/core/init/ (重新編譯init模組)
編譯提示資訊:target Symbolic: init (out/target/product/cht_cr_mrd/symbols/init)表示已經生成init程式,重新打包boot.img,燒錄boot.img.
燒錄完成後,系統開機,寫入bootchart採集時間:
adb shell "echo 120 > /data/bootchart-start"
然後重啟系統.(以上操作可以閱讀官方文件:system/core/init/README.BOOTCHART)
這時候問題來了,/data/bootchart目錄下本該有很多記錄資料的檔案,但居然沒有產生!
log上提示”audit: type=1400 audit(1325552984.022:5): avc: denied"許可權問題,開始懷疑selinux問題導致,把main函式裡的selinux_initialize()註釋掉,即關閉selinux,但問題依舊。.
於是就開始跟蹤分析bootchart程式碼,在init.c裡
queue_builtin_action(bootchart_init_action, "bootchart_init");新增action正常.
有呼叫bootchart_init_action函式,此函式有執行,新增列印後發現此函式裡bootchart_count的值居然為0!,程式碼如下
#if BOOTCHART
static int bootchart_init_action(int nargs, char **args)
{
bootchart_count = bootchart_init();
ERROR("bootchart_init_action:bootchart_count %d\n",bootchart_count);
if (bootchart_count < 0) {
ERROR("bootcharting init failure\n");
} else if (bootchart_count > 0) {
ERROR("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
} else {
ERROR("bootcharting ignored\n");
}
return 0;
}
#endif
於是就繼續跟程式碼到bootchart_init函式裡.找到建立/data/bootchart目錄的程式碼:
do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR);
新增列印,這裡ret返回值為0,即建立/data/bootchart目錄是成功的!,那為什麼沒有目錄呢?冷靜下來思考,懷疑是建立後被刪除了?但是按照bootchart的設計,這個目錄是用來儲存資料,需要使用者獲取的,bootchart本身不會去刪除的.所以在/data路徑下手動建立此目錄,重啟後,該目錄是存在的,排除了刪除的可能.跟蹤發現其他檔案open返回值也是正常的,當時很奇怪.折騰了一整天,後來檢視系統啟動過程資訊,分析發現在bootchart執行之後/data分割槽才掛載上來導致的!!!!!即bootchart_init裡open/mkdir方式建立的這些目錄和檔案,全部被之後掛載的分割槽覆蓋了!所以在不修改掛載前提下,就修改bootchart檔案路徑吧,山不過來,我就過去~找到問題點,修改就容易了,已知/dev目錄在bootchart呼叫之前,是一定會先建立的.所以修改方法,就是把使用的路徑從/data修改到/dev即可,修改如下:
--- a/system/core/init/bootchart.c
+++ b/system/core/init/bootchart.c
@@ -36,15 +36,17 @@
#define VERSION "0.8"
#define SAMPLE_PERIOD 0.2
-#define LOG_ROOT "/data/bootchart"
+#define LOG_ROOT "/dev/bootchart"
#define LOG_STAT LOG_ROOT"/proc_stat.log"
#define LOG_PROCS LOG_ROOT"/proc_ps.log"
要注意啟動bootchart需要讀取LOG_STARTFILE檔案的值(預設為/data/bootchart-start)來確定啟動取樣,目前data分割槽掛載的問題,無法使用,需要修改.嘗試在/dev/下建立bootchart-start節點,並寫入值,但是失敗了,因為/dev目錄下的檔案在重啟後是重新生成的,重啟前建立的檔案都不存在了,此方法不行. 於是就是去修改啟動bootchart的條件的程式碼.一種方式是通過修改/proc/cmdline的androidboot.bootchart=值,另外一種就是直接修改修改bootchart_init函式裡程式碼,本文采取後者:
proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) );
s = strstr(cmdline, KERNEL_OPTION);
+//force to 180s
+timeout = 180;
重新編譯,燒錄.測試圖表生成,打包bootchart圖表原始檔
adb shell
cd /dev/bootchart
- busybox tar -czf bootchart.tgz header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct
exit
adb pull /dev/bootchart/bootchart.tgz ./
3.生成bootchart效能分析圖
ubuntu上安裝bootchart工具:
sudo apt-get install bootchart
執行bootchart解析所獲取到的資料:
[email protected]:~/bootchart$ bootchart bootchart.tgz
parsing 'bootchart.tgz'
parsing 'header'
parsing 'proc_stat.log'
parsing 'proc_ps.log'
Traceback (most recent call last):
File "/usr/bin/bootchart", line 23, in <module>
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 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
MD,報錯了...
錯誤資訊看,是存在除0的異常,檢視這部分程式碼,interval存在為0的情況,所以在/usr/lib/pymodules/python2.7/pybootchartgui/samples.py報錯的這行,新增如下程式碼在
if interval == 0:
interval = 1
再次編譯,會報同樣除0的問題,修改方法與上面一樣.
編譯後生成png圖片
這裡有個問題,我們設定的是180s,實際上只採集了90秒左右,採集時間怎麼少了90秒?
檢視init.c程式碼裡,發現for迴圈中,在執行的command是非常多的,每次迴圈的間隔並不是固定的200ms,而每次迴圈都會執行--bootchart_count操作,即bootchart希望每次執行的間隔是200ms,但init迴圈任務中處理的多個command,時間都不固定(即程式碼中"poll(ufds, fd_count, timeout);的timeout不固定"),所以這裡的採集總時間就跟設定的所不同了.
圖示上標示資訊還是挺全的,如果還是不清楚,可以先閱讀官網(http://www.bootchart.org/)samples欄的示例分析.
4.總結
在開機優化方面,可以通過以下幾點來減少開機時間:
1.bootchart生成資料圖表,檢視是否存在長期佔用資源的情況.
2.刪除不需要的APK,減少開機預載入時間.
3.去除init.rc中不需要的服務.
4.清除systemserver.java中不需要的服務.
相關推薦
Android bootchart(5.1)
1.Bootchart介紹 Bootchart是對GNU / Linux的啟動過程的效能分析和視覺化工具。在開機過程中會收集資源利用和處理資訊,最後這些資訊會呈現在一個PNG,SVG或EPS編碼圖上(官網英文介紹地址:http://www.bootchart.org/)
下載Android原始碼(5.1.1)
Win10環境: 1/ 安裝Vmware Workstation 2/ 建立虛擬機器,下載安裝Ubuntu16.04 3/ 安裝OpenJDK ( http://www.linuxidc.com/Linux/2017-11/148695.htm ) $ sudo a
OAuth2.0學習(5-1)新浪開放平臺-微博OAuth2.0認證
com blank weibo mage pen auth 平臺 target img http://open.weibo.com/wiki/%E9%A6%96%E9%A1%B5 OAuth2.0學習(5-1)新浪開放平臺-微博OAuth2.0認證
2小時學會SpringBoot(5-1)
資料庫操作(上) Spring-Data-Jpa -> MySQL Spring-Data-Jpa JPA(Java Persistence API)定義了一系列物件持久化的標準,目前實現這一規範的產品有Hibernate、TopLink等。 RESTful API
影象處理與分析(數字影象處理第二版)學習筆記(5.1)
第五章,影象復原 1,什麼是影象復原? 影象復原是利用某種先驗知識來重建或者復原被退化的影象。一般來講,影象復原就是將退化模型化,並且採用相反的過程進行處理,以便復原出原影象。 2,影象退化模型表達形式? 退化過程模型化之後為一個退化函式和一個加性噪聲項。 g(x,y)=h(
吳恩達DeepLearning.ai筆記(5-1)-- 迴圈序列模型
吳恩達DeepLearning.ai筆記(5-1)– 迴圈序列模型 1.一些序列資料例子 2.數學符號 x<1>x<1>輸入序列X第一個單詞,TixTxi輸入序列X的單詞個數,X(i)<t>X(i)&l
吳恩達 深度學習 程式設計作業(5-1)Part 2
吳恩達 Coursera 課程 DeepLearning.ai 程式設計作業系列,本文為《序列模型》部分的第一週“迴圈神經網路”的課程作業——第二部分:字母級的語言模型:恐龍獸島。 Character level language model -
吳恩達Coursera深度學習課程 DeepLearning.ai 提煉筆記(5-1)-- 迴圈神經網路
Ng最後一課釋出了,撒花!以下為吳恩達老師 DeepLearning.ai 課程專案中,第五部分《序列模型》第一週課程“迴圈神經網路”關鍵點的筆記。 同時我在知乎上開設了關於機器學習深度學習的專欄收錄下面的筆記,以方便大家在移動端的學習。歡迎關
演算法-藍橋杯習題(5-1)
藍橋杯習題 藍橋杯練習系統習題加答案,總共分為6部分,90%習題使用C語言解答,部分使用C++或者Java。大部分習題為搜尋參考或者別人提供所得,不足之處在所難免,懇請批評指正(預計200多題,習題僅供學習交流) 目錄 藍橋杯練習系統評測
吳恩達Coursera深度學習(5-1)遞迴神經網路 RNN
Class 5:序列模型 Sequence Models Week 1:迴圈神經網路 RNN(Recurrent) 目錄 本課程將教你如何建立自然語言,音訊和其他序列資料的模型。 由於深入的學習,序列演算法的執行速度遠遠超過兩年前,這
【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做專案(5.1) 登入功能的實現,開始接觸Spring IOC、DI
索引 簡述 今天我們做登入,今天的東西比較多,用到了Spring的IOC和DI、介面的使用、驗證等,希望大家多多討論 專案準備 我們用的工具是:VS 2013 + SqlServer 2012 + IIS7.5 希望大家對ASP.NET MVC有一個初步的理解,理論性的東西我們不做過多解釋,有些
RK3288 平臺(Android 5.1)+ PN548 除錯流水賬(一、前期編譯篇)
一、獲取原始碼 客戶向瑞芯微技術視窗申請SDK 二、SDK 編譯 1.JDK 安裝 Android5.1 系統編譯依賴於 JDK7。 編譯之前需安裝 JDK7,並配置 JAVA 環境變數。例如, 安裝路徑為/usr/lib/jvm/java
Activity啟動流程分析(基於android 5.1)
最近由於工作需要,需要深入瞭解AMS的內部實現。說老實話,雖然已經經過了幾輪重構,AMS的程式碼還是又臭又長。。。 萬事開頭難,先找個入口開始看吧。當從Launcher介面點選啟動一個app時,會啟動一個新的activity。所以就從startActivity()看起,研究
顯示頁面鏈接(7.5.1)
info item mat pub 以及 size action get 傳遞 1、添加視圖模型 PagingInfo(WebUI.Models)(這一步不用改,每個項目照用就行) 創建 PagingInfo 視圖模型,將“可用頁面數”、&
filebeat讀取nginx經過elasticsearch到kibanna實戰(5.1.1版本)
filebeat+ELK使用版本為5.1.1(沒有用到logstash) 壓縮包準備,各種解壓。 因為filebeat比較小巧,所以採集端直接用filebeat 1 nginx日誌原始配置: nginx.conf log_format main
spring原始碼學習(5.1.0版本)——Bean的初始化(中)
目錄 前言 createBean 有自定義TargetSource代理類的生成 resolveBeforeInstantiation applyBeanPostProcessorsBeforeInstantiation postProcessBeforeIn
spring原始碼學習(5.1.0版本)——Bean的初始化(上)
目錄 前言 源頭 preInstantiateSingletons方法 getBean(String beanName) doGetBean getObjectForBeanInstance getObjectFromFactoryBean doGe
7-1 計算指數 (5 分)
真的沒騙你,這道才是簡單題 —— 對任意給定的不超過10的正整數n,要求你輸出2n。不難吧? 輸入格式: 輸入在一行中給出一個不超過10的正整數n。 輸出格式: 在一行中按照格式 2^n = 計算結果 輸出
Spring原始碼閱讀(5.1.0版本)——Contextloaderlistener
目錄 前言 結論 原始碼解析 前言 上了大三了,逐漸想保研,現在一邊準備比賽,一邊學習新知識,一邊做著專案,希望自己能扛下去吧,這篇部落格的原始碼來自spring 5.1.0版本,如有錯誤,歡迎指出 結論 Contextloaderlistener幹了下
spring原始碼學習(5.1.0)——Bean的初始化(下)
目錄 前言 結語 前言 上篇部落格主要介紹了createBean方法,Bean的初始化會有三個主要的方法 createBean:初始化Bean,此時還沒有進行屬性填充 populateBean:進行屬性填充 initializ