【硅谷问道】Chris Lattner 访谈录(上)

话题

  • Chris Lattner 是谁?
  • Xcode 的编译器 LLVM 背后有怎样的故事?
  • Swift 诞生的前世今生,封闭的苹果为何要拥抱开源?
  • 说好的 ABI 稳定性何时能推出?

Chris Lattner 是谁

 

教育背景

  • 伊利诺伊大学 PHD

工作经历

  • 2005年 - 2017年供职苹果,前开发部高级总监,架构师
  • 2017年开始,担任特斯拉副总裁,负责自动驾驶

主要成就

  • Swift 之父,主要作者
  • LLVM 之父,主要作者
  • Clang 主要贡献者

荣誉

  • 2016年被评为“创造未来的25位当世天才”
  • 2013年获得 ACM 系统设计大奖

访谈实录

自我介绍

1. 你怎么看待自己?

我是个程序员。我喜欢写代码。我编程有很长时间了。

我在读博的时候就开始写 LLVM 了。当时 LLVM 是我的博士研究项目,我想把它做成工业界中颠覆性的产品。当时我异想天开,尝试了各种架构设计,想解决以往编译器所有的弊端 -- 结果当然没有如愿。我毕业后,就希望能接着搞 LLVM ,当时只有苹果允许我入职之后继续设计并实现 LLVM 。我想都没想就加入了苹果。

LLVM

2. 说说 LLVM(Low Level Virtual Machine)到底是什么吧

  • 先说编译器:编译器是把程序员的代码翻译成机器可以理解的语言的工具;
  • 再谈 LLVM:一个模块化和可重用的编译器和工具链技术的集合,Clang 是 LLVM 的子项目,是 C,C++ 和 Objective-C 编译器,因为多模块的复用,所以提供了惊人的快速编译,比 GCC 快3倍。

3. LLVM 是一开始就作为一个完整的编译工具来使用的吗?还是有什么其他故事

LLVM 当时是为了解决一个小问题而开发的:当使用OpenGL 函数库的时候(Mac OS 10.4 和 10.5环境下),比如你要调用这个函数,glVertex3f(),编译器必须将其转化为特定的GPU可以理解的数据。但是这带来一个问题:市面上有海量的GPU,每个GPU的性能和参数也不尽相同,所要求的数据格式也不同。这时 LLVM 可以产生很小的一部分代码去解决这个问题,这是 LLVM 诞生的初衷。

4. LLVM 的 bytecode 和 Apple 现在的 bitcode 有什么不同?

这是历史遗留问题。一开始 LLVM 是开源的,所有代码在转成二进制时就叫做 bytecode -- 因为 java 当年就是这么叫的。当时这一部分有很多问题:比如不能扩展,无法兼容,非常脆弱。

然后就到了 LLVM 2.0,当时我重新设计了架构,采用的就是 Bitcode 机制。LLVM 2.0 将所有代码以比特流(bit stream)而不是字节流(byte stream)的形式来编码。这就是 bitcode 这一术语的由来。

主要的工作流程就是现将代码转成比特流,然后相应处理。处理完后再将编码传到其他地方去。

5. Bitcode 这个机制比直接传输二进制有什么好处

好处那是多了去了。首先 编译器工作起来会越来越好。因为通过Bitcode机制,它可以通过编译不同代码来存储各种优化方法,这样下次碰到类似代码,它就会自动启动相关优化机制,使得效率提升。还有个好处是 LLVM 可以让芯片的兼容性变得很好。因为 Apple 每年都在芯片上推陈出新,它们转化为二进制的规则都不尽相同,LLVM 只要每次重新编码并传输成比特流就好了。

当然 Bitcode 也不是万能的。比如它不能解决 32位的 APP 在64位机器上的兼容问题。这个问题其实应该依靠代码逻辑。

谈管理

6. 在职业生涯中,你在 LLVM 上鞠躬尽瘁,但我们发现这几年你更多的工作是在管理上,你自己怎么看这种转变的?

