bootchart 使用说明及代码分析--android启动优化

2023-10-24 23:50

本文主要是介绍bootchart 使用说明及代码分析--android启动优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

bootchart是一个用于linux启动过程性能分析的开源软件工具,在系统启动过程自动收集CPU占用率、进程等信息,并以图形方式显示分析结果,可用作指导优化系统启动过程。


bootchart是一个对linux启动流程进行分析得开源软件工具。android中有集成bootchart源码,路径为system/core/init/bootchart.c

 
第一部分:先从具体使用流程如下


1、编译android中的bootchart(缺省时不被编译)
  在android源码system/core/init/目录执行: mm INIT_BOOTCHART=true -B

  或者直接修改 Android.mak文件

[html] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <SPAN style="COLOR: #333333; FONT-SIZE: 14px">  LOCAL_PATH:= $(call my-dir)  
  2.     include $(CLEAR_VARS)  
  3.       
  4.     INIT_BOOTCHART :true  </SPAN>  
<span style="font-size:14px;color:#333333;">	LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
INIT_BOOTCHART := true  </span>

2、将新编译的android系统镜像烧录到android设备中。
编译生成新的可执行文件init,该文件在手机文件系统位于根/下,对应的flash image是boot.img,为此需重新烧写含有新的init的boot.img


3、在手机上创建文件/data/bootchart-start,其内容是bootchart的采样时间
adb shell 'echo $TIMEOUT > /data/bootchart-start'
其中$TIMEOUT是期望采样的时间,单位为秒,例如要采样两分钟,则执行:
adb shell 'echo 120 > /data/bootchart-start'


4、重启设备,init运行时将自动创建文件夹/data/bootchart/,并在其中保存采样数据,采样数据由5个文件组成:

[html] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <SPAN style="COLOR: #333333; FONT-SIZE: 14px">-rw-rw-rw- root     root          732 1970-01-01 08:00 header  
  2. -rw-r--r-- root     root            0 1970-01-01 08:00 kernel_pacct  
  3. -rwxr-xr-x root     root       517150 2014-04-09 12:06 proc_diskstats.log  
  4. -rwxr-xr-x root     root      2783967 2014-04-09 12:06 proc_ps.log  
  5. -rwxr-xr-x root     root       152090 2014-04-09 12:06 proc_stat.log</SPAN>  
<span style="font-size:14px;color:#333333;">-rw-rw-rw- root     root          732 1970-01-01 08:00 header
-rw-r--r-- root     root            0 1970-01-01 08:00 kernel_pacct
-rwxr-xr-x root     root       517150 2014-04-09 12:06 proc_diskstats.log
-rwxr-xr-x root     root      2783967 2014-04-09 12:06 proc_ps.log
-rwxr-xr-x root     root       152090 2014-04-09 12:06 proc_stat.log</span>

需要注意,在手机上运行bootchart采样完成后若不再使用bootchart则需手工删除文件/data/bootchart-start,否则手机每次重启时都会运行bootchart。


5、文件打包
在/data/bootchart/目录下执行命令:


[html] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <SPAN style="COLOR: #333333; FONT-SIZE: 14px">busybox tar -czf bootchart.tgz header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct </SPAN>  
<span style="font-size:14px;color:#333333;">busybox tar -czf bootchart.tgz header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct </span>

然后将生成bootchart.tgz用u盘拷贝到电脑(ubuntu系统)上。

也可手工通过adb pull将这5个文件上传到PC并打包,反正最终就是生成 bootchart.tgz 


6.在电脑上安装bootchart工具

使用sudo apt-get install bootchart 命令安装, 如果出现 bootchart无法正常解析android中生成的bootchart.tgz文件。
需要使用老版本的安装包bootchart_0.9-0ubuntu6_all.deb,可以在此下载http://download.csdn.net/detail/sckgenius/7166477。
先sudo apt-get install librsvg2-bin,然后sudo dpkg -i bootchart_0.9-0ubuntu6_all.deb 。


7、执行下面的命令生成分析结果图表,缺省生成png格式的图像文件bootchart.png:
java -jar /usr/share/bootchart/bootchart.jar /path/to/bootchart.tgz

这里上传一张bootchart.png图:



第二部分:下面说一下bootchart是如何得到这些数据信息的


分析是源码:system\core\init\bootchart.c 只有一个文件


1、启动

init.c 中通过宏定义 BOOTCHART 增加代码

[cpp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <SPAN style="COLOR: #333333; FONT-SIZE: 14px">#if BOOTCHART  
  2. static int bootchart_init_action(int nargs, char **args)  
  3. {  
  4.     bootchart_count = bootchart_init();  
  5.     if (bootchart_count < 0) {  
  6.         ERROR("bootcharting init failure\n");  
  7.     } else if (bootchart_count > 0) {  
  8.         NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);  
  9.     } else {  
  10.         NOTICE("bootcharting ignored\n");  
  11.     }  
  12.   
  13.     return 0;  
  14. }  
  15. #endif</SPAN>  
