写点什么

连 1.0 版本都没有,Uber 为什么会采用这样一项新技术?

  • 2022-06-06
  • 本文字数:4610 字

    阅读完需:约 15 分钟

连1.0版本都没有,Uber为什么会采用这样一项新技术?

本文最初发布于 Motiejus Jakštys 的个人博客。

免责声明:我在 Uber 工作,我的一部分职责是将zig cc引入公司。但这篇文章是我的观点,与 Uber 无关。

我日前在 Zig 的一场交流会上作了题为“Uber 引入 Zig”的演讲。本文从技术和社交两方面简单介绍了“Uber 是如何使用 Zig 的”,而主要的篇幅是介绍“我把 Zig 带到 Uber 的经验”。


本文要点:


  • Uber 使用 Zig 来编译其 C/C++代码。现在,Uber 只在Go Monorepo中使用bazel-zig-cc,但计划尽可能地将zig cc推广到其他需要 C/C++工具链的语言。

  • 与其他工具链相比,zig-cc 提供的 C/C++工具链的主要优势是:glibc 版本可配制与 macOS 交叉编译。

  • Uber 没有任何使用 zig-the-language 的计划。

  • Uber 与 Zig 软件基金会(ZSF)签署了一份支持协议,以优先修复我们提交的 Bug。ZSF 的财务报告有披露了合同额。

  • 感谢我的团队、Go Monorepo 团队、Go 平台团队、我的主管、财务、法律,当然还有 Zig 软件基金会,是他们让这种关系成为现实。到目前为止,这种关系已经带来了丰硕的成果。


Uber 技术栈简介

Uber 于 2010 年创立,已拥有超过 150 亿次的出行记录,为此,他们实现了很多很酷的创新技术。Go 和 Java 是通用服务器端语言,Python 和 Node 应用于特定的情况(如 Node 用于前端,Python 用于数据分析/ML)。C++被用于一些底层的库。在后端代码中使用其他语言的情况很少。


我们的 Go Monorepo 比 Linux 内核还要大,有几千名工程师在开发和维护。总而言之,很大。

Uber 是如何使用 Zig 的?

Abhinav Gupta是我们的来自 Go 平台团队的同事,其实他描述得比我好:我理解我们只是在使用 Zig 的 C 工具链,而不是将其作为语言使用。Zig 支持基于 C 的代码的交叉编译,能减少对系统 C 编译器的依赖。


Uber 技术栈发展历程

2018 年之前,Uber 的 Go 服务都有单独的存储库。2018 年,我们开始将这些服务大规模地迁移到 Go Monorepo。我的团队参与了第一波迁移——我仍然记得那有多复杂。

2019:寻求一个封闭式的工具链

当时,Go Monorepo 已经使用了一个封闭式的 Go 工具链。因此,用于构建 Go Monorepo 的 Go 编译器不会受系统上安装的编译器影响(如果有的话)。因此,无论在哪个环境下构建,都会使用相同版本的 Go。Bazel文档对此做了很好的解释


创建于 2019 年,没有太多变动。


C++工具链是一个编译 C/C++代码的程序集。不可避免地,我们的一些 Go 代码要使用CGo,所以它需要一个 C/C++编译器。然后,CGo 将 Go 和 C 部分链接成最终的可执行文件。


从 Go Monorepo 创建伊始,C++工具链就不是封闭式的:Bazel 会使用它在系统上发现的任何东西。也就是说,在 macOS 上使用 Clang,在 Linux 上使用 GCC(无论什么版本)。在 Bazel 中创建一个封闭式的 C++工具链是一项很大的工作(对于我们的 Go Monorepo 来说,需要花费数月时间),没有迫切的需求,也没有足够的痛苦,我们还无法接受做这样一件事。


现在,我们看下非封闭式 C++工具链的局限性:


  • 不能交叉编译。所以,如果需要 CGo 的话(我们的许多服务都需要),我们就无法在 Mac 上编译生成 Linux 上的可执行文件。这可以通过......而不是交叉编译来解决。

  • CGo 的可执行文件将链接到系统上发现的 glibc 版本。也就是说,在升级操作系统时(数月的努力),构建机群必须最后升级。否则,如果构建主机上 glibc 的版本比生产主机上的新,那么生成的二进制文件将链接到较新的 glibc 版本,就会与生产主机上的旧版本不兼容。

  • 我们无法使用新的编译器,即使它提供了更好的优化功能,因为我们在构建机群上运行的是旧版本的操作系统(只向后迁移编译器,而不迁移 glibc,本身就有风险)。

  • Go 的新版本的官方二进制文件在构建时使用的 GCC 版本,比我们的一些构建机器上的新。在这些机器上,我们不得不通过从源代码编译 Go 来解决这个问题。所有这些问题都很令人恼火,但不足以让我们在工具链上进行投资。

