手机APP安装包缩减方案

安装包大小对于产品很重要

主要有如下几个原因:

1、手机APP安装包的大小会影响用户是否愿意花费流量来下载此APP;

2、包体越大下载过程越长,用户取消下载的可能性越大;

3、在手机空间不足,用户需要清理手机空间时,包体越大的软件被清理的可能性越大;

4、一些预装软件,合作厂商会限定软件大小;

5、APP经过多次版本迭代,产生不少冗余代码和无用资源,会带来更高的学习和维护成本,也更容易出错。

文章将分三大部分进行讲解

一、iOS安装包的构成

二、安装包缩减方案

三、相关工具和知识介绍

1

iOS安装包的构成

选择ipa安装包,右键打开压缩包可见,iOS安装包主要由三部分组成:二进制可执行文件、资源文件(图片和视频)和其他文件(sdb数据库、plist文件等)。

以腾讯手机管家iOS版本安装包为例:发布包解压缩后是39.6M,其中二进制可执行文件共25.54MB占比64%,资源文件8.63MB,占比22%,其他文件大小总和占比14%。

2

安装包缩减方案

从第一部分可以看出,二进制可执行文件和资源文件是缩包方案的重点,下面分别从资源文件瘦身和二进制可执行文件瘦身两个方面进行详述。

一、资源文件瘦身

去掉无用资源

无用图片

原理:扫描项目里面所有png和jpg图片,然后在二进制文件、plist、xib里面匹配文件名字符串,得出图片没被引用

具体方法:在项目工程中,一般使用到图片资源均会在代码中使用字符串常量来引入图片资源。那么通过otool命令逆向__TEXT__cstring段来获取二进制文件中所有的字符串常量,并检查这些字符串常量是否匹配安装包中任意图片资源名(去除文件后缀,如@3x.jpg)。之后,没有被匹配的安装包中的图片资源就标记为疑似无用图片,然后做进一步排查处理。

因为在代码中,通过一些拼接字符串引用的图片资源在此方法中会被标记为无用图片,而实际中是有被使用到,这部分需要开发排查。

删除/压缩无用的视频文件、字体文件等其它资源

删除曝光率低功能或者变成网页形式

压缩资源

imageOptim进行无损压缩(主要是如文件的EXIF标签、颜色配置文件、作者等信息)。

imageAlpha进行有损压缩。

二、可执行文件瘦身

删除无用类

随着代码工程越来越大和研发历史越来越长,在工程中会存在一些类并没有被使用,而Objective-C的动态性,编译器会把项目里所有OC源文件编进可执行文件里,那么删除这些无用类文件必定能减少二进制文件的大小。取全部类列表classlist和在工程中被引用的类classrefs之差,就是无用类。

具体方法为:

通过otool命令逆向__DATA.__objc_classlist段和__DATA.__objc_classrefs段来获取当前所有oc类和被引用的oc类,其结果中包含类的段地址。

通过脚本解析,抽取出如上两个结果文件的差,也就是所有无用类的段地址集合

 “otool -o 二进制文件” 命令获得所有段的详细信息

④ 将步骤2中对应的段地址作为参数,在步骤3的结果中脚本解析出具体的类名

删除无用方法

由于Objective-C的动态性,它可以通过类名和方法名获取这个类和方法进行调用,所以编译器会把项目里所有OC源文件编进可执行文件里,哪怕该方法没有被使用到,删除这些无用方法必定能减少二进制文件的大小。取全部的类方法和被引用的类方法selrefs之差,就是无用方法。实践证明,这种方法会比较多,那么可以做个类方法大小排序,去处理大于一定阀值的无用类方法。

具体方法为:

用脚本从linkmap文件中解析二进制文件中所有的类方法(通过解析text代码段内容)

通过otool命令逆向__DATA.__objc_selrefs段获得被引用的类方法

如上两个结果文件相减就是没有使用到的类方法

步骤3结果结合linkmap文件,可以获取每个类方法的大小,并依据方法大小对类方法进行排序

监控可执行文件大小

对linkmap文件进行分析,根据序号累加每个obj文件在每个段的占用大小,从而计算出每个obj文件在可执行文件的占用大小,进而算出每个静态库、每个功能模块代码占用大小(__DATA.__bbs是代表未初始化的静态变量,Size表示应用运行时占用的堆大小,并不占用可执行文件,所以计算obj占用大小时,要排除这个段的Size)