<span style="font-size:14px;color:#333333;">#if BOOTCHART
static int bootchart_init_action(int nargs, char **args)
{
bootchart_count = bootchart_init();
if (bootchart_count < 0) {
ERROR("bootcharting init failure\n");
} else if (bootchart_count > 0) {
NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
} else {
NOTICE("bootcharting ignored\n");
}
return 0;
}
#endif</span>

通过调用 bootchart_init() 启动


2、周期性执行

int main(int argc, char **argv)

[cpp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <SPAN style="FONT-SIZE: 14px"><SPAN style="COLOR: #333333">{  
  2.   
  3. #if BOOTCHART  
  4.     queue_builtin_action(bootchart_init_action, "bootchart_init");  
  5. #endif  
  6.   
  7.     for(;;) {  
  8.         int nr, i, timeout = -1;  
  9.   
  10.   
  11. #if BOOTCHART  
  12.         if (bootchart_count > 0) {  
  13.             if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)  
  14.                 timeout = BOOTCHART_POLLING_MS;  
  15.             if (</SPAN><STRONG><SPAN style="COLOR: #ff0000">bootchart_step(</SPAN><SPAN style="COLOR: #cc0000">)</SPAN></STRONG><SPAN style="COLOR: #333333"> < 0 || --bootchart_count == 0) {  
  16.                 bootchart_finish();  
  17.                 bootchart_count = 0;  
  18.             }  
  19.         }  
  20. #endif   
  21.   
  22.         nr = poll(ufds, fd_count, timeout);  
  23.           
  24.   }   
  25.     ...  
  26. }</SPAN></SPAN>  
<span style="font-size:14px;"><span style="color:#333333;">{
#if BOOTCHART
queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif
for(;;) {
int nr, i, timeout = -1;
#if BOOTCHART
if (bootchart_count > 0) {
if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
timeout = BOOTCHART_POLLING_MS;
if (</span><strong><span style="color:#ff0000;">bootchart_step(</span><span style="color:#cc0000;">)</span></strong><span style="color:#333333;"> < 0 || --bootchart_count == 0) {
bootchart_finish();
bootchart_count = 0;
}
}
#endif
nr = poll(ufds, fd_count, timeout);
}	
...
}</span></span>

默认周期时间:
# define BOOTCHART_POLLING_MS   200   /* polling period in ms */


3、具体如何采样数据

分析一下源码就很清楚了,就是通过linux中的标准命令(shell上执行cat xxx 类似)并将其结果写入相应的文件

/proc/cmdline

/proc/version
/proc/cpuinfo
写入到文件 #define LOG_HEADER      LOG_ROOT"/header"

/proc/uptime
/proc/stat
写入到文件 #define LOG_STAT        LOG_ROOT"/proc_stat.log"

/proc/uptime
/proc/diskstats
写入到文件 #define LOG_DISK        LOG_ROOT"/proc_diskstats.log"

/proc/uptime
/proc/$PID/cmdline
/proc/$PID/stat
写入到文件 #define LOG_PROCS       LOG_ROOT"/proc_ps.log"

这个文件只打开,没有写入什么内容
/* create kernel process accounting file */
#define LOG_ACCT        LOG_ROOT"/kernel_pacct"


参考资料:

1、system/core/init/README.BOOTCHART

2、http://www.bootchart.org/index.html

这篇关于bootchart 使用说明及代码分析--android启动优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/278604

相关文章

Nginx启动失败:端口80被占用问题的解决方案

《Nginx启动失败:端口80被占用问题的解决方案》在Linux服务器上部署Nginx时,可能会遇到Nginx启动失败的情况,尤其是错误提示bind()to0.0.0.0:80failed,这种问题通... 目录引言问题描述问题分析解决方案1. 检查占用端口 80 的进程使用 netstat 命令使用 ss

Python使用Pandas对比两列数据取最大值的五种方法

《Python使用Pandas对比两列数据取最大值的五种方法》本文主要介绍使用Pandas对比两列数据取最大值的五种方法,包括使用max方法、apply方法结合lambda函数、函数、clip方法、w... 目录引言一、使用max方法二、使用apply方法结合lambda函数三、使用np.maximum函数

Qt 中集成mqtt协议的使用方法

《Qt中集成mqtt协议的使用方法》文章介绍了如何在工程中引入qmqtt库,并通过声明一个单例类来暴露订阅到的主题数据,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一,引入qmqtt 库二,使用一,引入qmqtt 库我是将整个头文件/源文件都添加到了工程中进行编译,这样 跨平台

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2