2020 年 12 月:需要 musl

我在做一个与 Uber 无关的小项目。该项目是用 Bazel 构建的,并使用了 CGo。我希望我的二进制文件是静态的,但 Bazel 并没有让这个过程变得简单。我花了几个晚上基于musl.cc创建了一个 Bazel 工具链,但没走多远,因为当时我无法深入理解 Bazel 的工具链文档,而且也没有找到一个好的示例可以参照。

2021 年 1 月:发现zig cc

2021 年 1 月,我发现了 Andrew Kelley 的博文“zig cc:一个功能强大的GCC/Clang替代品”。我推荐你读一下这篇文章;它改变了我对编译器的看法(也有助于你更好地理解本文接下来的内容,因为我是讲给 Zig 追随者听的)。综观 Andrew 的文章,zig cc有以下优势:


  • 完全封闭的 C/C++编译器,压缩包只有大约 40MB。这比 Clang 的标准发行版要小一个数量级。

  • 可以链接到通过命令行参数提供的 glibc 版本(例如,-target x86_64-linux-gnu.2.28将以 x86_64 Linux 为编译目标并链接到 glibc 2.28)。

  • 主机和目标平台是解耦的。不管是什么主机,针对目标平台linux-aarch64darwin-x86_64的设置都是一样的。

  • 与 musl 链接“只是一个不同的 libc 版本”:-target x86_64-linux-musl。我开始摆弄zig cc。我随便编译了一些程序,报告了一些问题。我想过把它做成一个bazel工具链,但有很多拦路的 bug 或缺失的功能。其中之一就是缺少 Bazel 所依赖的zig ar

2021 年 2 月:请求关注

向Zig报告了Bug。一个星期都没有动静。我每月捐 50 美元,希望“Zig 的人”能优先处理我所报告的问题。接着又是一个星期的沉默。然后我在#zig:libera.chat中扔了一枚炸弹:


<motiejus> 捐赠后,有什么规约可以用来“申请”开发时间吗?<andrewrk> ZSF只接受不附带任何条款的捐赠。<andrewrk> 你是从哪里获得了不同的印象吗?
复制代码


当时,我希望无论谁注意到这段对话都立即忘掉它。好吧,一年多以后,我又把这段话写在这里,看着玩吧。

2021 年 6 月:bazel-zig-cc 和 Uber 的 Go Monorepo

2021 年 6 月,Adam Bouhenguel创建了一个可以工作的bazel-zig-cc原型。基本功能没问题,但仍然缺少一些特性。后来,Andrew 实现了zig ar,这是一个真正可用的 bazel-zig-cc 所缺少的最后一块拼图。我集成了zig ar,完善了文档,并在Zig邮件列表中宣布了我创建的 bazel-zig-cc 分叉。至此,它对我的小项目是有效的。


在公告发布几周后,我为 Uber 的 Go Monorepo 创建了一个“WIP DIFF”:只是按照我的上线说明,天真地将其提交到我们的 CI。几乎所有的测试它都没有通过。


将 bazel-zig-cc 加入 Uber 的 Go Monorepo。


大部分失败都是由系统库依赖导致的。关于这一点,很明显,要想真正搭载 bazel-zig-cc 并编译所有的 C/C++代码,需要巨大的投入来消除对系统库的依赖,并偿还大量的技术债务。

2021 年底:回顾

  • Uber 有很多地方可以从一个封闭式的 C++交叉编译器中受益,但由于需要大量的投资,再加上没有足够的理由,所以没有获得资助。

  • bazel-zig-cc 有点用,但 bazel-zig-cc 和 zig cc 已知都存在 Bug。

  • 我无法实现必要的修改或 Bug 修复。所以,我试图实现zig ar,LLVM ar的一个小前端,但失败了。

  • 如果确定一个问题是 Zig 的问题,那么我们就无法预知它什么时候能引起 Zig 开发者的关注。有些问题几天内就得到了解决,有些则花了 6 个多月的时间,而捐款并不会改变zig cc的优先级。

  • Monorepo 上线差异(monorepo-onboarding diff)正在酝酿之中,等待时机。