具体方法为:

分别获得版本1和版本2中各个文件的大小

用脚本获取两个版本中文件大小的差值

对步骤2中的结果进行排序和具体分析

3

相关工具和知识介绍

一、Otool命令介绍

Otool可以提取并显示ios下目标文件的相关信息,包括头部,加载命令,各个段,共享库,动态库等等。它拥有大量的命令选项,是一个功能强大的分析工具,当然还可以做反汇编的工具使用。

使用方法:将安装包中的二进制文件作为otool的命令参数

二、LinkMap简介

LinkMap文件是Xcode产生可执行文件的同时生成的链接信息,用来描述可执行文件的构造成分,包括代码段(__TEXT)和数据段(__DATA)的分布情况。

使用方法:只要设置Project->Build Settings->Write Link Map File为YES,并设置Path to Link Map File,build完后就可以在设置的路径看到LinkMap文件了

LinkMap文件内容详解

 Object files

第一部分列举可执行文件里所有.obj文件,以及每个文件的编号

 Sections

第二部分是可执行文件的段表,描述各个段在可执行文件中的偏移位置和大小。

 Symbols

第三部分详细描述每个obj文件在每个段的分布情况,按第二部分Sections顺序展示。

      #Address                 Size                    File Name
      0x100001114       0x00000708 [  1]  -[MQQXLoadingView initWithFrame:]

原文发布于微信公众号 - 腾讯移动品质中心TMQ(gh_2052d3e8c27d)

原文发表时间:2016-11-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

Go语言并发与并行学习笔记

Go语言的并发和并行 不知道你有没有注意到一个现象,还是这段代码,如果我跑在两个goroutines里面的话: var quit chan int = make...

42150
来自专栏GopherCoder

『Go 内置库第一季:net/url』

其实这是一个比较小的内置函数,主要用在网络请求方面上,可能最多的用途也就是用来处理网络请求的参数。当然如何你经常在项目中编写restfulAPI, 那么你也可能...

16120
来自专栏欧阳大哥的轮子

从Xcode10不再支持libstdc++说起

众所周知从Xcode10起,苹果摒弃了对libstdc++库的支持转而支持libc++库了。这两个库在Xcode9甚至更早的版本就已经同时存在于系统中并且可供开...

42030
来自专栏Albert陈凯

2018-08-02 IntelliJ IDEA - Debug 调试多线程程序IntelliJ IDEA - Debug 调试多线程程序

https://blog.csdn.net/nextyu/article/details/79039566

22220
来自专栏Golang语言社区

Go语言并发与并行学习笔记

Go语言的并发和并行 不知道你有没有注意到一个现象,还是这段代码,如果我跑在两个goroutines里面的话: var quit chan int = make...

32560
来自专栏编程

近期做的比较好的web

? 本文作者:p0desta。 感谢p0desta。来稿,本文稿费100元。持续小广告:各位大佬有安全方面新的创作都可以向小编砸过来,将文章以Word形式发送...

22580
来自专栏安恒网络空间安全讲武堂

Sniper-OJ 练习平台多题WriteUp

题目 ### 图书管理系统(200) ### as fast as you can(50) ### md5-vs-injection(50) ### 2048...

81070
来自专栏点滴积累

Fish Shell

今天看到阮一峰同学的一篇博客(Fish shell 入门教程),讲述的非常详细、清楚,有兴趣的可以直接转去查看此文,本文仅提供一下个人使用心得。 一、fish ...

37960
来自专栏嵌入式程序猿

ARM cortexM4 异常处理(1)

在嵌入式开发中,尤其是在ARM的程序开发中,对异常的处理起着至关重要作用,那么cortexM4内核是如何管理异常的呢?我们将分几个小篇来讲解异常,今天先来了解下...

309110
来自专栏PHP实战技术

PHP经典面试题目汇总(上篇)

1、双引号和单引号的区别 双引号解释变量,单引号不解释变量 双引号里插入单引号,其中单引号里如果有变量的话,变量解释 双引号的变量名后面必须要有一个非数字、字母...

37270

扫码关注云+社区

领取腾讯云代金券