作者:字节跳动终端技术——徐纪光

背景

iOS 业界研发模式多为 CocoaPods + Xcode + Git 的多仓组件化开发模型。为追求极致的研发体验、提升研发效率,对该研发模式进行了大量优化,但目前遇到了以下瓶颈,亟需突破:

  • pod install 时间长:编译优化绝大部分任务放在了 CocoaPods 上,CocoaPods 承担了更多工作,执行时间因此变长。
  • 编译时间长:虽然现阶段绝大部分工程已经从源码编译转型成二进制编译,但编译耗时依旧在十分钟左右,且现有工程基础上已无更好优化手段。
  • 超大型工程通病:Xcode Index 慢、爆内存、甚至卡死,链接时间长。

如何处理这些问题?

究其本质,产生这些问题的原因在于工程规模庞大。据此我们停下了对传统模式各节点的优化工作,以"缩小工程规模"为切入点,探索新型研发模式——动态研发模式 ARK。

ARK[1] 是全链路覆盖的动态研发模式,旨在保证工程体验的前提下缩小工程规模:通过基线构建的方式,提供线下研发所需物料;同时通过实时的动态库转化技术,保证本地研发仅需下载和编译开发仓库。

Show Case

动态研发模式本地研发流程图如下。接下来就以抖音产品为例,阐述如何使用 ARK 做一次本地开发。

演示基于字节跳动本地研发工具 MBox[2] 。

流程图

  1. 仓库下载

ARK 研发模式下,本地研发不再拉取主仓代码,取而代之的是 ARK 仓库。ARK 仓库含有与主仓对应的所有配置,一次适配接入后期不需要持续维护。

相较传统 APP 仓库动辄几个 GB 的大小,ARK 仓库贯彻了缩减代码规模这一概念。仓库仅有应用配置信息,不包含任何组件代码。ARK 仓库大小仅 2 MB,在 1 s 内可以完成仓库下载 。

在 MBox 中的使用仅需几步点击操作。首先选择要开发的产品,然后勾选 ark 模式,选择开发分支,最后点击 Create 便可以数秒完成仓库下载。

  1. 开发组件

CocoaPods 下进行组件开发一般是将组件仓库下载到本地,修改 Podfile 对应组件 A 为本地引用 pod A, :path =>'./A' ,之后进行本地开发。而在 MBox 和 ARK 的研发流程中,仅需选择要开发的组件点击 Add 便可进行本地开发。

动态研发模式 ARK 通过解析 Podfile.lock 支持了 Checkout From Commit 功能,该功能根据宿主的组件依赖信息自动拉取相应的组件版本到本地,带来便捷性的同时也保证了编译成功率。

  1. pod install

传统研发模式下 pod install 必须要经历 解析 Podfile 依赖、下载依赖、创建 Pods.xcodeproj 工程、集成 workspace 四个步骤,其中依赖解析和下载依赖两个步骤尤为耗时。

ARK 研发模式下 Podfile 中没有组件,因此依赖解析、下载依赖这两个环节耗时几乎为零。其次由于工程中仅需开发组件步骤中添加的组件,在创建 Pods 工程、集成工程这两个环节中代码规模的降低,对提升集成速度的效果非常显著。

没有依赖信息,编译、链接阶段显然不能成功。ARK 解决方案通过自研 cocoapods-ark 及配套工具链来保证编译、链接、运行的成功,其原理后续会在系列文章中介绍。

  1. 开发组件编译&调试

和传统模式一样通过 Xcode 打开工程的 xcworkspace ,即可正常开发、调试完整的应用。

工程中仅保留开发组件,但是依然有变量、函数、头文件跳转能力;参与 Index、编译的规模变小,Xcode 几乎不存在 loading 状态,大型工程也可以秒开;编译速度大幅提升。在整个动态研发流程中,通过工具链将组件从静态库转化成动态库,链接时间明显缩短。

  1. 查看全源码

