iOS 启动优化和安装包瘦身

1 启动优化

在iPhone的启动方式中,分为冷启动和热启动两种方式:

  • 1、冷启动(Cold Launch):从零开始启动APP ,需要系统新创建一个进程进行启动,这是一次完整的启动;
  • 2、热启动(Hot Launch):APP已经在内存中,在后台存活着,再次点击直接打开

我们一般说的启动优化是指: 冷启动时的优化;

要达到优化启动的目的,就需要知道在APP启动的时候,有哪些流程,做了哪些事情;

APP的启动过程是从:点击应用icon图标,到启动图展示,再到首页展示完成的过程:

打印查看启动时间:

通过添加环境变量可以打印出APP的启动时间分析(Edit scheme -> Run -> Arguments)

1、将DYLD_PRINT_STATISTICS设置为1

image.png

打印如下:


image.png

2、 如果需要更详细的信息,那就将DYLD_PRINT_STATISTICS_DETAILS设置为1

image.png

打印如下:

image.png

1.1 Main()函数执行前

dyld(dynamic link editor):动态链接器,用来装载Mach-O文件(可执行文件、动态库等)

  • dyld 加载可执行文件mach-o文件到内存中

    • 装载APP的可执行文件,同时会递归加载所有依赖的动态库
    • 当dyld把可执行文件、动态库都装载完毕后,会通知Runtime进行下一步的处理
  • runtime加载类和分类:

    • 调用map_images进行可执行文件内容的解析和处理
    • 在load_images中调用call_load_methods,调用所有Class和Category的+load方法
    • 进行各种objc结构的初始化(注册Objc类 、初始化类对象等等)
    • 调用C++静态初始化器和attribute((constructor))修饰的函数

所有初始化工作完成以后,dyld会调用main函数,接下里就是UIApplicationMain函数的流程

1.1.2 启动优化:

  • 1、dyld

    • 减少动态库、合并一些动态库(定期清理不必要的动态库)
    • 减少Objc类、分类的数量、减少Selector数量(定期清理不必要的类、分类)
    • 减少C++虚函数数量
    • Swift尽量使用struct
  • 2、runtime

    • 用+initialize方法和dispatch_once取代所有的
    • attribute((constructor))、C++静态构造器、ObjC的+load
  • 3、main

    • 在不影响用户体验的前提下,尽可能将一些操作延迟,不要全部都放在finishLaunching方法中
    • 按需加载

2. 安装包ipa瘦身

官方 App Thinning

App Thinning 是由苹果公司推出的一项可以改善 App 下载进程的新技术,主要是为了解决用户
下载 App 耗费过高流量的问题,同时还可以节省用户 iOS 设备的存储空间。

现在的 iOS 设备屏幕尺寸、分辨率越来越多样化,这样也就需要更多资源来匹配不同的尺寸和分 辨率。 同时,App 也会有 32 位、64 位不同芯片架构的优化版本。如果这些都在一个包里,那 么用户下载包的大小势必就会变大。

App Thinning 会专门针对不同的设备来选择只适用于当前设备的内容以供下载。比如:iPhone 6 只会下载 2x 分辨率的图片资源,iPhone 6plus 则只会下载 3x 分辨率的图片资源。

2.1、使用Asset

  • 使用Asset,将图片区分,对应的2X图片和3X图片,在上传appStore以后会做不同的变体,减少下载包的大小
image.png

例如我现在的项目,由于是老项目,所有的图片都是直接放在工程中的,所以打包的时候没有区分设备,都会直接打包的app包中;

如果使用了现在的Asset,将2x图和3x图区分开来,在appstore下载App的时候,会根据设备,只下载对应的图片,如果使用的是2x设备则只下载2x的图片,3x的设备只下载3x的图片;

这样就会减小从appstore下载时App包的大小。

2.2、删除无用的图片资源

项目中如果迭代过很多版本,图片资源就会很多,需求在更新的同时,所以可能会有很多无用的图片;

所以要使用一定的方法找到项目中不用的图片,并剔除掉;

  1. 通过 find 命令获取 App 安装包中的所有资源文件,比如 find /Users/daiming/Project/ - name。
  2. 设置用到的资源的类型,比如 jpg、gif、png、webp。
  3. 使用正则匹配在源码中找出使用到的资源名,比如 pattern = @"@"(.+?)""。
  4. 使用 find 命令找到的所有资源文件,再去掉代码中使用到的资源文件,剩下的就是无用资源
    了。
  5. 对于按照规则设置的资源名,我们需要在匹配使用资源的正则表达式里添加相应的规则,比如
    @“image_%d”。
  6. 确认无用资源后,就可以对这些无用资源执行删除操作了。这个删除操作,你可以使用
    NSFileManger 系统类提供的功能来完成。
  • 使用第三方软件:LSUnusedResources 链接