2021 年底:Uber 需要交叉编译

我的任务是为 Uber 评估 arm64。撇开评估细节不说,我需要为 linux-arm64 编译软件。大量的软件!由于我们大部分的底层基础设施都在 Go Monorepo 中,我首先需要一个交叉编译器。


我终于有了一个实现交叉编译器的商业理由。现在,时间和金钱都可以投入了。“WIP DIFF”搭配zig cc是一个良好的开始,但距离终点还很远:团队不相信这是正确的事情,DIFF 更多的是一个原型。而且,要让 zig-cc 和 bazel-zig-cc 在任何情况下都可以使用,还有很多工作要做。


在一个大公司里引进这样的技术时,最重要的是风险管理。由于 Zig 是一项新技术(甚至连 1.0 都没有!),建议用它来编译我们所有的 C 和 C++代码很不寻常。我们应该做好至少十年内都使用它的计划。人们提了一些问题,并针对这些问题做了认真仔细的评估。为此,我真心感谢 Go Monorepo 团队,特别是 Ken Micklas,为这个未经证实的原型做了大量的工作和研究。

评估不同的编译器

我们需要一个交叉编译器,摆在我们面前的选项有两个:


  • grailbio/bazel-toolchain:使用普通的 Clang。没有风险。容易理解。显然,这是一个安全、恰当的解决方案。

  • ~motiejus/bazel-zig-cc:使用zig cc。有问题,有风险,不安全,不确定,没有人使用,但却是一个相当诱人的解决方案。与bazel-toolchain相比,zig cc额外提供了以下特性:

  • 可配置的 glibc 版本。使用grailbio,就需要 sysroot(本质上是一个带有系统库的 chroot,因此,程序可以与之链接),而这需要维护。

  • a working, albeit still buggy, hermetic (cross-)compiler for macOS.一个存在缺陷,但可以工作的封闭式 macOS(交叉)编译器。使用这两种方法中的任何一种处理 glibc 都没问题,然而,grailbio似乎不大可能编译到 macOS 上,更不用说交叉编译了。依赖开发者笔记本电脑上的系统编译器是不可取的,Go 平台团队亲身感受到了这一点,尤其是在 macOS 升级期间。


对于以 macOS 为目标封闭式工具链,选择的天平偏向了zig cc,连同它所有的缺陷、风险和不稳定性。


还有一个问题需要注意:我们知道,如果我们在重要的地方使用 Zig,会遇到问题,但又可能不具备解决这些问题的专业知识。作为一家大公司,我们该如何降低采用风险,确保严重的 Bug 及时得到处理?我们确信,ZSF 的出发点是好的:显然,如果我们发现并报告一个合理的 Bug,它就会得到修复。但是,怎么才能设定一个等待时间的上限呢?

金钱

50 美元的捐款无济于事,也许一份大的服务合同会有帮助?我四处打听,是否可以通过花些钱来降低“交叉编译器”的风险。获得管理层同意大约需要 10 分钟;起草、审批和签署合同大约需要 2 个月。


合同条款大致如下:


  • Uber 将问题报告到 github.com/ziglang/zig,并通知 Loris。

  • Loris 将其分配给 ZSF 的某人。

  • 解决问题。

  • 完成后,Loris 输入解决这个问题花费的时间。Uber 有权占用 ZSF 成员的时间。我们对 Zig 没有任何决定权或投票权。我们有权提出建议,但这些建议将和来自其他第三方的建议等量齐观。我们不能要求特殊权利,这在合同中有明确规定,我们也不希望那样。


合同签署了,电汇完成了,在 2022 年 1 月:


  • 我们与 ZSF 签订了服务合同,他们承诺优先处理我们提交的问题。

  • Go 平台团队承诺为我们的 C++工具链实现交叉编译和封闭。

合同金额是公开的,因为 ZSF 是非营利的。

2022 年及以后

2022 年 2 月,该工具链通过一个命令行标志(--config=hermetic-cc)做了限定。自此,你可以在 Uber 的 Go Monorepo 中调用zig cc了,不需要自定义补丁。


证明我们的提交队列登录了我的 WIP DIFF。


2022 年截至目前的时间线:


  • 今年 4 月,我在米兰演讲期间,我们向生产环境交付了第一个用 zigc-cc 编译的 Debian 软件包。

  • 今年 5 月,我们在所有的 Debian 软件包中启用了zig cc

  • 下半年,我们希望用zig cc编译所有的 cgo 代码,并将--config= hermatic -cc作为默认设置。

  • 下半年,我们希望将bazel- zigc -cc移到 github.com/uber 下。我们已经向 Zig 提交了一些问题,截至发稿时,所有的问题都已解决。有些是由 ZSF 单独处理的,有些则涉及面比较广,需要 ZSF、Uber 和 Go 开发者之间合作。