ARK 工程下默认只有开发组件的源码,查看全源码是开发中的刚需。动态研发流程提供了 pod doc 异步命令实现该能力,此命令可以在开发时执行,命令执行完成后重启工程即可通过 Document Target 查看工程中其他组件源码。

pod doc 优点:

  • 支持异步和同步,执行过程中不影响本地开发。
  • 执行指令时跳过依赖解析环节,从服务端获取依赖信息,下载源码。
  • 通过 xcodegen 异步生成 Document 工程,大幅降低 pod install 时间。
  • 仅复用 pod installer 中的资源下载、缓存模块。
  • 支持仓库统一鉴权,自动跳过无权限组件仓库。

收益

体验上: 与传统模式开发流程一致,零成本切换动态研发模式。

工具上: 站在巨人的肩膀上,CocoaPods 工具链相关优化在 ARK 同样生效。

时间上: 传统研发模式中,历经各项优化后虽然能将全链路开发时间控制在 20 分钟左右,但这样的研发体验依旧不够友好。开发非常容易在这个时间间隔内被其他事情打断,良好的研发体验应该是连贯的。结合本地开发体验我们认为,一次连贯的开发体验应该将工程集成时间控制在分钟级,当前研发模式成功做到了这一点,将全链路开发时间控制在 5 分钟以内。

成功率: 成功率一直是研发效率中容易被忽视的一个指标。据不完全数据统计,集团内应用的本地全量编译成功率不足五成。一半的同学会在首次编译后执行重试。显然,对于工程新手来说就是噩梦,这意味着很长时间将在这一环节中浪费。而 ARK 从平台基线到本地工具链贯彻 Sandbox 的理念,整体上提高编译成功率。

写在最后

ARK 当前已经在字节跳动内部多业务落地使用。从初期技术方案的探索到实际落地应用,遇到了很多技术难点,也对研发模式有了新的思考。

相关技术文章将陆续分享,敬请期待。

扩展阅读

[1] ARK: https://github.com/kuperxu/KwaiTechnologyCommunication/blob/master/5.WWDC-ARK.pdf

[2] MBox: https://mp.weixin.qq.com/s/5_IlQPWnCug_f3SDrnImCw

字节跳动终端技术团队(Client Infrastructure)是大前端基础技术的全球化研发团队(分别在北京、上海、杭州、深圳、广州、新加坡和美国山景城设有研发团队),负责整个字节跳动的大前端基础设施建设,提升公司全产品线的性能、稳定性和工程效率;支持的产品包括但不限于抖音、今日头条、西瓜视频、飞书、懂车帝等,在移动端、Web、Desktop等各终端都有深入研究。

火山引擎应用开发套件MARS是字节跳动终端技术团队过去九年在抖音、今日头条、西瓜视频、飞书、懂车帝等 App 的研发实践成果,面向移动研发、前端开发、QA、 运维、产品经理、项目经理以及运营角色,提供一站式整体研发解决方案,助力企业研发模式升级,降低企业研发综合成本。