image.png

下载完成以后直接运行,然后选择工程所在的目录,直接search,如果项目比较大的话,search的时间也会比较久;

运行以后,直接会显示无用的图片,位置和大小:

image.png

这里选出来的图片需要斟酌一下再去工程里面删除,毕竟也是用正则表达式筛选出来的,有可能会有误差,如果检查过确实没用,就可以直接删除。

2.3、图片资源压缩

删除了无用的图片资源,有用的图片资源其实也是可以优化的,那做法就是将图片进行压缩和解压处理:

对于 App 来说,图片资源总会在安装包里占个大头儿。对它们最好的处理,就是在不损失图片 质量的前提下尽可能地作压缩。目前比较好的压缩方案是,将图片转成 WebP。WebP 是 Google 公司的一个开源项目。

  • 将图片转化成WebP,由于将图片转化成WebP和解压的过程消耗较大,所以可以将图片大于100k的进行转化,其他的小图片不做处理

2.4、删除无用代码

App 的安装包主要是由资源和可执行文件组成的,所以我们在掌握了对图片资源的处理方式后, 需要再一起来看看对可执行文件的瘦身方法。

可执行文件就是 Mach-O 文件,其大小是由代码量决定的。通常情况下,对可执行文件进行瘦 身,就是找到并删除无用代码的过程。而查找无用代码时,我们可以按照找无用图片的思路, 即:

  1. 找出方法和类的全集;
  2. 找到使用过的方法和类;
  3. 接下来,取二者的差集得到无用代码;
  4. 最后,由人工确认无用代码可删除后,进行删除即可。

2.4.1、使用Link Map 统计所有的方法和类

在build settings中搜索link map,然后设为YES;

设置build的输出路径,指定一个文件夹,然后指定输出文件的格式和名字,一般是txt格式,设置好路径后,直接运行,就会在指定的文件夹下生成一个.txt文件;

image.png

打开txt文件,以.o结尾的,都是生成的目标文件,如图:

测试demo我创建了两个类,一个YYPerson,一个YYStudent;

image.png

LinkMap 文件分为三部分:Object File、Section 和 Symbols。如下图所示:


image.png
  • Object File 包含了代码工程的所有文件;
  • Section 描述了代码段在生成的 Mach-O 里的偏移位置和大小;
  • Symbols 会列出每个方法、类、 block,以及它们的大小。

通过 LinkMap ,你不光可以统计出所有的方法和类,还能够清晰地看到代码所占包大小的具体 分布,进而有针对性地进行代码优化。

如果项目较为复杂,分析起来可能会很困难;

可借助第三方工具解析LinkMap文件:链接

运行以后直接打开txt文件:


image.png

这个软件能够清晰的看到有哪些类,以及每个类的大小;

2.4.2、使用 MachOView 统计所有使用过的类

在products中找到.app包,在finder中显示,然后右击显示包内容,找到可执行文件:

image.png

然后使用 MachOView打开可执行文件:

image.png

如图上所示,我们可以看到 objc__selrefs 和 objc__classrefs 以及objc__superrefs 这三个 section。

其实这3个里面都是通过消息机制,objc__msgSend()函数调用过的对象方法,类方法,类,元类等;

但是,这种查看方法并不是完美的,还会有些问题。原因在于, Objective-C 是门动态语言,方法调用可以写成在运行时动态调用,这样就无法收集全所有调用的方法和类。所以,我们通过这 种方法找出的无用方法和类就只能作为参考,还需要二次确认。

2.5 编译器优化

  • Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default设置为YES

  • 去掉异常支持,Enable C++ Exceptions、Enable Objective-C Exceptions设置为NO, Other C Flags添加-fno-exceptions

利用AppCode检测未使用的代码:菜单栏 -> Code -> Inspect Code

其实启动优化和ipa瘦身,在于平时的很多细节,比如如果是不用的图片,要立即删除,不用的类和方法,也要及时清理,我们一般不删除的原因是怕以后还有可能用到,但是一般都有版本控制,删除了以后再要用可以从之前的版本中去找;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345