欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS 性能优化(二)安装包瘦身

程序员文章站 2022-03-23 22:14:30
随着版本迭代和业务的堆积,安装包会越来越大,安装包变大也带来了其他隐患,比如之前在App Store下载的应用超过150MB时,是无法使用流量下载的,只能连接到无线局域网下载。虽然现在可以设置允许所有App使用蜂窝数据下载,但是有个“超过200MB时请求许可”的选项可能是默认勾选的,而且对流量和手机存储空间敏感的用户,有时候安装包的大小就决定了是否拥有这个用户,所以,对于安装包的瘦身是App发展和优化过程中不可避免的重要一步。...

目录

前言

一、安装包组成

二、资源瘦身优化

2.1 无用资源删除

2.2 资源压缩

2.3 图片管理方式

2.4 动态下载资源

三、可执行文件优化

3.1 找到方法和类的全集:Link Map 文件分析

3.2 找到已使用的方法和类: Mach-O 文件

3.3 使用AppCode

四、编译选项优化

总结


前言

随着版本迭代和业务的堆积,安装包会越来越大,安装包变大也带来了其他隐患,比如之前在App Store下载的应用超过150MB时,是无法使用流量下载的,只能连接到无线局域网下载。虽然现在可以设置允许所有App使用蜂窝数据下载,但是有个“超过200MB时请求许可”的选项可能是默认勾选的,而且对流量和手机存储空间敏感的用户,有时候安装包的大小就决定了是否拥有这个用户,所以,对于安装包的瘦身是App发展和优化过程中不可避免的重要一步。

一、安装包组成

iOS的安装包就是ipa,把一个ipa文件将后缀.ipa修改为.zip,然后将其解压出来,在Payload中的.app 选择显示包内容,就可以查看里面的资源文件。

.app 里面的主要内容

  • _CodeSignature:存放文件的 hash 列表。里面有一个文件 CodeResources ,这个文件是一个属性列表,包含 bundle 中所有其他文件的列表。这个属性列表只有一项 files,这是一个字典,键是文件名,值通常是 Base64 格式的散列值。如果键表示的文件是可选的,那么值本身也是一个字典,这个字典有一个 hash 键和一个 optional 键(布尔值 true)。它的作用是用来判断一个应用程序是否完好无损,能够防止不小心修改或损坏资源文件。

    iOS 性能优化(二)安装包瘦身

  • 一些.bundle文件:bundle是一种标准化的层次结构,保存了可执行代码以及代码所需要的资源。bundle文件可以理解为一个资源包,用于存储图片、音频、文本、nib文件等,方便在其他项目中引用包内的资源。bundle包是静态的,不参与编译,也就意味着,bundle 包中不能包含可执行的文件。它仅仅是作为资源,被解析成为特定的二进制数据。从.app的包里可以看到,.bundle文件基本上都是一些SDK制作的。
  • Assets.car:把放在Assets.xcassets中的图片(除了AppIcon和LaunchImage,这两种图片是直接放在包中的)打包后统一压缩成一个Assets.car的文件,减小包的大小。
  • 一些.nib文件:使用xib创建的文件。
  • .plist:一些属性列表文件。
  • Frameworks:Framework 是一种打包方式,将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发。
  • 一些.png、.jpg、.mp3、.mp4等形式的图片和音视频资源。

二、资源瘦身优化

资源瘦身主要是去掉无用资源压缩资源,资源包括图片音视频文件配置文件等,其中图片资源应该是用的最多的。无用资源是指资源在工程文件里,但没有被代码引用。

2.1 无用资源删除

相关业务或模块移除后,对应的图片资源没有删除,造成安装包里面积累很多无用图片,清理的办法也比较简单,就是根据图片的名字在Xcode里全局搜索,如果没有搜到可能就是没有用到的图片,但是并不完全肯定,也有代码里有可能是通过字符串拼接的方式使用了图片。

