写点什么

砍掉百万行代码,这些巨头玩不转超级应用了?

  • 2024-03-06
    北京
  • 本文字数:4194 字

    阅读完需:约 14 分钟

大小:1.97M时长:11:27
砍掉百万行代码,这些巨头玩不转超级应用了?

为谋求生存,Grab 将其应用软件“瘦身”四分之一;而为了提升研发效率,Shopify 一年删除了超 300 万行代码。

 

在马斯克一心要将推特变成微信那样的“超级应用”后,超级应用似乎成了大家追求的应用方向。但是,东南亚超级应用开发商 Grab 却在做相反的事:给自己“瘦身”。

 

“随着应用程序功能的不断扩展,存储空间或者网络带宽有限的新用户,越来越难以获得一致且高质量的体验。”Grab 博文里说道。

 

Grab 应用最初只是一款叫车软件,但在接下来的十年间逐渐将功能扩展到食品配送、包裹快递、移动支付等多个领域,甚至还针对司机端提供贷款服务。截至 2020 年 9 月,Grab 业务已经涵盖了东南亚 8 个国家,共 319 座城市。

 

但并不是每位用户都用得到这么多功能,而冗余代码又继续留存在应用当中,导致 Grab 软件代码如今已增长至 400 万行。

 

早在 2019 年,Grab 就发现了一个现实问题:其应用软件的大小几乎每个月增长 1%,导致已不太适合东南亚地区的普通智能手机,故而降低了用户体验并最终威胁到其吸引更多用户的业务发展愿景。

 

2021 年第三季度,这家总部位于新加坡的公司启动了“盆景项目(Bonsai project)”,希望控制应用软件的下载大小与存储空间占用。在六个月时间内,Grab 成功将性能提高了 26%,并在一定程度上削减了对存储空间的需求。

 

关注每次提交的应用大小

 

Grab 超级应用的布局发展是非常快的:2012 年 Grab 推出打车服务;2016 年 GrabPay 上线;2017 年 GrabPay 衍生到打车之外的支付领域,随后成立 Grab Financial,短短两年完成支付宝到蚂蚁金服十年的旅程。

 

打通支付体系后,Grab 开始为自己的超级应用引入更多服务。2018 年,Grab 还发布面向开发者的应用平台 GrabPlatform,也是达成东南亚唯一超级应用目标的基础。通过 GrabPlatform,合作伙伴可以将 Grab 集成到他们的服务中,也可以将他们的服务集成到 Grab 中。

 

但越来越多的业务板块,带来的挑战也是显而易见的。Grab 主 App 包含很多业务板块,这些业务之间互相独立、又相互依赖。相对其他业务,Grab 的“打车”主业务具有极高的稳定性要求,因为一旦系统出现故障会造成千上万人滞留,可能会演变为社会事件。

 

在盆景项目之前,Grab 一直采用应用捆绑方法,并根据特定设备提供定制化的 APK 安装文件。Grab App 拥有超过 100 名 Android 工程师和多个协作团队,每周发布一次,每次发布都会有数百次提交。因此,团队密切监控每次提交时应用程序大小的变化。

 


监控 APK 大小的变化

 

他们还会监控应用变更,对合并至主分支的每一项提交建立调试 build 进行 APK 文件大小控制,采用 R8/Proguard 作为“代码收缩器”。

 

在资源优化方面,Grab 团队也做了很多努力,包括尽可能使用矢量图像而非像素图像,在需要像素图像的特殊情况下,Grab 采用 webp 格式而不是 png,以便用更好的图像压缩来最小化应用大小。Grab 启用的资源配置仅支持 Grab 应用程序主动使用的语言,其在 resourceConfig 中删除所在地区不使用的语言,从而减少不必要的资源开销。另外,Grab 还为第三方库建立了审查流程,评估其规模对应用程序的影响。

 