我虽然做管理了,但是我依然喜欢写代码,而且我每天都写,因为我就是个极客嘛。而且,其实我很早就开始做管理的工作了。不过我一直是作为技术领导人的角色带 2 到 3 个人的,我只是在写代码方面把把关,给他们提提建议这样。

后来带的人多了,队伍也大了。我不仅管程序员,还管小组经理和其他技术领导人。虽然我一直喜欢写代码,但是管理对我来说是一个必须要去做的事。现在回过头来,我觉得干得还不错。跟大家一起工作之后我知道很多事协同工作效果更好,和同事交流你就会理解他们的想法,这样我就可以制定更好的计划路线。

其实我没感觉整个过程有什么不同。直到今天我还夜以继日、废寝忘食得写代码,我并不是坐那边动动嘴皮子,指挥别人干活的老板。我其实每个周末都在写代码,我很忙的。

Swift

7. Swift 是如何诞生的?在苹果这样一个大厂,决定做出如此巨大的变革,同时还是在封闭的环境下,你是如何一步步实现的?

首先,苹果内部所有的项目都不尽相同 -- 工作流程、战略规划、实施细节,到最后发布。Swift 也一样,没有可比性。因为苹果本身就是小组单兵作战模式 -- 每个组负责不同的大方向,组里自己计划和工作,甚至招人都是各自招。

言归正传,契机发生在2010年了。当时好像是我们刚刚完成了 Clang 对 C++的支持。你也知道 C++ 写起来有多丑,但是做个编辑器支持 C++,完善 C++ 这门语言就是另一回事了,我们当时搞了好久终于完成的时候特别有成就感。当然 Clang 远没有到达完美的地步。

我又扯远了。除了做 Clang 以外,无论是 C语言,C++,还是 Objective-C,都有一些我不是很满意的地方。所以我就想要不我们搞个新的语言来吧。新的语言要越简单越好。一开始大家都没认真,后来我跟很多同事聊了之后觉得新语言的计划可行,而且大家都很亦可赛艇。于是我们就用业余时间开始顶层设计和写代码。

现在问题来了,因为我们已经有 Objective-C 了。虽然它有几个地方很丑,比如老是用 "@",每句结束了还要打分号,但是这些并不妨碍它是一门伟大的语言。所以,我们为什么要开发新语言,而不是把精力花在优化 Objective - C 上?

 

原因有三。

第一,如果我们大幅优化 Objective - C,把很多 Swift 的特性加进去,这对开发者来说是灾难性的,因为他们要对原来的 APP 要进行大幅修改;

第二,Objective - C 很多特性积重难返,比如它安全性上的问题;

第三,Objective - C 是基于 C 开发的语言,所以你无论怎么优化,它必然有 C 语言自身的缺陷。

于是我们就动手做 Swift 了,它的背后有着数百人的努力: 支持 Xcode,开发 Playground,兼容调试器和编译器。我个人感到最骄傲的一点是,我们并不打算自己内部把它做到完美 -- 我们开源、我们依靠社区,这样一门语言才能在无数开发者的实战中得到检验和改进,我想这才是 Swift 最棒的地方。

8. 你之前在优化 Objective-C 的时候,有没有想到什么地方是未来 Swift 可以用得到的?

ARC。我们其实一直都在争论是用垃圾回收机制(garbage collection)还是 ARC,后来决定了是 ARC。

另一个是模块化,我们也将这一部分的经验带到了 Swift 开发中。

其实,很多数组和字典方面的语法优化本来是计划在 Objective - C 上面的。但是后来我们开发了 Swift,于是这些改进被直接用在了新语言上,所以大家会在写 Swift 的时候觉得似曾相识,因为本来这些就是 Objective-C 的升级版本嘛。

我可以透露一个有意思的事情。我们在做 Swift 的时候,很多 iOS 开发者,包括苹果内部的工程师,都在吐槽我们这几年在 Objective - C 上毫无建树,都在说你们为什么不做这个那个。我们当然不能告诉他们我们在全力开发 Swift,而他们所要的语法功能我们都会给。

