zoukankan      html  css  js  c++  java
  • iOS App 瘦身

    现在的 App 是越来越大,内容是越来越多。开发商的角度总希望通过丰富的内容 精美的UI 来吸引更多的流量,然而越来越大的包也让用户望而生畏。用户的角度,用户可能为了解决小需求 就要下载动辄几十上百M的包 没必要嘛!

    自然 App 瘦身很有必要!总结一下,App 瘦身 可以从以下几个角度来考虑:

     首先我们来看 App 构成:

     

    1、可执行文件瘦身 

     (1)编译器优化 配置编译选项

     Xcode 是使用 Clang 来编译的,Clang 的优化选项在其文档 https://clang.llvm.org/docs/CommandGuide/clang.html 可以查阅得到。

     XCode 中设置的选项最终会反应在 Clang 命令上,打开Xcode 的 build log 可以看到设置的 Xcode 选项最终 是如何传递给 Clang的。

       你可以根据需求 直接在 Other C Flag 中添加其它参数。比如你在 Optimization Level 中设置 Fastest Smallest[-Os] 和在 Other C Flags 中添加 -Os 效果是一样的

       Build Settings->Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest[-Os],这个选项会开启那些不增加代码大小的全部优化,并让可执行文件尽可能小。

      (2)优化指令集   指令集选择放弃 armv7 armv7s

     iOS设备支持的指令集

     armv6:   iPhone, iPhone 3G, iPod 1G/2G

     armv7:   iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G, iPad, iPad 2, iPad 3, iPad Mini

     armv7s:  iPhone 5, iPhone 5c, iPad 4

     arm64:   iPhone X,iPhone 8(Plus),iPhone 7(Plus),iPhone 6(Plus),iPhone 6s(Plus), iPhone 5s, iPad Air(2), Retina iPad Mini(2,3)

     arm64e:  iPhone XSXRXS Max 

     自身工程可以选择不支持 armv7 和 armv7s, 分别对应 4s 和5c的 指令集 现在这些机型已经非常少了,移除影响不大

     

     静态库优化

    项目中会引入一些第三方静态库。比如微信SDK
    lipo -info libWeChatSDK.a 
    Architectures in the fat file: libWeChatSDK.a are: armv7 armv7s i386 x86_64 arm64 
    
    通过以下指令瘦身 lipo libWeChatSDK.a
    -thin armv7 -output libWeChatSDK-armv7.a

      (3)去除符号信息

     iOS 的调试符号是 DWARF 格式的,相关概念如下:

    • Mach-O: 可执行文件,源文件编译链接的结果。包含映射调试信息(对象文件)具体存储位置的 Debug Map。
    • DWARF:一种通用的调试文件格式,支持源码级别的调试,调试信息存在于 对象文件 中,一般都比较大。Xcode 调试模式下一般都是使用 DWARF 来进行符号化的。
    • dSYM: 独立的符号表文件,主要用来做发布产品的崩溃符号化。dSYM 是一个压缩包,里面包含了 DWARF 文件。

     Strip Style 表示的是我们需要去除的符号的类型的选项,其分为三个选择项:

    • All Symbols: 去除所有符号,一般是在主工程中开启。
    • Non-Global Symbols: 去除一些非全局的 Symbol(保留全局符号,Debug Symbols 同样会被去除),链接时会被重定向的那些符号不会被去除,此选项是静态库/动态库的建议选项。
    • Debug Symbols: 去除调试符号,去除之后将无法断点调试。

       (Levels选项内)Generate Debug Symbols  设置为NO。这个配置选项应该会让你减去小半的体积。注意这个如果设置成NO断点不生效。

      Strip Linked Product  是去除 生成产品的符号信息

      Strip Debug Symbols During Copy 设置为YES。这个是将那些拷贝进项目包的三方库、资源或者 Extension 的  Debug Symbol 去除掉,同样也是使用的 strip 命令。这个选项没有前置条件,所以我们只需要在 Release 模式下开启,不然就不能对三方库进行断点调试和符号化了。

     

      Deployment Postprocessing 位置为 YES   ( Deployment Postprocessing 是 Strip Linked Product,Dead Code Stripping, Strip Debug Symbols During Copy 等选项的总开关 )

      Make Strings Read-Only 设为 YES       复用字符串字面量

      Linking Dead Code Stripping 设置成 YES        消除无效代码

      Symbols hidden by default 设置为 YES            函数符号隐藏

      Strip Swift Symbols             对 Swift 符号 进行 strip

     (4)BitCode 

      BitCode 是一种程序中间码,其实就是 LLVM IR 的一种编码形式

      当提交程序到App store上时,Xcode会将程序编译为 BitCode。然后App store会再通过这个 BitCode 编译为 对应不同平台和指令集(如iPhone 或 iPad )的可执行的64位或32位程序。当 Apple 升级系统版本等,Apple 可以通过 BitCode 来重新生成你的 App,而无需你 重新提交。 注意:如果你 引用的第三方库不支持 BitCode 那么你开这个选项是不支持的,会报错。 

      由于最终的可执行文件是 Apple 自动生成的,同时会产生新的符号表文件。所以当我们需要查看分析崩溃日志的时候,我们使用原本打包生成的 dSYM 符号化文件是无法完成符号化的。所以我们需要在上传至 App Store 时需要勾选 Include app symbols for your application to receive symboilcated crash logs from Apple。勾选之后将我们的dSYM文件上传至Apple, Apple 会给我们重新生成 dSYM,然后我们根据需要就可以在 Xcode -> Organizer 或者 iTunes Connect 中下载App 实际对应的 dSYM 文件来进行符号化。

     (5)Dead Code Stripping

    C/C++/Swift 等静态语言编译器会在 link 的时候移除未使用的代码,但是对于 Objective-C 等动态语言是无效的。因为 Objective-C 是建立在运行时上面的,底层暴露给编译器的都是 Runtime 源码编译结果,所有的部分应该都是会被判别为有效代码。 基于代码扫描来清理无效代码,但是动态语言可以通过字符串来直接调用,所以代码扫描的方式,出来结果往往并不是很精确。

      基于代码扫描有以下三种方向:

      基于 clang 扫描

    基本思路是基于 clang AST。追溯到函数的调用层级,记录所有定义的方法/类和所有调用的方法/类,再取差集。具体原理参考 如何使用 Clang Plugin 找到项目中的无用代码,目前只有思路没有现成的工具。

      基于可执行文件扫描

    Mach-O 文件中的 (__DATA,__objc_classlist) 段表示所有定义的类, (__DATA.__objc_classrefs) 段表示所有引用的类(继承关系是在 __DATA.__objc_superrefs 中);使用的方法和引用的方法也是类似原理。因此我们使用 otool 等命令逆向可执行文件中引用到的类/方法和所有定义的类/方法,然后计算差集。具体参考iOS微信安装包瘦身。  具体也可以参考 Snake。 

      基于源码扫描

    一般都是对源码文件进行字符串匹配。例如将 A *a、[A xxx]、NSStringFromClass("A")、objc_getClass("A") 等归类为使用的类,@interface A : B 归类为定义的类,然后计算差集。基于源码扫描 有个已经实现的工具 - fui,但是它的实现原理是查找所有 #import "A" 和所有的文件进行比对,所以结果相对于上面的思路来说可能更不准确。

        可以通过  simian 来分析 无效代码

      (6) 通过 LinkMap 瘦身

    在 Project->Build Settings->Write Link Map File为YES,build完后就可以在设置的路径看到LinkMap文件。我们可以从 linkmap 文件中统计出 每个目标文件 .o 和每个静态库 .a 占用的体积。 通过对LinkMap文件的分析,可以得知每个模块可执行文件占用大小,来进行针对性的移除。

      (7) 通过 machoview 来分析 代码块

     machoview 这里下载 http://sourceforge.net/projects/machoview/

     

    2、资源优化与压缩

    移除重复的资源

     fdupes 是Linux下的一个工具,可以在指定的目录及子目录中查找重复的文件。fdupes通过对比文件的MD5签名,以及逐字节比较文件来识别重复内容。这个工具是开源的!地址前面已经给出。

     删除没用到的资源

     推荐使用 FengNiao 来自动删除没用到的图片资源。

    资源压缩

    ImageOptim 是一款优秀的无损图片压缩工具 通过优化压缩参数 移除无用的文件元数据 和 不必要的颜色配置来实现图片的无损压缩。使用了 ImageOptim压缩后 在 Xcode 中记得要设置 COMPRESS_PNG_FILES 为NO 否则 Xcode 会按照它的规则再来优化一遍 png 图片,结果是会让你的图片比你压缩前更大! 

     苹果自身提供了  On-Demand Resources in iOS Tutorial 按需加载资源的思路给我们提供了一种阶段性加载资源的途径,但是苹果的服务器对于中国用户来说实在是慢的不行,所以不建议采取这种方式。

     

    参考: 

    1、iOS APP安装包瘦身实践

    2、Xcode中和symbols有关的几个设置 

    3、iOS 安装包瘦身(上篇)

    4、iOS 安装包瘦身(下篇)

    5、抖音品质建设 - iOS 安装包大小优化实践篇

    6、今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小

  • 相关阅读:
    [WEB]对于"Refused to execute script from 'http://xx.xx.xx/yy/zz.js' because its MIME type ('') is not executable, and strict MIME type checking is enabled."问题的解决办法
    Linux下为python3.6.5配置环境变量
    Yii2自带验证码实现
    php在Nginx环境下进行刷新缓存立即输出,实现常驻进程轮询。
    php文件锁解决少量并发问题
    过滤各种不合法标签数据
    wampserver下升级php7
    php异步请求(可以做伪线程)
    linux 定时执行shell
    记一次工单排查经历(修改显示时间)
  • 原文地址:https://www.cnblogs.com/lesten/p/14285479.html
Copyright © 2011-2022 走看看