本文最初发布于 Halide 官方博客,原作者: Ben Sandofsky 。经授权由 InfoQ 中文站翻译并分享。阅读英文原文: One Weird Trick to Lose Size 。
你可能不知道的是,有些广为使用的社交网络 App 包大小达到了惊人的 400MB。如果每周发布一个新版本的话,一年下来用户将要下载 20GB 的数据。
自发布 Halide 以来,我们收到的最出乎意料的点赞是关于该 App 的大小。Halide 约 11MB,我们一年所推送的数据要少于那些社交网络 App 一次更新就要推送的数据。
有朋友会问:“难道你们没有使用 Swift 吗?”。Swift 会将自己的标准库捆绑到你的 App 中,这将增大 App 的大小。Halide 几乎是完全采用 Swift 开发的。
那么我们是怎样做到 App 瘦身的?让我们首先给出一点技术相关的内容。虽然它们主要来自对 QA1795 的概述,但是这些内容很重要。
QA1795:Reducing the size of my App
https://developer.apple.com/library/content/qa/qa1795/_index.html
测定,而非猜测
从 Xcode 中导出构建。在 Xcode 中选择“Save for Ad Hoc deployment.”。如果 App 支持“ app thinning ”(当前的 App 应该都支持),选择“Export for Specific Devices.”。确保你勾选了“Rebuild from bitcode”选项。
这样做,我们不仅能得到 App 软件包最终的大小,而且还能得到一份“App 瘦身报告”。依此报告去检查 App 软件包,找出其中最具影响的问题。
使用 Asset Catalog
将资源(Asset)保存在 Asset Catalog 中。在上传 App 时,Apple 会将其切分为特定于设备的版本,具有两倍尺寸屏幕的设备不会得到三倍的资源,反之亦然。
运行 PNG-crush
在将资源置入 Asset Catalog 前运行 pngcrush 工具。根据 QA1681 介绍,Xcode 将自动为处于 Asset Catalog 之外的 PNG 压减资源。
尝试对照片使用 JPEG
将 UI 资源及类似条条框框限定为 PNG,App 中的大部分资源很可能由此构成。但是如果资源中有一些照片,尝试一下 JPEG。稍加压缩就非常有助于 App 瘦身。
下面介绍工作的难点
完成这些工作难点,只会对上百 M 的大块头 App 取得数 M 的瘦身效果。我不知道该怎么婉转的告诉你,但你需要的是减少代码量。
选择正确的突破点
Halide 具有约一万五千行 Swift 代码,其中包括:一个实时视频处理器、大量的用户控制,以及我们的平台控制 AVFoundation。我们关注的是并非由我们自己编写的代码。
我借助 Auto Layout 削减了上千行的模板代码。很多开发人员依然执着于使用手工布局。可能他们对 Auto Layout 并不甚了解,或者由于他们辗转从他人那里听说 Auto Laytout 的性能堪忧(虽然事实并非如此)。
我已经看到太多的开发人员致力于开发内部使用的布局引擎,尤其是在一些大型企业中。这太疯狂了。Apple 在操作系统上绑定了精细的布局引擎,因此不要使用定制框架,这会导致 App 规模膨胀。
如果弃用 Interface Builder(IB),我们可以再削减 100K 大小。用户手册和设置页几乎完全是使用 IB 搭建的,使用了一些简单的约束。Camera UI 高层布局的管理也类似。虽然减掉 100K 很诱人,但是出于对短期内生产效率的考虑,值得让这一部分保持原样。
避免库膨胀
如果查看一些大型 App 的软件包,我们将会发现其中存在数十个第三方框架,大小从 100K 到数兆不等。
我并没有使用第三方软件库。虽然这有些走极端,但是我们的情况有些特殊。
这是因为并没有多少第三方软件库能适合我们的需要。在 iOS 开发社区中,有很多人在做 JSON 的映射,但是没有人关注对 DNG 文件的底层操作。
那么我前面所提及的视频处理的情况又如何?我能听到读者喊出来:“可扩展 GPUImage 实现!要自己造轮子,难道你疯了!”
就我自身在 Periscope 技术栈的工作经验而言,从 GPUImage 转到自己的内部解决方案将会收益颇丰。GPUImage 完全适用于不需要实时图像处理的业务。但是出于对 Halide 的长远考虑,我们需要实时渲染的功能。自建该组件是十分重要的。
因为 GPUImage 文件的规模,我从未考虑过它。我们自己造轮子,避免了在 App 中绑定 125 种不会被使用的过滤器。
在替代画蛇添足的大型框架问题上,PSPDFKit 具有异曲同工的成功之处:
很高兴宣布,我们使用 PSPDFKit 6.8 for iOS 重写了数字签名的核心实现,这改进了检测、验证,并给出了更好的错误报告。依此,我们还想方设法完全去除了对 OpenSSL 的依赖。这一过程削减了我们二进制程序的规模。
不要染上“不需重造轮子”的症状,我们有充分的理由避免使用软件库。
避免在分析和A/B 测试上浪费资源
我们不使用任何第三方分析或是崩溃报告服务。首先一点,我们很反感向广告商发送用户数据。不过我们先不谈理想情况,看看现实是怎样的。
数据并非是凭空产生的。在大型App 中,每个行为都会记录为一个分析事件。大型App 需要日志架构,去唯一识别用户、请求去重、日志缓存,并在失败时重试,诸如此类。这些加起来,代码量自然上去了。
A/B 测试更为恶劣。一个典型的社会网络 App 中充斥着非活动的 A/B 测试,没有人会回过头去清理干净。
避免分析和 A/B 测试的出发点并非是考虑到代码膨胀,这是我们的产品哲学。知道过多数据会改变你的主意。你发现自己疲于为大众用户做优化,而非在对真正能带来可见的变化而放手一搏。
基于这些原因,我们仅使用 Apple 分析。它工作良好,无需对代码做任何更改,并且是免费的。它尊重用户的隐私,需要用户主动参与。我们的用户选择参与率是 32%,完全适用于我们的需要。
Apple 分析需要你设置时间和地点。曾经我们并不确定应用最优价格,因此我们利用 Apple 分析做了一些试验。但是,我们对业务驱动的分析和产品研发间作了严格的区分,避免打扰后者。
减不下来?你需要调整目标
我们是一个两人组成的团队,通过销售产品而营利。我们的成长是完全健康的。如果得到用户的喜欢,他们会帮我们口口相传。我们乐于提供小型 App,我们认为这也会使用户开心。
我们的建议并不能对那些极大膨胀的 App 起到帮助。因为社交网络需要从广告商处谋利,而广告商则需要详细的分析用于广告定位。
大型 App 会具有上百名开发人员,他们组成了数十个团队,每个团队具有独立的季度目标。开发人员走得越快,实现了更多的目标,就越可能得到提拔。
这种考虑是可以理解的:“该软件库会节省我们一个星期的时间,但会对 App 增加一兆大小。那好,既然该 App 已经上百兆了,再增加一兆又何妨?”
大型企业充斥着一些这样的会导致未知结果的看上去“合理”的想法。
特性的交付并不会使一个开发人员得到技术职位上的升迁,而构建一个新的布局引擎则会。而记录了这些复杂技术的博客甚至被企业作为招聘的亮点。
唯一的解决方案是让高层领导给出声明:“我们将要对 App 瘦身”。不幸的是,技术 CEO 不会去使用只有 8G 存储的 iPhones,他们也不会在网速恶劣的地区居住。
这并非毫无回报的事情。自交付 Halide 以来,我们已经收到来自全球用户的大量消息,感谢我们保持 App 的小型化。
聚焦于客户是 App 瘦身的唯一可信理由。
感谢徐川对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论