9. 苹果内部对于 Swift 的使用情况和开发是怎么看得?

Swift 团队对于开发上有明确的目标和计划,应用二进制接口(ABI)的稳定性一直是我们的首要目标。很多人很喜欢我们开源的 Swift Playground。同时 iOS 系统内置的 Music App 也是 Swift 写的。其实用不用 Swift 主要是技术和开发方面的考量,苹果内部同时得兼顾稳定性和开发效率,这不是说大家喜不喜欢这个语言的问题。

Swift 刚发布的时候,内部很多组都很惊讶:我们已经有了 Objective-C,为什么还要搞新的 Swift?而且 Objective-C 本身就很不错,开发起来也很顺手。后来渐渐 Swift 成熟了,大家也爱上了这个新生儿。

内部其实对于 Swift 一个很大的顾虑在于,苹果的所有开发必须兼容32位机器,而32位的应用都采用了 Objective-C 的 runtime 机制。这就要求 Swift 团队也弄出个类似的机制,或者弄个兼容的方案,否则 Swift 无法与 AppKit 适配。

10. 开源后的 Swift 发展态势喜人,你对此有什么看法?

开源之后,Swift 发展之好让我咋舌,然而这也是问题所在。

当年我们开源了 LLVM 和 Clang,它们也发展喜人。我们的对手 AMD 们完全跟不上我们。但是跟 Swift 比起来,它们的发展也太慢了,LLVM 和 Clang 开源后完全没有 Swift 这么火。

Swift 就不同了,开源一年之后,我们就有了上百万的开发者在使用这门语言 -- 我和很多有丰富开源经验的老工程师都吓了一跳,这简直了!然后我们每天收到无数的邮件和 pull requests,要求更新这个、要求优化那个,我们的节奏完全被打乱了。我们如何规划开发?我们如何把 Swift 的开发导向一个正确的方向?这些问题随着时间的推移和经验的积累,慢慢找到了解决之道。

我现在觉得开源这个决定至关重要。一来大家会帮着优化;二来我们有个巨大的论坛,在那里大家可以畅所欲言,全世界的人都在帮着 Swift 进步,这真的很棒。我们虽然没有一开始就具体计划要开源,但是苹果内部当时都觉得 Swift 肯定有一天要开源。

苹果与特斯拉

 

11. 苹果好像一直是个封闭的公司,你们内部对于开源怎么看?

苹果其实有开源的传统。 LLVM 虽然不是始于苹果,但是最终是苹果完成并将其开源。Clang 则完完全全是生于斯开源于斯。还有其他工具,比如 LLDB,libc+,以及compiler-rt 都是如此。

所以对于 Swift 来说,开源只是时间问题。当年从 Swift 1.0 到 Swift 2.0,一切都乱七八糟。当时我们重点在开发错误处理机制,还有协议、拓展等一系列重要的功能。所以开源 Swift 1.0,并不是一个好选择,因为这些重要的东西都没有,而这些开发是当务之急。当 Swift 2.0 到来的时候,我们才有空去开源、去做社区拓展和论坛搭建。开源社区可以帮我们修复细节,我们这时候可以更多的投入在架构设计上。

12. 苹果最让你怀念的是什么?

苹果是这样一个公司,你可以选择你喜欢的东西,然后努力工作去实现它,最终你的工作会落实在产品上,影响亿万计的人。

有很多公司,你可以努力工作,但是不一定能做你喜欢的东西;你做出来东西,可能会被束之高阁;你做的产品,也许最后很幸运的发布,但是并不一定有很多人会用。在苹果,你的工作可以真正改变世界,很有成就感。

13. 你觉得到特斯拉之后,还会努力为 Swift 做出贡献吗?

特斯拉的工作非常有挑战性,这是我最开心的地方。我现在还没入职,所以也不知道我之后对 Swift 能做多少工作。也许我还会夜以继日的发 Pull Request,也许我就周末写写 Swift 代码。我应该会从各个方面 -- 无论是顶层设计还是具体代码实现,与苹果的核心团队合作,为这个语言做贡献。