小结

我开始准备演讲,希望能给出一个大公司如何采用 Zig 的“运行手册”。然而,其实并没有什么“运行手册”;我为采用 zig-cc 所做的努力本可能会因为很多很多原因而失败。


回顾过去,我觉得要想获得成功,最重要的是在适当的时候有一个杀手锏特性。在我们的例子中,有两个:无需 sysroot 的 glibc 版本选择和交叉编译到 macOS。


原文链接:https://jakstys.lt/2022/how-uber-uses-zig/

2022-06-06 12:288415

评论 2 条评论

发布
用户头像
"交叉变异",好恐怖 😱
2022-06-13 09:05
回复
“编译”~哈哈,那处已修正
2022-06-14 10:44
回复
没有更多了
发现更多内容

Microsoft Remote Desktop Beta:无缝连接,跨平台办公新体验!

Rose

FontLab for Mac 轻松设计各种字体样式

Rose

解锁思维无限,Tinderbox 10 mac笔记工具让创意触手可及!

Rose

Jutoh for Mac(电子书制作软件)v3.18.4中文注册版

Rose

EasyAnimate-v3版本支持I2V及超长视频生成

阿里云大数据AI技术

AIGC 视频生成 EasyAnimate 图片生成视频

TaD+RAG-缓解大模型“幻觉”的组合新疗法

京东零售技术

人工智能 LLM 大模型幻觉 企业号2024年7月PK榜

蓝易云 - 在k8s中用label控制Pod部署到指定的node上

百度搜索:蓝易云

云计算 Kubernetes 运维 k8s Node

蓝易云 - PHP8的匿名函数-PHP8知识详解

百度搜索:蓝易云

php Linux 运维 Web 云服务器

Mac平台XLIFF文件编辑工具Xliff Editor for Mac

Rose

Three-Body Technology Lost Soul 1.6.0 千里洞箫音源插件

iMac小白

智启未来—我与小浣熊共绘高效办公新篇章

申公豹

小浣熊

边缘计算技术:为什么边缘计算平台如此重要?

3DCAT实时渲染

边缘计算 实时云渲染 边缘计算平台

如何挑选适合您项目的横道图软件

爱吃小舅的鱼

项目进度 横道图

蓝易云 - SAAS系统建站的优势是什么

百度搜索:蓝易云

云计算 运维 SaaS 云服务器 服务器租用

GPT-4与Data Analysis:【机器学习】自然语言处理的新前沿

蓉蓉

openai gpt4o

Three-Body Technology Phoenix Growl 1.6.0 鸾和唢呐音源插件

iMac小白

专业级音频制作软件:Logic Pro X for Mac 中文激活版

你的猪会飞吗

mac软件下载 Mac破解软件

小浣熊不单单是方便面,还是办公的“方方面面”

IT蜗壳-Tango

小浣熊办公助手:重塑数据分析新体验

乌龟哥哥

FiveNotes for mac(小型文本编辑器)v3.0.2激活版

Rose

拯救我的期末大作业,小浣熊助我高分轻松飘过

白日梦

小浣熊

Topaz Video AI 专注于完成视频增强任务:去隔行扫描、放大和运动插值

Rose

Nuro Audio Xpitch 1.0.2 音频修正校准插件

iMac小白

智能办公新篇章:商汤小浣熊助力前端数据分析革命

三掌柜

商汤 商汤科技 小浣熊家族 小浣熊

Three-Body Technology Heavier7Strings 1.7.0 虚拟吉他插件

iMac小白

光标快速移动和管理窗口的工具 Rectangle Pro for Mac

Rose

Proxyman Premium for Mac(网络调试和分析工具)v5.6.1激活版

Rose

FSNotes for mac 文本处理软件 包括纯文本、Markdown和富文本格式(RTF)

Rose

蓝易云 - 文本溢出解决text-overflow: ellipsis;不生效的问题

百度搜索:蓝易云

云计算 运维 云服务器 高防服务器 text-overflow: ellipsis;

网络安全作业二

白开水又一杯

连1.0版本都没有,Uber为什么会采用这样一项新技术?_语言 & 开发_Motiejus Jakštys_InfoQ精选文章