拒绝编译等待 - 动态研发模式 ARK的更多相关文章

  1. Java-马士兵动态代理模式

    Java-马士兵动态代理模式 模拟jdk的动态代理的实现原理, 这些东西没有必要写出来,写项目的时候一般用不上,主要是为了面试和理解原理: java动态代理有什么作用 作用非常大,在很多底层框架中都会 ...

  2. [转载]Web 研发模式演变

    原文链接:https://github.com/lifesinger/blog/issues/184 前不久徐飞写了一篇很好的文章:Web 应用的组件化开发.本文尝试从历史发展角度,说说各种研发模式的 ...

  3. Web 研发模式演变

    前不久徐飞写了一篇很好的文章:Web 应用的组件化开发.本文尝试从历史发展角度,说说各种研发模式的优劣. 一.简单明快的早期时代 可称之为 Web 1.0 时代,非常适合创业型小项目,不分前后端,经常 ...

  4. Qt 4.7.4 完美动态编译发布动态调试,以及静态编译发布

    首先是准备工作,去QT主页下载独立的QT类库安装包以及完整QT SDK安装包,还有QT Creator for windows 版 下载地址:http://qt.nokia.com/downloads ...

  5. 读 《 Web 研发模式的演变 》与《Javascript:世纪机器语言》

       读了两篇文章,内心还是很震撼的,在这之前,我学习知识都是直接找教程,翻阅资料,写几个小demo,没有去了解我所学的东西的发展历程,<Web研发模式的演变>这篇文章讲述了web的前世今 ...

  6. java jdk动态代理模式举例浅析

    代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...

  7. Web 研发模式的演变

    前不久徐飞写了一篇很好的文章:Web 应用的组件化开发.本文尝试从历史发展角度,说说各种研发模式的优劣. 一.简单明快的早期时代 可称之为 Web 1.0 时代,非常适合创业型小项目,不分前后端,经常 ...

  8. .Net Core Razor 预编译,动态编译,混合编译

    预编译 预编译是ASP .Net Core的默认方式.在发布时,默认会将系统中的所有Razor视图进行预编译.编译好的视图DLL统一命名为 xxx.PrecompiledViews.dll 或者 xx ...

  9. apache 静态编译和动态编译参考

    apache-2.2.22 编译安装笔记 一.静态编译     在使用./configure 编译的时候,即没有使用--enable-mods-shared=[module]或者--enable-[m ...

随机推荐

  1. 【LeetCode】85. Maximal Rectangle 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/maximal- ...

  2. 【LeetCode】438. Find All Anagrams in a String 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 滑动窗口 双指针 日期 题目地址:https://l ...

  3. Docker 与 K8S学习笔记(十)—— 容器的端口映射

    我们一般将应用部署在容器里面,而一个服务器上会有许许多多的容器,那么外界该如何访问我们的应用呢?答案是:端口映射. Docker可以将容器对外提供服务的端口映射到host的某个端口上,外网通过此端口访 ...

  4. 排列组合 "n个球放入m个盒子m"问题 总结

    求,盒子都可以分成是否不能区分,和能区分,还能分成是否能有空箱子,所以一共是8种情况,我们现在来一一讨论. 1.球同,盒不同,无空箱 C(n-1,m-1), n>=m0, n<m 使用插板 ...

  5. Java练习小题_求一个3*3矩阵对角线元素之和,矩阵的数据用行的形式输入到计算机中 程序分析:利用双重for循环控制输入二维数组,再将a[i][i]累加后输出。

    要求说明: 题目:求一个3*3矩阵对角线元素之和,矩阵的数据用行的形式输入到计算机中 程序分析:利用双重for循环控制输入二维数组,再将 a[i][i] 累加后输出. 实现思路: [二维数组]相关知识 ...

  6. 编写Java程序,测试包的使用和成员的访问权限

    返回本章节 返回作业目录 需求说明: 测试包的使用和成员的访问权限: 分别创建两个包,在这两个包下分别建立两个类. 其中某个类的某个方法需要引用用另一个包中某个类的某些成员属性. 被引用成员属性分别使 ...

  7. linux端口开放关闭 firewalld 使用

    systemctl status firewalld # 查看防火墙状态 firewall-cmd --zone=public --add-port=27017/tcp --permanent # m ...

  8. SQLServer中的CTE(Common Table Expression)通用表表达式使用详解

    概述 我们经常会编写由基本的 SELECT/FROM/WHERE 类型的语句派生而来的复杂 SQL 语句.其中一种方案是需要编写在 FROM 子句内使用派生表(也称为内联视图)的 Transact-S ...

  9. Log4j2完整XML参考(详细注释说明)

    1.说明 本文提供完整的log4j2.xml配置文件, 供开发中参考使用,可以作为模板, 配置对应实现如下常用的功能: 1.自动检测和重新加载配置,每10分钟(600s)检测一次 2.每个日志文件最大 ...

  10. Ranger-Yarn插件安装

    Ranger-Yarn插件ranger-0.6.0-yarn-plugin安装到Yarn的所有ResourceManager节点, 其他的NodeManager节点不需要安装. 登陆hdfs安装的用户 ...