但事实证明,这一切还不够。Grab 超级应用如今不仅有超过 400 万行代码,还与数百个第三方库集成,应用规模还是变得很大,以至于 Grab 目标市场区域中普遍存在的低端设备和互联网基础设施差异,不足以支撑这样规模应用的运行,进而阻碍了其业务发展。

 

Grab 还引用了谷歌在 2020 年的一项研究结果:应用程序大小对转化率有负面影响,应用程序 APK 大小每扩展 6MB,转化率就会下降 1%。因此,“瘦身”对于 Grab 来说势在必行。

 

400 万行代码怎么来的?

 

在盆景项目中,Grab 希望通过一切必要手段来量化、削减并控制其应用软件的大小。

 

Grab 首先开发了一款定制化工具,用以分析捆绑文件中的二进制文件。他们将这款工具命名为 App Size,并整合进工作流程当中。

 

该工具会将数据发送至 Grafana 实例,借此监控并观察特定设备所需下载的应用软件大小、识别哪些库和模块占用的存储空间最大,并创建出一份大文件清单。Grab 计划在不久的将来对该工具进行开源。

 

为了帮助应用软件有效瘦身,Grab 决定不再添加任何新内容,而是先找到导致软件体量膨胀的“罪魁祸首”。“我们的重点是优化 dex 文件大小、优化资源并消除重复与冗余部分。”Grab 方面解释道。

 

根据分析,Java/Kotlin 代码是这款应用软件的主要体量“贡献者”,因此成为优化工作的重中之重。在这部分代码中,R 类占据主要比例。博文指出,“R 类不仅包含对自身资源的 ID 引用,同时也涉及对所传递依赖项中资源的 ID 引用。”

 


“也就是说,如果模块 A 依赖于模块 B,而模块 B 又依赖于模块 C(模块 A -> 模块 B -> 模块 C),那么即使模块 A 不会直接用到这些资源,模块 A 的 R 类也将包含对模块 B 和 C 中资源的 ID 引用。也正因为如此,模块化项目中的 R 类才经常积累下数百万行代码。”

 

这家超级应用开发商还发现,其应用软件中包含超过 1500 个模块和第三方库,这进一步导致 R 类体量失控。也正因为如此,某些提交尽管没有添加大量资源、库或者代码,也仍然会显著提升应用的整体大小。

 

Grab 开发团队成员回忆道,“这些波动与依赖关系图的变化有关,也进一步凸显出 Transitive R 类的影响。”此外,根据默认规则,R 类还会被长期保留下来。

 

为了修复此问题,开发团队决定在自动化测试完成后更新 AGP 版本,在瘦身的同时避免无意中删除仍在使用的 R 类字段。这项测试的内容,是通过脚本来搜索使用 R 类反射的实例。各第三方库会进行反编译并应用同样的脚本。除此之外,Grab 还修改了 R8 配置规则以查找非必要冗余。

 

进一步控制膨胀

 

在发现大文件时,盆景项目鼓励开发团队在确定不必要时将其删除,包括考虑将其转移至云服务器,或者转化为更加经济的文件格式。

 

Grab 甚至在字体上也做了简化。现在这款超级应用删除了很少使用的字体、并清除了重复字体。Grab 软件目前正努力采用统一字体。Grab 在帖子中解释道,“我们建议采用单一主字体样式,并在编程中灵活融入不同的字体变化,从而立足同一字体实现多种显示效果。”

 

开发团队发现,某个特定库自己就占用了该应用存储空间的 8%。Grab 删除了该库,同时努力清理其他库中的重复函数。

 

Grab 应用还提供了一个附加功能,以开关形式远程禁用某项功能,这同样有助于削减软件体量。“这能帮助我们轻松关闭那些实验性功能,或者可能引发问题的特定功能。”博文作者指出。

 

Grab 还在不断探索更多应用瘦身途径,包括常见的 UI 设计组件及动态交付实验。Grab 还在考虑为各开发部门分配强制性的“应用大小配额”。

 

Grab 自豪地宣布,“通过优先考虑代码优化、资源管理、模块化与资产捆绑,我们在提高用户体验的同时,也实现了对应用软件体量的显著优化。”

 

