关于android开机速度性能方面
16lz
2022-05-01
android开机,分为三个阶段,
1.
2.linux内核启动,开机动画开始显示
3.开始进入android的世界
4.android部分启动完成,开始初始化一些系统进程
1. Bootloader引导
这个引导就是把os启动起来的代码,就是这段代码能够让下面的linux内核跑起来,这部分内容基本上都是mtk给到我们之后,就不需要去修改了,所以不做具体介绍
2.linux内核启动
大家都知道,android本身的内核是linux内核,开机启动自然是从linux内核启动开始。这部分由于是涉及的内核比较多,而且从目前来看,能够优化的部分不多,且风险比较大,就不具体介绍,
目前,我所知道的linux内核启动速度优化的方法,通过一个比gzip更快的方式去解压内核映射,可以加快开机速度
3.android的世界
先来说init进程的内容,为什么要说这个进程呢? 因为这个进程非常特殊,它基本控制了android系统里面的propertity,native service等..., 首先,从linux kernel启动完成之后,第一个启动的用户进程就是init进程,具体的代码会在system/core/init/init.cpp里面,这个进程会去解析init.rc及init.xxx.rc之类的文件,并根据这些配置文件的关键字进行系列操作,如启动进程,只是设置服务等待启动之类...., 需要注意的是android世界的第一个进程zygote也是在这里面定义的,并通过init进程启动的,
64 位:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
32位:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
从上面的配置可以看到,实际上zygote进程也是通过init进程启动,实际上执行的是/system/bin/app_process的一个bin文件,64位的机器比较特殊,它是能够支持32位apk和64位apk,所以会有两个zygote进程
如果想在mtklog中搜索开机log,一般有下面的内容(针对64位):
01-01 12:56:30.427526 881 881 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
01-01 12:56:30.894456 882 882 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
一般是两个,第一个是64位的,第二个32位的
启动到了这一步,我们现在可以通过看event_log.boot进一步分析,
01-01 12:56:30.427702 881 881 I boot_progress_start: 26858
01-01 12:56:33.985307 881 881 I boot_progress_preload_start: 30415
01-01 12:56:34.063756 882 882 I boot_progress_preload_start: 30494
01-01 12:56:36.573528 881 881 I boot_progress_preload_end: 33003
01-01 12:56:36.903491 882 882 I boot_progress_preload_end: 33333
此阶段为zygote进程加载一些常用的类,这个步骤可以使应用启动的时候,不需要再去加载一些类对象
01-01 12:56:36.965987 1386 1386 I boot_progress_system_run: 33396
01-01 12:56:37.478227 1386 1386 I boot_progress_pms_start: 33908
01-01 12:56:37.571837 1386 1386 I boot_progress_pms_system_scan_start: 34002
01-01 12:57:24.897414 1386 1386 I boot_progress_pms_data_scan_start: 81327
01-01 12:57:24.920992 1386 1386 I boot_progress_pms_scan_end: 81351
01-01 12:57:26.433115 1386 1386 I boot_progress_pms_ready: 82863
此阶段为pms对各种路径下的apk包进行扫描
01-01 12:57:27.233841 1386 1386 I wm_stack_created: [0,0,0,0,0]
01-01 12:57:27.365301 1386 1386 I configuration_changed: 7672
01-01 12:57:27.381441 1386 1386 I configuration_changed: 1032
01-01 12:57:27.923816 1386 1386 I configuration_changed: 512
01-01 12:58:40.760186 1386 1386 I free_storage_left: [10827628544,463716352,397475840]
01-01 12:58:40.760295 1386 1386 I free_storage_changed: 10827628544
01-01 12:58:45.829452 1386 1421 I boot_progress_ams_ready: 162259
此阶段,系统进程基本已经准备好了,可以去启动一些系统应用了
可以看到,这一部分是相当耗时的,我们从main log里面看一下,在做什么
搜索dex2oat,会发现,其实这个时候,大部分的时间是在做编译apk的动作,
如果预置的三方应用很多,这样启动的时间就会越长,比如Facebook编译的时间长达220s以上,
还有就是编译一些在/system/framework下的jar包,以及编译一些应用内部自己添加的jar包,
01-01 00:00:25.697944 3916 3916 I dex2oat : /system/bin/dex2oat --compiler-filter=interpret-only --dex-file=/data/user/0/com.google.android.googlequicksearchbox/files/extradex_jars/XJDyz7eY4OZBOGABJHxSaFQ/verified/ondevicewebsuggest/ondevicewebsuggest-0.jar --oat-file=/data/user/0/com.google.android.googlequicksearchbox/files/extradex_jars/XJDyz7eY4OZBOGABJHxSaFQ/verified/ondevicewebsuggest/ondevicewebsuggest-0.dex
01-01 12:57:27.941746 1386 1386 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /system/app/Twitter/Twitter.apk pkg=com.twitter.android isa=arm vmSafeMode=false debuggable=false oatDir = null
01-01 12:57:39.723015 1386 1386 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /system/app/NoteBook/NoteBook.apk pkg=com.fly.android.notes isa=arm64 vmSafeMode=false debuggable=false oatDir = null
从上面的数据可以证明,我们上述的一些观点,
实际上从sys_log里面,是可以看到启动的阶段的,关键字:SystemServiceManager,Starting phase
具体的启动阶段代表的含义在SystemService.java中
public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?
/**
* After receiving this boot phase, services can obtain lock settings data.
*/
public static final int PHASE_LOCK_SETTINGS_READY = 480;
/**
* After receiving this boot phase, services can safely call into core system services
* such as the PowerManager or PackageManager.
*/
public static final int PHASE_SYSTEM_SERVICES_READY = 500;
/**
* After receiving this boot phase, services can broadcast Intents.
*/
public static final int PHASE_ACTIVITY_MANAGER_READY = 550;
/**
* After receiving this boot phase, services can start/bind to third party apps.
* Apps will be able to make Binder calls into services at this point.
*/
public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
/**
* After receiving this boot phase, services can allow user interaction with the device.
* This phase occurs when boot has completed and the home application has started.
* System services may prefer to listen to this phase rather than registering a
* broadcast receiver for ACTION_BOOT_COMPLETED to reduce overall latency.
*/
public static final int PHASE_BOOT_COMPLETED = 1000;
可以看到,只有在跑到值为1000的PHASE_BOOT_COMPLETED 阶段,才算系统基本启动完成的,之前有一个SD卡performance比较差的问题,也是看这个启动
阶段,可以发现,正常的机器与异常的机器,时间差得非常多,这样就可以从启动的阶段去排查,看哪个阶段时间长了,
那我们优化点的建议:
预置应用:
比如在:/system/app下的应用,如果是预置应用,在Android.mk建议加上LOCAL_DEX_PREOPT := true控制,
在/system/vendor下的预置应用,如果此应用编译时间比较长的,也使用上LOCAL_DEX_PREOPT := true
目前已采用新的策略,
/system/framework/下的jar包:
这部分的jar包,因为本身jar文件是在/system/framework下的,所以无身也无法通过升级,因为/system分区是只读,不可写的,
所以建议,在make的时候,我们就可以编译这部分的jar包,而不是等到手机第一次开机的时候才去编译,增加了第一次开机的时间
此方案,对启动速度有一定的优化作用
应用内置的额外的jar包:
这部分jar包的一般是在应用加载启动的时候编译的,会增加应用第一次启动的时间,建议,第一次加载的时候,不编译这部分jar ,而是放在之后才进行编译,对应用本身运行并不会造成影响,
新策略:
目前是通过,在第一次开机的时候,我们并不通过主线程去优化APK,而是通过另起线程在一定的时间内去优化APK,这样的好处是,不会阻塞主线程,这样开机的速度自然就加快了,
目前代码还在测试中,之后的一段时间这些代码将会上传。。
上面的优化点建议是基于android6.0的,也适用于5.0,5.1
Android5.0,5.1上,在系统第一次启动的时候,会做一个patchoat的动作,此操作基本相当于做了两次dex2oat的时间,这个优化点,我们建议是去掉这个patchoat,
后续关于这部分的内容,我们会继续添加,敬请关注....
1.
2.linux内核启动,开机动画开始显示
3.开始进入android的世界
4.android部分启动完成,开始初始化一些系统进程
1. Bootloader引导
这个引导就是把os启动起来的代码,就是这段代码能够让下面的linux内核跑起来,这部分内容基本上都是mtk给到我们之后,就不需要去修改了,所以不做具体介绍
2.linux内核启动
大家都知道,android本身的内核是linux内核,开机启动自然是从linux内核启动开始。这部分由于是涉及的内核比较多,而且从目前来看,能够优化的部分不多,且风险比较大,就不具体介绍,
目前,我所知道的linux内核启动速度优化的方法,通过一个比gzip更快的方式去解压内核映射,可以加快开机速度
3.android的世界
先来说init进程的内容,为什么要说这个进程呢? 因为这个进程非常特殊,它基本控制了android系统里面的propertity,native service等..., 首先,从linux kernel启动完成之后,第一个启动的用户进程就是init进程,具体的代码会在system/core/init/init.cpp里面,这个进程会去解析init.rc及init.xxx.rc之类的文件,并根据这些配置文件的关键字进行系列操作,如启动进程,只是设置服务等待启动之类...., 需要注意的是android世界的第一个进程zygote也是在这里面定义的,并通过init进程启动的,
64 位:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
32位:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
从上面的配置可以看到,实际上zygote进程也是通过init进程启动,实际上执行的是/system/bin/app_process的一个bin文件,64位的机器比较特殊,它是能够支持32位apk和64位apk,所以会有两个zygote进程
如果想在mtklog中搜索开机log,一般有下面的内容(针对64位):
01-01 12:56:30.427526 881 881 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
01-01 12:56:30.894456 882 882 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
一般是两个,第一个是64位的,第二个32位的
启动到了这一步,我们现在可以通过看event_log.boot进一步分析,
01-01 12:56:30.427702 881 881 I boot_progress_start: 26858
01-01 12:56:33.985307 881 881 I boot_progress_preload_start: 30415
01-01 12:56:34.063756 882 882 I boot_progress_preload_start: 30494
01-01 12:56:36.573528 881 881 I boot_progress_preload_end: 33003
01-01 12:56:36.903491 882 882 I boot_progress_preload_end: 33333
此阶段为zygote进程加载一些常用的类,这个步骤可以使应用启动的时候,不需要再去加载一些类对象
01-01 12:56:36.965987 1386 1386 I boot_progress_system_run: 33396
01-01 12:56:37.478227 1386 1386 I boot_progress_pms_start: 33908
01-01 12:56:37.571837 1386 1386 I boot_progress_pms_system_scan_start: 34002
01-01 12:57:24.897414 1386 1386 I boot_progress_pms_data_scan_start: 81327
01-01 12:57:24.920992 1386 1386 I boot_progress_pms_scan_end: 81351
01-01 12:57:26.433115 1386 1386 I boot_progress_pms_ready: 82863
此阶段为pms对各种路径下的apk包进行扫描
01-01 12:57:27.233841 1386 1386 I wm_stack_created: [0,0,0,0,0]
01-01 12:57:27.365301 1386 1386 I configuration_changed: 7672
01-01 12:57:27.381441 1386 1386 I configuration_changed: 1032
01-01 12:57:27.923816 1386 1386 I configuration_changed: 512
01-01 12:58:40.760186 1386 1386 I free_storage_left: [10827628544,463716352,397475840]
01-01 12:58:40.760295 1386 1386 I free_storage_changed: 10827628544
01-01 12:58:45.829452 1386 1421 I boot_progress_ams_ready: 162259
此阶段,系统进程基本已经准备好了,可以去启动一些系统应用了
可以看到,这一部分是相当耗时的,我们从main log里面看一下,在做什么
搜索dex2oat,会发现,其实这个时候,大部分的时间是在做编译apk的动作,
如果预置的三方应用很多,这样启动的时间就会越长,比如Facebook编译的时间长达220s以上,
还有就是编译一些在/system/framework下的jar包,以及编译一些应用内部自己添加的jar包,
01-01 00:00:25.697944 3916 3916 I dex2oat : /system/bin/dex2oat --compiler-filter=interpret-only --dex-file=/data/user/0/com.google.android.googlequicksearchbox/files/extradex_jars/XJDyz7eY4OZBOGABJHxSaFQ/verified/ondevicewebsuggest/ondevicewebsuggest-0.jar --oat-file=/data/user/0/com.google.android.googlequicksearchbox/files/extradex_jars/XJDyz7eY4OZBOGABJHxSaFQ/verified/ondevicewebsuggest/ondevicewebsuggest-0.dex
01-01 12:57:27.941746 1386 1386 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /system/app/Twitter/Twitter.apk pkg=com.twitter.android isa=arm vmSafeMode=false debuggable=false oatDir = null
01-01 12:57:39.723015 1386 1386 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /system/app/NoteBook/NoteBook.apk pkg=com.fly.android.notes isa=arm64 vmSafeMode=false debuggable=false oatDir = null
从上面的数据可以证明,我们上述的一些观点,
实际上从sys_log里面,是可以看到启动的阶段的,关键字:SystemServiceManager,Starting phase
具体的启动阶段代表的含义在SystemService.java中
public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?
/**
* After receiving this boot phase, services can obtain lock settings data.
*/
public static final int PHASE_LOCK_SETTINGS_READY = 480;
/**
* After receiving this boot phase, services can safely call into core system services
* such as the PowerManager or PackageManager.
*/
public static final int PHASE_SYSTEM_SERVICES_READY = 500;
/**
* After receiving this boot phase, services can broadcast Intents.
*/
public static final int PHASE_ACTIVITY_MANAGER_READY = 550;
/**
* After receiving this boot phase, services can start/bind to third party apps.
* Apps will be able to make Binder calls into services at this point.
*/
public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
/**
* After receiving this boot phase, services can allow user interaction with the device.
* This phase occurs when boot has completed and the home application has started.
* System services may prefer to listen to this phase rather than registering a
* broadcast receiver for ACTION_BOOT_COMPLETED to reduce overall latency.
*/
public static final int PHASE_BOOT_COMPLETED = 1000;
可以看到,只有在跑到值为1000的PHASE_BOOT_COMPLETED 阶段,才算系统基本启动完成的,之前有一个SD卡performance比较差的问题,也是看这个启动
阶段,可以发现,正常的机器与异常的机器,时间差得非常多,这样就可以从启动的阶段去排查,看哪个阶段时间长了,
那我们优化点的建议:
预置应用:
比如在:/system/app下的应用,如果是预置应用,在Android.mk建议加上LOCAL_DEX_PREOPT := true控制,
在/system/vendor下的预置应用,如果此应用编译时间比较长的,也使用上LOCAL_DEX_PREOPT := true
目前已采用新的策略,
/system/framework/下的jar包:
这部分的jar包,因为本身jar文件是在/system/framework下的,所以无身也无法通过升级,因为/system分区是只读,不可写的,
所以建议,在make的时候,我们就可以编译这部分的jar包,而不是等到手机第一次开机的时候才去编译,增加了第一次开机的时间
此方案,对启动速度有一定的优化作用
应用内置的额外的jar包:
这部分jar包的一般是在应用加载启动的时候编译的,会增加应用第一次启动的时间,建议,第一次加载的时候,不编译这部分jar ,而是放在之后才进行编译,对应用本身运行并不会造成影响,
新策略:
目前是通过,在第一次开机的时候,我们并不通过主线程去优化APK,而是通过另起线程在一定的时间内去优化APK,这样的好处是,不会阻塞主线程,这样开机的速度自然就加快了,
目前代码还在测试中,之后的一段时间这些代码将会上传。。
上面的优化点建议是基于android6.0的,也适用于5.0,5.1
Android5.0,5.1上,在系统第一次启动的时候,会做一个patchoat的动作,此操作基本相当于做了两次dex2oat的时间,这个优化点,我们建议是去掉这个patchoat,
后续关于这部分的内容,我们会继续添加,敬请关注....
更多相关文章
- android mainfest 属性详解
- android中的binder通信机制
- Android快速调试方法
- Android(安卓)判断应用 第一次启动
- Android(安卓)启动时 出现黑屏
- HOWTO install and setup Android(安卓)NDK for Windows(Android
- [日更-2019.4.22、23、24] cm-14.1 Android系统启动过程分析(三)-S
- Android进程的内存管理分析
- Android(安卓)多进程通信