同时安装多个应用慢

APK的安装过程

常见的APK安装方式有以下几种:

  1. 开机扫描时安装:开机时通过PMS的包扫描动作完成
  2. 下载后点击apk文件安装:用户自行下载安装包,通过点击安装包触发安装
  3. adb install安装:使用shell命令安装
  4. 从market安装:直接使用play store等安装

以下以下载后点击apk文件安装为例

当下载apk 到手机再点击apk 安装时,GooglePackageInstaller.apk会弹出一个是否安装界面,即PackageInstallerActivity。当用户点击安装时,就跳转到安装进度信息界面,即InstallAppProgress。这个过程会调用PMS解析下载的apk的基本信息,并保存到InstallParams 中,并发送INIT_COPY 消息,进入安装并一直显示直到安装结束。

第一阶段:复制apk文件

将需要安装apk的信息保存到InstallParams 中,并发送INIT_COPY 消息,这个过程是GooglePackageInstaller.apk调用PMS服务向PMS主进程发送INIT_COPY 消息。PMS 进程handle 会处理INIT_COPY消息,并连接IMediaContainerService服务,当连接成功,就会将消息对应的InstallParams加入一个列表,并发送MCS_BOUND 消息,处理这个消息时就开始apk 复制。

这个过程耗时比较短,而且只要点击安装新的apk就会向PMS主线程发送消息,这个过程没有互斥锁。

第二阶段:装载安装应用

当apk 复制完成,就会进入安装对应apk的过程,这个过程是通过创建一个新的进程runnable,并作为一个消息发post 到PMS所在主进程消息队列中。由于这些线程是异步的,并持有mInstallLock锁,所以如果同时安装多个apk其执行过程是不能并行的。必须上一个应用安装完成下一个应用线程才能启动。

这个过程主要有:包扫描收集组件信息并更新系统数据结构、apk需要空间信息的处理过程、

dexopt 优化过程及链接库处理过程。这些是在一个线程中完成,并持有mInstallLock 锁。当这些过程处理完,apk安装即将完成。

数据对比

安装耗时

                                    表一

表一是S31(1G/16G) userdebug 版本恢复出厂设置后微信、qq、qq game 三个应用同时安装的时间,同样条件下单独安装这三个apk 得到的数据相差很小,可能在手机ram 足够大时同时安装几个应用影响很小,需要在手机较忙时才有明显的可比性。

System 进程堆栈

 adb shell dumpsys meminfo  system_server

同时安装 微信、qq、qq game 获取system_server堆栈值

 App Summary

                       Pss(KB)

                        ------

           Java Heap:    30740

         Native Heap:    12040

                Code:    10136

               Stack:      892

            Graphics:     1336

       Private Other:     5588

              System:     2637

               TOTAL:    63369      TOTAL SWAP (KB):    23952

单独安装微信获取system_server堆栈值。

 App Summary

                       Pss(KB)

                        ------

           Java Heap:    25740

         Native Heap:    11936

                Code:    12012

               Stack:      932

            Graphics:     1472

       Private Other:     3808

              System:     4386

               TOTAL:    60286      TOTAL SWAP (KB):    24040

空闲时获取system_server堆栈值。

 App Summary

                       Pss(KB)

                        ------

           Java Heap:    19900

         Native Heap:    13652

                Code:    10576

               Stack:      956

            Graphics:     7504

       Private Other:     3728

              System:     4116

               TOTAL:    60432      TOTAL SWAP (KB):    24320

多个apk 安装慢影响项

1:apk 安装时,dexopt 是一个重要耗时项。

2:同时安装apk时,会对每个apk开启一个新的安装线程,同时线程均持有mInstallLock 互斥锁,  开启多线程开销从而对apk安装有一定的影响。

3:多个apk安装会增加 PMS 主线程消息处理消耗,从而对apk安装有一定的影响。

4:同时安装多个apk时,java heap 占用量变化相对明显,在手机较忙时影响大。

微信:

04-07 18:16:04.135820  1072  1137 I PackageManager: init_copy idx=0: InstallParams{72a2f6d file=/data/app/

04-07 18:16:05.087538  1072  1137 D PackageManager: begin to process post message  time :126955  installerPackageName:null

04-07 18:16:48.725164  1072  1137 D PackageManager: end to process post message  time :170593  installerPackageName:Package{41d9339 com.tencent.mm}

53s        55                                              41s

04-07 18:16:49.888977  1072  1137 D PackageManager: begin to process post message  time :171756

04-07 18:16:57.395392  1072  1137 D PackageManager: end to process post message  time :179263  installerPackageName:Package{88331c1 com.facebook.katana}

28s   -----51s                                           23s

04-07 18:16:59.269660  1072  1137 D PackageManager: begin to process post message  time :181137

04-07 18:17:21.658882  1072  1137 D PackageManager: end to process post message  time :203526  installerPackageName:Package{9740e34 com.afmobigroup.gphone}

38s   ------70s                                         20s

04-07 18:17:23.484403  1072  1137 D PackageManager: begin to process post message  time :205352  

04-07 18:17:55.207531  1072  1137 D PackageManager: end to process post message  time :237075  installerPackageName:Package{41828bd com.tencent.mobileqq}

68s    ------75s                                        59s                    

04-07 18:17:55.462424  1072  1137 D PackageManager: begin to process post message  time :237297  

04-07 18:18:02.278030  1072  1137 D PackageManager: end to process post message  time :244146  installerPackageName:Package{10c697 com.whatsapp}

60s     ------70s                                       35s              

04-07 18:16:04.135586  1072  1137 D PackageManager: PROCESS INIT_COPY

04-07 18:16:04.136210  1072  1137 I PackageManager: Trying to bind to DefaultContainerService

04-07 18:16:04.136910  1072  1117 W art     : Long monitor contention with owner PackageInstaller (1222) at int com.android.internal.content.NativeLibraryHelper.nativeCopyNativeBinaries(long, java.lang.String, java.lang.String, boolean, boolean)(NativeLibraryHelper.java:-2) waiters=0 in boolean com.android.server.pm.PackageInstallerSession.isPrepared() for 563ms

04-07 18:16:26.869698  1072  1117 W art     : Long monitor contention with owner PackageInstaller (1222) at java.lang.Object java.lang.Throwable.nativeFillInStackTrace!()(Throwable.java:-2) waiters=0 in boolean com.android.server.pm.PackageInstallerSession.isPrepared() for 11.210s

04-07 18:16:26.899029  1072  1086 W art     : Long monitor contention with owner android.io (1117) at void com.android.server.pm.PackageInstallerService$2.run()(PackageInstallerService.java:556) waiters=0 in android.content.pm.IPackageInstallerSession com.android.server.pm.PackageInstallerService.openSessionInternal(int) for 11.238s

04-07 18:16:26.903281  1072  1085 W art     : Long monitor contention with owner android.io (1117) at void com.android.server.pm.PackageInstallerService$2.run()(PackageInstallerService.java:556) waiters=1 in int com.android.server.pm.PackageInstallerService.createSessionInternal(android.content.pm.PackageInstaller$SessionParams, java.lang.String, int) for 2.646s

04-07 18:16:26.915094  2849  2849 D InstallAppProgress: Installation error code: 1

04-07 18:16:26.939220  2849  2849 D InstallAppProgress: Installation error code: 1

安装时间对比

多个应用安装耗时,从代码角度是计算的主要安装时间。

可以看出多个应用安装总用时比单个安装总用时要少。

同时有安装9个应用,实际只有5个安装了,apk实际点击安装的顺序跟截图上到下顺序一样。

有其它四个apk未安装的原因及安装实际耗时长如下log:

I PackageManager: Trying to bind to DefaultContainerService

W art     : Long monitor contention with owner PackageInstaller (1222) at int com.android.internal.content.NativeLibraryHelper.nativeCopyNativeBinaries(long, java.lang.String, java.lang.String, boolean, boolean)(NativeLibraryHelper.java:-2) waiters=0 in boolean com.android.server.pm.PackageInstallerSession.isPrepared() for 563ms

W art     : Long monitor contention with owner PackageInstaller (1222) at java.lang.Object java.lang.Throwable.nativeFillInStackTrace!()(Throwable.java:-2) waiters=0 in boolean com.android.server.pm.PackageInstallerSession.isPrepared() for 11.210s

W art     : Long monitor contention with owner android.io (1117) at void com.android.server.pm.PackageInstallerService$2.run()(PackageInstallerService.java:556) waiters=0 in android.content.pm.IPackageInstallerSession com.android.server.pm.PackageInstallerService.openSessionInternal(int) for 11.238s

W art     : Long monitor contention with owner android.io (1117) at void com.android.server.pm.PackageInstallerService$2.run()(PackageInstallerService.java:556) waiters=1 in int com.android.server.pm.PackageInstallerService.createSessionInternal(android.content.pm.PackageInstaller$SessionParams, java.lang.String, int) for 2.646s

D InstallAppProgress: Installation error code: 1

D InstallAppProgress: Installation error code: 1

1:apk copy 时包安装服务io操作太费时导致一直查询互斥对象锁,PackageInstaller 也会为下个apk安装不断查询互斥对象锁。

针对这一点可以修改同步锁类型,如将现在的一直查询改为未获取锁则睡眠等待通知,或者优化io读写速度。

安装消息处理:

1:MCS_UNBIND 、INIT_COPY 、MCS_BOUND

改变PMS消息队列消息处理顺序,比如当取到MCS_UNBIND,再查询后续5个消息是否有INIT_COPY 或MCS_BOUND消息,有则丢掉MCS_UNBIND 消息,继续处理后续消息,这样可以减少断开与连接DefaultContainerService开销。

参数调整

目前平台dalvik 参数如下:

dalvik.vm.dex2oat-filter     verify-at-runtime

Dalvik.vm.usejit               true

vmSafeMode                     false    

以上参数都是比较优的参数配置

2:延迟MCS_UNBIND发送时间,现在是10s,或者发送跟POST_INSTALL (安装几乎完毕)消息建立一个时间关系。

3:复制apk优化,如buffer改变

4:certificate verification 优化

          

安装时间对比(N)

多个应用安装耗时,从代码角度是计算的主要安装时间。

可以看出多个应用安装总用时比单个安装总用时要少。

同时有安装9个应用,实际只有5个安装了,apk实际点击安装的顺序跟截图上到下顺序一样。

有其它四个apk未安装的原因及安装实际耗时长如下log:

I PackageManager: Trying to bind to DefaultContainerService

W art     : Long monitor contention with owner PackageInstaller (1222) at java.lang.Object java.lang.Throwable.nativeFillInStackTrace!()(Throwable.java:-2) waiters=0 in boolean com.android.server.pm.PackageInstallerSession.isPrepared() for 11.210s

W art     : Long monitor contention with owner android.io (1117) at void com.android.server.pm.PackageInstallerService$2.run()(PackageInstallerService.java:556) waiters=0 in android.content.pm.IPackageInstallerSession com.android.server.pm.PackageInstallerService.openSessionInternal(int) for 11.238s

D InstallAppProgress: Installation error code: 1

D InstallAppProgress: Installation error code: 1

1:包安装服务io操作太费时导致一直查询互斥对象锁,PackageInstaller 也会为下个apk安装不断查询互斥对象锁。

针对这一点可以修改同步锁类型,如将现在的一直查询改为未获取锁则睡眠等待通知,或者优化io读写速度。

安装消息处理:

1:MCS_UNBIND 、INIT_COPY 、MCS_BOUND

优化PMS消息队列消息处理,比如当取到MCS_UNBIND,再查询后续5个消息是否有INIT_COPY 或MCS_BOUND消息,有则丢掉MCS_UNBIND 消息,继续处理后续消息,这样可以减少断开与连接DefaultContainerService开销。

参数调整:

目前平台dalvik 参数如下:

dalvik.vm.dex2oat-filter     verify-at-runtime

Dalvik.vm.usejit               true

vmSafeMode                     false    

以上参数都是比较优的参数配置,不宜修改。

frameworks\base\services\core\java\com\android\server\pm\PackageManagerServiceCompilerMapping.java

class PackageManagerServiceCompilerMapping {
    // Names for compilation reasons.
    static final String REASON_STRINGS[] = {
            "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "nsys-library", "shared-apk",
            "forced-dexopt", "core-app"
    };

Pm.dexopt.

frameworks\base\services\java\com\android\server\SystemServer.java

startOtherServices

-->

第一次启动或升级时:

public void updatePackagesIfNeeded() {

获取opt apk 和排序优先级

-->pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);

-->performDexOpt(pkgs, mIsPreNUpgrade /* showDialog */,
            getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT));

-->performDexOpt

-->performDexOptTraced 

-->performDexOptTraced

-->performDexOptInternal

-->performDexOptInternalWithDependenciesLI

-->performDexOpt

-->performDexOptLI

包安装

installPackageLI

-->mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
        null /* instructionSets */, false /* checkProfiles */,
        getCompilerFilterForReason(REASON_INSTALL));

PMS

PackageManagerService

-->performDexOpt(coreApps, false,
        getCompilerFilterForReason(REASON_CORE_APP));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值