其实我一直想说,Swift 只是我在苹果工作的一小部分,我花了大量的时间在其他事情上。实际上在苹果我也就晚上或者周末有空写写 Swift。我希望到了特斯拉之后我还能花同样的精力和时间在 Swift 上,毕竟我对这门语言统治世界充满期待。

ABI 稳定性

14. 现在 Swift 已经到了第3个版本了。我们也知道ABI稳定性的追求一直是你们的目标,但是它也一直被各种事情拖延。你对此有什么计划吗?或者说你从拖延中学到了什么经验教训吗?

ABI 推迟有两个原因。

第一是因为 Swift 的开发进程中有很多不确定性。当 Swift 开源之时,一堆人对我们提 pull request,提各种各样的 issue。这样我们就不得不去花大量的时间去维护开源社区,而不是专心去做计划内的工作。

第二个原因是,尽管稳定的 ABI 很重要,但是对于开发者来说,稳定的 ABI 对他们来说没有明显的好处,他们更关心是语法和兼容上的稳定和优化。所以我们后来修改了计划,语法和兼容上的稳定性被定为是最先要实现的目标。这样当 Swift 3.1 或者 Swift 4.0 出来的时候,大家不用担心语言上的转化会让 Xcode 崩溃,或是需要大家整个重构 APP。Swift 3.0 主要就是实现这个目标。

 

15. 稳定的 ABI 什么时候推出?他会赶在异步和并发模型之前吗?

Swift 现有的内存管理机制对 ABI 稳定性造成了不小的影响。有些底层逻辑还需要调整,比如 getter 和 setter 的生成以及属性的内存分配问题,苹果内部正在做这件事,这之后我们才能完成 ABI。至于并发模型啥的就跟 ABI 没有关系了。

很多人担心 Swift 4.0 的时候苹果能不能推出稳定的 ABI,因为毕竟工作量太大。ABI 的工作正在井然有序得进行,而且对于开源社区来讲推出稳定的 ABI 至关重要。Ted (Chris Lattner 之后的 Swift 领导人)有一件事说对了,现在 Swift 当务之急就是让编译器更稳定,让错误处理更方便,提高编译速度,并且将 Swift 拓展到大规模系统中。

我在想 Swift 4.0 的时候究竟能看到什么。也许没有稳定的 ABI,但是一定会有重要的新功能加入。

ABI 将允许未来 Swift 版本开发的应用程序和编译库可以在二进制层次上与 Swift 3.0 版本的应用程序和编译库相互调用。这样,ABI的稳定性将保证一定程度的二进制兼容性,并且第三方更容易发布二进制库。另外,ABI 将允许删除需要的 Swift 标准库和二进制文件,就像目前情况下通过Xcode创建的 iOS 和 OS X 应用程序一样。

补充

 

LLVM.png

补充:LLVM的三层结构

  • 第一层:Clang 编译器,负责编译各种语言
  • 第二层:代码优化器,通过模块化操作优化代码,是 Bitcode 逻辑的主要部分
  • 第三层:代码翻译器,针对不同平台和 GPU 将代码翻译成机器语言

补充:LLDB,llbc++,compile rt

  • LLDB: 一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器。LLDB 绑定在 Xcode 内部,存在于主窗口底部的控制台中;
  • libc++,libc++ ABI: 高性能 C++ 标准库实现,支持 C++ 11
  • compiler-rt:为 LLVM 和 Clang 设计的编译器扩展函数库。针对 __fixunsdfdi 和其他目标机器上没有一个核心 IR (intermediate representation) 对应的短原生指令序列时,提供高度调优过的底层代码生成支持。

ABI 是什么?

Application Binary Interface,中文名:应用二进制接口。是 APP 和 操作系统、其他应用之间的二进制接口。它包括以下细节:

  • 数据类型的大小、布局和对齐;
  • 调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;
  • 系统调用的编码和一个应用如何向操作系统进行系统调用;
  • 以及在一个完整的操作系统ABI中,目标文件的二进制格式、程序库等等。