该文档简单主要描述了如何找出开机各个阶段耗时情况,以及对开机各个阶段的分析方法和如何优化开机时间,减少耗时。便于读者可以通过此文档了解开机时间的各个阶段的耗时情况。
具体开机时间的优化需要根据开机流程来分析: 找出各个阶段的耗时情况
2.1、zygote阶段
一般有两个耗时点:
a). 预加载class/resource的时间。需要确认是否有添加很多系统资源
b). 这期间是否有很多GC动作
2.2、SystemServer阶段:
Check各个service开机初始化过程的耗时情况
通常耗时点:
a). pms scan package阶段:
b). pms dexopt阶段:
c).其他service初始化过程问题。
2.3、AMS Ready阶段:
Check耗时情况,通常耗时点:prebootcompleted动作;启动service/persistent进程;如果没有客制化动作,基本上无优化空间
2.4、动画包过大问题
如果动画包过大,播放的图片过多,分辨率过高也会影响开机时间
2.5、StopBootAnimation:
WMS需要在keyguard, wallpaper, launcher都初始化好的前提下,才会停止开机动画。
需要check keyguard是否有做完、Check wallpaper是否有异常、Check launcher 初始化时间。
3.1 cat/proc/bootprof[单位:ms(毫秒)]
从下面的log中我们可以看到内核启动时间标志字段:BOOT_Animation:END
3.1.1 Preloader&lk time
Preload和lk启动时间如下:
3.1.2 Kernel Init
Kernel初始化时间 如下:
3.1.3 Mount partition
分区挂载时间如下:
3.1.4 Android Boot
3.1.4.1 Pre-load classes
预加载类所消耗的时间
3.1.4.2 Package scanning
包扫描时间
3.1.4.3 App initializations
AP初始化时间
3.2 通过添加log得到Package扫描耗时情况
源码位于:frameworks/base/service/java/com/android/server/PackageManagerService.java中的scanDirLi()方法中
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
......
if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Scanning app dir " + dir + " scanMode=" + scanMode
+ " flags=0x" + Integer.toHexString(flags));
}
long startScan,endScan;
int i;
for (i=0; i<files.length; i++) {
File file = new File(dir, files[i]);
if (!isPackageFilename(files[i])) {
// Ignore entries which are not apk's
continue;
}
......
startScan = SystemClock.uptimeMillis();
Log.d(TAG,"scan package: " + file.toString() + " , start at: " + startScan + "ms.");
PackageParser.Package pkg = scanPackageLI(file,
flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
endScan = SystemClock.uptimeMillis();
Log.d(TAG,"scan package: " + file.toString() + " , end at: " + endScan + "ms. elapsed time = " + (endScan - startScan) + "ms.");
......
}
我们可以通过DDMS通过搜索关键字scan package,TAG为PackageManager进行查看。
4.1 cat /proc/mtprof/cputime
相关字段解释:
- Process:进程名
- Status:进程状态,e.g如果进程处于活动状态值为L(alive),否则为D(dead)
- PID、TGID:进程ID和线程组ID
- CPU Time(ms):真正使用CPU的时间
- Elapsed(ms):生命周期内耗时
- User:用户模式时间
- Kernel:Kernel模式时间
4.2 Application init
我们需要防止无关AP在启动期间进行初始化操作,因为Android在安装新的apk后可能会启动一些额外的应用。我们需要找出哪些在系统启动完成前启动了哪些应用程序,来进一步确认是否有启动了一些不需要的AP。
3.2.1在系统启动期间对应用初始化是因为在Apk的AndroidManifest.xml中application节点android:persistent的值为true。这个属性从字面上来说可以理解为可持久,也就是常驻的应用。被该属性修饰的应用会在系统启动之后被AM启动起来。例如PhoneApp在AndroidManifest.xml中注册了常驻app:
<application android:name=”PhoneApp”
android:persisitent=”true”
android:label=”@string/dialerIconLabel”
android:persisitent=”@drawable/ic_launcher_phone”>
4.2.2一些应用程序的启动是被其他AndroidAP唤起的如:
4.3 启动动画
系统安装了过多的应用很容易影响启动时间,主要在package scanning和application init。那么此时Boot animation也会随着这种影响而进一步影响启动时间。原因如下:
E.g:如果android启动动画占用10%的CPU,那么如果系统启动时间为20sec,那么动画占用的时间就是2s(动画耗时:20*10%=2),那么也就是说我们安装的应用越多,动画对整个开机过程的影响也就越大。