安卓底层开发学习经验第十八期

这一期我们学习 Zygote 在启动过程中的预加载分析与优化
下面我们来看一下我们 preload 加载资源的一个过程

我们加载资源分为三种,第一个就是preloadClasses 预加载我们的系统类,这个系统类定义的文件是在 frameworks/base/preloaded-classes ,我们加载的一个过程其实是 Class.forName 来真正的加载这个类,加载完之后我们就会在 zygote 中查找到这个类,这就是预加载的一个过程;第二个是我们要预加载一些资源,这个资源分为两种,第一个是我们的图片,第二个是我们一个颜色的设置,我们所说的图片以及颜色设置,它定义在我们的 frameworks/base/core/res/res/values/arrays.xml 中,当他编译生成 jar 包时,我们会把一些图片资源,以及一些颜色的定义全部生成相关的 xml ,然后我们可以在 zygote 启动的时候,使用 preloadResource() 把这些资源提前加载进来,在加载的过程中,我们会把它保存在一个全局变量中;第三个预加载就是加载我们的 OPengl 资源
下面我们来看一下我们预加载资源的目的是什么

首先我们知道我们的每一个APP 都是我们的 zygote 创建的,如果我们的 zygote 提前把我们所需要的一些系统的类,和 resource 全部加载完之后,当我们使用 fork 这个系统调用去创建一个子进程的时候,我们的子进程就会把这个系统资源,以及系统类全部继承过来,然后我们在调用 java 的方法再去启动我们的应用,这是我们就会发现我们新的应用已经把这两个资源给继承过来了,这样的话我们的应用就不会去重新加载我们的资源和我们的类了,这样我们就能提高应用的启动和运行速度,为什么说提高应用的启动和运行速度呢,说可以提高启动速度是因为,我们在启动一个应用的时候,不需要再去加载这些资源,这样就可以提高应用的启动速度了,因为我们加载这个资源和类,这个耗时是几秒钟的事,如果我们省去这一个步骤,不做预加载,那么启动应用的时候,它就会自己去找这些资源和类,如果在运行过程中再去找这些资源和类,那么他的运行速度肯定就会受到影响,这些资源是所有应用都需要的,所以说在 zygote 启动时把这些资源和类与加载进来,能提高应用的启动和运行速度
下面我们再来看一下 preloadClasses 他的一个过程

preloadClasses 其实就是导入我们类的一个配置文件,这个配置文件在我们的 frameworks/base 下面定义好了,他有我们系统里边的每一个类,然后把这个文件打开,然后把他读出来,在使用 Class.forName 把这些类加载到 zygote 中。
下面我们看一下他的具体实现过程,打开 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 这个文件,查找到 preloadClasses 这个方法

首先他会打开我们这个资源文件,这个资源文件的定义是在 frameworks/base/preloaded-classes 里边,我们可以打开它看一下,可以看到它里边使我们 Android 下的所有的类,这个 preloadClasses 所做的事情就是,把这些类提前加载进来。它加载的过程首先就是打开这个文件,然后把这个文件一条条的读进来,如果看到一个 # 号,那么说明这一行是不需要 load 的,如果不是 # 号,那么就会调用 Class.forName 把他加载进来,直到加载完成。在最后我们会打印一下加载时间,和加载了多少类,这个就是 preloadClasses 的一个过程
下面我们来看一下是如何加载我们系统资源的

我们加载系统资源分为两部分,第一是加载资源,第二是加载颜色的一些设置,首先调用的是preloadResource() 来加载系统资源,加载时我们会首先创建一个 resource ,然后把它赋值给我们的全局变量, mResource ,他用来保存我们系统的资源,加载资源时首先是 preloadDrawables() ,就是把刚才看到的所有的 xml 的所有文件给 load 进来,第二个就是加载一些颜色的设置,这个也在我们的 xml 中,我们来看一下代码的具体实现

他所的就是把我们com.android.internal.R.array.preloaded_drawables 给他 load 进来,我们来看一下这个文件,这个文件是在 frameworks/base/core/res/res/values/arrays.xml 中,打开它可以看到,这里面是一些图片文件,然后会把它预加载到这个 mResource 中, preloaded_drawables 所做的事情就是,把我们的图片资源使用 mResources.getDrawable 的方法把它加载进来,这就是我们加载资源的一个过程,然后会将我们加载资源的个数给显示出来,再加载我们预先设置好的颜色,加载颜色的过程也是一样的,它是用 mResources.getColourStateList 的方法,加载到我们的 mResources 中,这样就完成了图片和颜色的预加载
我们用 adb 来看一下我们预加载这些资源用的时间

我们可以看到总的时间大概是4 秒多,这个时间是在我们 Android 启动过程中所要花费的时间,所以 Android 手机启动慢就有这个方面的原因
下面我们来看一下如何利用我们的硬件资源来加快我们 load 的一个效率,我们可以看到,我们加载类的时间基本大于 2 秒,加载 Resource 的时间基本大于 1 秒,这时我们可以考虑采用多线程的方式去加载我们的类,和 Resource ,我们可以使用线程池的方法实现这个多线程加载

我们加载的过程首先是,在zygote 中创建一个线程池,这个线程池去实现一个类和资源的加载,当我们执行 preloadClass 时,将加载类的操作串行添加到线程池中,添加完之后我们去解析我们的 resource ,然后将我们 resource 中加载的资源操作串行的添加到我们的线程池中,然后就会等待线程池工作结束,当他工作完成之后,我们就可以知道,我们加载资源和类的一个过程已经完成了,完成之后就可以去做其他的操作了,如果说线程池的个数是 4 个,并且 CPU 也是 4 核的话,那么他的执行效率肯定比我们使用一个线程快很多,这就是用多线程的方法优化 zygote 的一个启动过程
下面我们来看一下我们使用多线程或者线程池优化的一个前提

我们使用多线程优化的实质是:使我们的 zygote 进程最大限度的抢占 CPU ,所以说我们的执行才能更快一些。
除了使用多线程优化之外呢,还有另一种方法,就是 BLCR ,这种方法现在还不成熟,有兴趣的朋友可以去了解一下
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值