但应用软件膨胀的问题恐怕很难快速得到遏制,特别是在东南亚地区,随着智能手机使用量的持续增长,消费者对产品价格的承受能力却没有同步提升。

 

应用到底“做小”还是“做大”?

 

做减法的不只 Grab。

 

Shopify 是一站式 SaaS 模式的电商服务平台,有百万家企业使用其平台创建了在线店铺。“对于商家来说,每一毫秒都至关重要。这意味着我们的应用在保证易扩展的同时,还不能被复杂的架构拖慢运行速度。”Shopify 副总裁、工程部门负责人 Farhan Thawar 说道。

 

因此在做重要更新时,Shopify 都致力于消除复杂性并提升性能。

 

2023 年,Shopify 删除了超 300 万行代码、归档了大约 6800 个未使用或者不必要的 GitHub 仓库、合并了 702 条由机器生成的用于清理僵尸代码的 PR,重要的是将一个用于在线购物网站的后台进程内存使用量从 3GB 左右减少到了 400MB 左右。

 

另外,Shopify 将后台开发人员的反馈机制提速了 20 倍,包括在计算机资源减少了 35% 的情况下,将持续集成的速度提高了 50%。团队还大幅改进了 Storefront Renderer 对 Ruby 垃圾回收机制的使用效率,使得平均 GC 时间减少 56%,GC 的 P99 时间减少了 80%。

 

所有措施也带来了不错的效果:8 万个列表的页面,加载时间从 20 秒左右缩短到 400 毫秒左右;跨境订单关税的计算速度。我们的 p99 从 500ms 左右下降到了 80ms 左右;管理后台搜索结果的响应速度提高了 7 倍以上等,此外 Shopify 的研发效率也提升了 20 倍。

 

但与 Grab、Shopify 相反,微信却在肉眼可见的变大。

 

上个月,微信因为安装包变大上了一次热搜。微信推送了 iOS 平台 8.0.47 正式版更新时,网友发现,软件更新信息显示,本次安装包的大小竟然达到 712.8MB。相较于之前的版本一下增加了几十 MB。当时有网友发文称,自己的微信占用内存达 50 多 GB,其中有 47GB 是聊天记录。可以看出,微信占的内存中,聊天记录占比高达 75%-95%。

 

而在 2022 年时,微信就因“安装包 11 年膨胀了 575 倍”登上热搜。当时有博主扒了微信安装包后发现,lib 文件夹大小为 337MB,占用了该微信版本空间的 54%,里面是 157 个各种第三方动态库。据 UP 主分析,这些库大多是因为“面向复制粘贴编程”:缺少什么功能就去网上找实现这种功能的“轮子”再缝合进 App 里,安装包体积会因为各种动态库的加入变得越臃肿。

 

对比初代微信,8.0.24 版本中各种单元都增加了 500 倍以上,尤其是 string 字符串,从最初的 1845 个到新版中暴涨近 150 万个。UP 主还调侃道:“可见新版微信中有 99.9% 的内容都是垃圾,真正实现聊天部分的代码可能只占 0.1%。”

 

还有一些细节表明了微信的开发非常混乱,如“收款到账”的音频放在 assets\sound 路径下,而同为音频文件的“微信电话铃声”却直接放在了 assets 路径下。

 

“微信把自己当操作系统来做 App,什么打车、快递、外卖、游戏,不管用不用得上都给你塞进去,然后淘宝、支付宝、美团等各种 App 又来占一遍你的手机空间,导致手机提升的性能和增加的内存都用来运行这些垃圾功能的代码,而用户丝毫没有选择权。”这名 UP 主最后总结道。

 

不过,微信里的应用对性能要求没有那么高,用户可以接受适当的等待。同时,微信依托腾讯背后的基础设施能力,可能一时间还不会想给自己做减法。

 

相关链接:

https://www.theregister.com/2024/03/05/grab_downsizes_app/

https://engineering.grab.com/project-bonsai