查找并删除这些无用的图片资源流程是这样的

  1. 查找:使用find命令获取选定的目录下的所有指定类型的资源文件(比如png、jpg、gif等)。
  2. 匹配:使用正则匹配在代码中使用到的图片名,可以设置匹配规则,比如为了方便循环创建,这样命名的@"icon_%d"。
  3. 删除:所有的资源文件减去用到的资源文件就是无用的资源文件了,对这些无用的资源再确认一下删除就可以了。

推荐一个好用的开源工具 LSUnusedResources,使用起来很简单,搜索速度和匹配的准确性也很高。

除了图片资源外,音视频资源,像.json、plist、README.md 等这样的无用文件也可以删除掉。

2.2 资源压缩

对于有用的资源文件,可以通过无损压缩减少占用空间。尽量使用8-bit的PNG图片,比32-bit的图片能减少4倍的压缩率。由于8-bit的图片支持最多256种不同的颜色,所以8-bit的图片一般只应该用于一小部分的颜色图片。例如灰度图片最好使用8-bit。

2.3 图片管理方式

工程中的图片资源主要有两个方式管理,一种是在项目中添加文件夹存放,另一种是放在Assets.xcassets管理。推荐使用Assets.xcassets管理,因为它会把里边的所有 png 格式的图片打包成一个Assets.car文件,压缩比率比文件夹管理图片要高,而且可以根据不同的设备,不同的分辨率设置相应的图片。

2.4 动态下载资源

有些非必要的文件资源可以放在服务器,结合本地缓存策略,比如主题、皮肤、音乐这样的资源。

三、可执行文件优化

App 安装包主要是由资源文件和可执行文件(Mach-O)组成的,可执行文件大小是由代码量决定的。通常情况下,对可执行文件进行瘦身,就是找到并删除无用代码的过程。方法和图片资源清理类似:先找出方法和类的全集,再找到使用过的方法和类,取二者的差集就得到无用代码,人工二次确认后删除。

3.1 找到方法和类的全集:Link Map 文件分析

Xcode build产生的Link Map文件能比较直观的反映出程序各部分的文件大小情况,对于减少包体积很有帮助。

获取 LinkMap :将 Build Setting 里的 Write Link Map File 设置为 Yes,然后指定 Path to Link Map File 的路径就可以得到每次编译后的 LinkMap 文件了。我们只修改一下生成的 Link Map文件的路径就可以了,后缀名不要修改。

iOS 性能优化(二)安装包瘦身

LinkMap 文件分为三部分:Object files、Section 和 Symbols。

  • Object files:代码工程中所有文件编译后的目标文件.o;
    iOS 性能优化(二)安装包瘦身
  • Section:描述了代码段在生成的 Mach-O 里的偏移位置和大小,包括代码段(__TEXT)和数据段(__DATA)的分布情况;
    iOS 性能优化(二)安装包瘦身
  • Symbols:符号相关信息,会列出每个方法、类、block,以及它们的大小,第一列Address 是在文件中的偏移位置,第二列Size 是大小,第三列File 是对应上面Object files 中的文件编号,第四列Name 是文件名。可以看到黄色框框部分跟上图Object files 是对应的。
    iOS 性能优化(二)安装包瘦身

通过对 LinkMap 的分析,我们不但可以统计出所有的方法和类,还能够清晰地看到代码所占包大小的具体分布,从而有针对性地对代码进行优化。对Symbols的分析还可以通过方法的二进制重排来提升冷启动速度(本篇不做过多介绍)。

3.2 找到已使用的方法和类: Mach-O 文件

Mach-O是Mach Object的缩写,是Mac/iOS上用于存储程序、库的标准格式。常见的Mach-O文件比如iOS开发好的代码打包好后就是Mach-O格式的文件。​​​Xcode编译完工程会生成一个可执行程序,查找方式也简单,首先在Xcode的Preferences里找到这个路径:

iOS 性能优化(二)安装包瘦身

在这个文件夹下找到对应的工程文件名/Build/Products/Debug,进入这个目录下,就可以找到我们的可执行文件了。

iOS 性能优化(二)安装包瘦身

iOS 的方法都会通过 objc_msgSend 来调用。而objc_msgSend 在 Mach-O 文件里是通过 __objc_selrefs 这个 section 来获取 selector 这个参数的。所以,__objc_selrefs 里是被调用了的方法,__objc_classrefs 里是被调用过的类,__objc_superrefs 是调用过 super 的类。通过 __objc_classrefs 和 __objc_superrefs,我们就可以找出使用过的类和子类。可以通过MachOView来查看 Mach-O 文件里的信息。

iOS 性能优化(二)安装包瘦身

对比Link Map文件就可以找出没有用到的类和方法了,但是Objective-C 是动态语言,方法可以在运行时动态调用,通过这种方法找到的无用代码还需人工确认才可以删除。

3.3 使用AppCode

如果不想这么麻烦地去分析对比,推荐一个好用的工具 AppCode,代码量不是很大时,AppCode通过静态分析可以快速帮我们找出没有用到的文件和方法,使用方式是在 AppCode 里选择 Code->Inspect Code 就可以进行静态分析。

iOS 性能优化(二)安装包瘦身

分析结果也是清晰明了,包括:

Not implemented methods:没有实现的方法;

Key value coding:KVC相关,比如使用KVC访问了@private修饰的成员变量;

Unused class:没有用到的类;

Unused import statement:无用类引入声明;

Unused instance variable :无用的实例变量;

Unused method:没有用到的方法;

Unused property :没有用到的属性;

Unused parameter :无用参数;

Unused local variable :无用的局部变量;

Unused value :无用的值;

Unused macro :无用的宏;

Unused global declaration :无用全局声明。

iOS 性能优化(二)安装包瘦身

但是检测结果并不是完全可靠,只是为我们优化代码提供参考方向,最好还是人工确认一下,不要完全相信工具。

四、编译选项优化

Xcode 支持编译器层面的一些优化优化选项,可以让我们在更快的编译速度、更小的二进制和更快的执行速度之间*选择想要的优化程度。

  1. Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default设置为YES,目前Xcode已经默认打开的,老项目注意检查;
  2. 去掉异常支持,Enable C++ Exceptions、Enable Objective-C Exceptions设置为NO,Other C Flags添加-fno-exceptions;
  3. Strip Debug Symbols During Copy设置为YES,这个是将那些拷贝进项目包的三方库、资源或者 Extension 的  Debug Symbol 去除掉。这个选项没有前置条件,只需在Release模式下开启,否则就不能对三方库进行断点调试和符号化了;
  4. Build Settings -> Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest,这个选项会开启那些不增加代码大小的全部优化,并让可执行文件尽可能小;
  5. Enable BitCode设置为YES;

总结

业务的不断堆积迭代,总会产生一些无用的资源,所以安装包瘦身要定期清理这些无用文件和代码。除了自己写的代码外对用到的三方库也可以做检查优化,比如有的库还支持Mac的i386和x86_64架构处理器,这部分代码就可以根据实际情况删除;对比SDK和三方库的导入对ipa大小的影响,使用满足需求的较小库;项目中重复方法抽离出来等,这些优化可能对安装包的大小影响很小,但是积少成多,形成对ipa大小敏感的习惯也能帮助我们写出效率更高的代码。对安装包瘦身的探索还有很长的路走,本文也只是列举了一些常用的瘦身方案,对于庞大的项目,操作起来也是如履薄冰,还好在没有影响业务和正常功能使用的情况下,我们的ipa减少了大约15MB,优化之路还在继续,以后还会补充更多的方案。

本文地址:https://blog.csdn.net/weixin_44867400/article/details/108299765

相关标签: iOS开发 ios