https://mp.weixin.qq.com/s/GjYOxoSUM2l37_1GjEueJg

https://www.bilibili.com/video/BV1cB4y1b77n?spm_id_from=333.337.search-card.all.click

https://www.infoq.cn/article/rwMNMXHvMg7TtAKu-UOh?utm_campaign=geek_search&utm_content=geek_search&utm_medium=geek_search&utm_source=geek_search&utm_term=geek_search

2024-03-06 14:1310352

评论 2 条评论

发布
用户头像
跟开发者团队的习惯也有关系,开发者都倾向于添加新代码,而不是删除旧代码,即便知道旧代码已经弃用了也不会删除
2024-03-09 16:52 · 北京
回复
用户头像
张"小而美"有恃无恐
2024-03-06 15:31 · 江苏
回复
没有更多了
发现更多内容

Go类型转换和类型断言可别搞混了

王中阳Go

golang 高效工作 学习方法 面试题 11月月更

React源码中的dom-diff

夏天的味道123

React

老板拍脑袋决策,团队群魔乱舞

填空时光

决策 团队内耗 企业敏捷

TiDB常用SQL

TiDB 社区干货传送门

性能调优 集群管理

详解Native Memory Tracking之追踪区域分析

华为云开发者联盟

开发 内存 华为云

# 分布式数据库新秀TIDB初探

TiDB 社区干货传送门

TiDB 底层架构 TiDB 源码解读

将业务从mysql迁移至TIDB,有哪些需要注意的?

TiDB 社区干货传送门

管理与运维 应用适配 大数据场景实践

诚迈科技深耕汽车操作系统领域,获评优质供应商

科技热闻

TiFlash 源码阅读(六) DeltaTree Index 的设计和实现分析

TiDB 社区干货传送门

React性能优化的8种方式

xiaofeng

React

AntDB入选《2022爱分析·信创厂商全景报告》

亚信AntDB数据库

AntDB 信创 国产数据库 aisware antdb AntDB数据库

10年码农生涯经验总结,聊聊工作中18种接口优化方案!

Java全栈架构师

Java 数据库 程序员 程序人生 性能优化

低代码实现探索(五十三)后台逻辑的控制

零道云-混合式低代码平台

react源码中的协调与调度

flyzz177

React

《关键信息基础设施安全保护要求》于明年五月正式实施

行云管家

网络安全

CQRS与Event Sourcing

胖子笑西风

架构 DDD CQRS Event Sourcing #java

技术分享 | 多测试环境的动态伸缩实践

LigaAI

云原生 自动化测试框架 测试环境 测试自动化 kubenetes

TiFlash 源码阅读(八)TiFlash 表达式的实现与设计

TiDB 社区干货传送门

安防厂商在企业数字化转型中的机遇和挑战

慕枫技术笔记

AIOT 11月月更

注意 ! !|95% 的应用程序中发现错误配置和漏洞

SEAL安全

配置管理 软件供应链安全 漏洞管理

GaussDB CN服务异常实例分析

华为云开发者联盟

数据库 华为云 GaussDB

React生命周期深度完全解读

夏天的味道123

React

TiFlash 源码阅读(七)TiFlash Proxy 模块

TiDB 社区干货传送门

React中常见的TypeScript定义实战

xiaofeng

React

react源码中的hooks

flyzz177

React

React的5种高级模式

夏天的味道123

React

使用Docker踩坑,排查完问题之后,又涨知识了

程序员小毕

Java Docker 程序员 程序人生 后端

react源码中的fiber架构

flyzz177

React

教你一招,安全的从 MySQL 切换到 TiDB

TiDB 社区干货传送门

迁移 实践案例

《全国一体化政务大数据体系建设指南》发布,隐私计算将如何发挥作用?

洞见科技

技术分享 | TiUP工具 - TiDB集群滚动升级核心流程解析

TiDB 社区干货传送门

砍掉百万行代码,这些巨头玩不转超级应用了?_架构_褚杏娟_InfoQ精选文章