摘要:Swift 之父 Chris Lattner 访谈录

536 阅读8分钟

www.swift51.com/post/6421.h… 原文地址

LLVM(Low Level Virtual Machine)是一个模块化、可重用的编译器和工具链的集合。Clang 是 LLVM 的子项目,是 C,C++ 和 Objective-C 编译器。多模块的复用,提供惊人的快速编译,比 GCC 快3倍。

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

一开始 LLVM 是开源的,所有代码在转成二进制时就叫做 bytecode(同 java ),出现很多问题,如不能扩展,无法兼容,非常脆弱。在 LLVM 2.0 中重新设计了架构,采用 Bitcode 机制,将所有代码以比特流(bit stream)而不是字节流(byte stream)的形式来编码。 主要的工作流程就是先将代码转成比特流,处理,再将编码传到其他地方去

什么是比特流编码

通过 Bitcode 机制,可以通过编译不同代码来存储各种优化方法,下次碰到类似代码会自动启动相关优化机制,使得效率提升;可以让芯片的兼容性变得很好。当然 Bitcode 也不是万能的,比如它不能解决 32位的 APP 在64位机器上的兼容问题,这个问题其实应该依靠代码逻辑。

32位 兼容问题目前解决了没有,有待核实

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

Swift 5.0 ABI 稳定, 5.1 模块稳定 

ABI ,Application Binary Interface,应用二进制接口,是 APP 和 操作系统、其他应用之间的二进制接口。包括:

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

Swift 将成为一门一统天下的语言(Swift was designed to scale from hello world to an entire operating system)。

Swift 之父 Chris Lattner 访谈录

若要成为服务器端的流行语言,这几个部分 Swift 必须具备:编码和解码,网络传输协议,HTTP。这些部分我觉得要成为标准函数库,因为它们是最基本的东西,苹果内部自己来做也许更好,因为能确保质量。  我觉得对开源社区而言,最重要是两个工作。

第一,是 Swift 的包管理器(Package Manager)。这个可以让我们在多个平台、不同函数库之间协同工作,大幅提高兼容性和效率;第二,是并发模型(Concurrency Model)。Go 语言之所以在服务器和云端开发这么受欢迎,就是因为并发模型做得好。并发模型应该会集成在 Swift 5 中

在网页开发上 看好 asm.js 和 WebAssembly,它们都是通过 LLVM 编译的,跟 Swift 一样。如果这两个今后做得足够好,也许就没 Swift 什么事了。 

而且我现在发现,Java 已经变成一门基础语言了。我看很多脚本语言现在都直接编译成 Java,Java 就像比特一样成为一个最基本的表达方式。我觉得五年之后,很有可能 asm.js 会一统网页端。虽然大家说 Java 不好 debug,但其实就算你写 C 这么成熟的语言,debug 起来依然很头疼。这也是我们为什么不在 Swift 中加入宏定义,因为那个给编译和 debug 增加了难度。

不在 Swift 中加入宏定义

Swift 设计得简单易懂、而同时又有很多高阶的复杂操作是一门将复杂和简易融为一体的语言。经验丰富的程序员可以写出漂亮的语法糖,对编程一窍不通的可以玩转 Playground。致力于让 Swift 成为一门简单易学的语言,同时又足够强大,为此不支持内联汇编 (inline assembly support) 这样的功能。以后我们也要秉持这个原则。

Swift 确实是大杂烩。但是它并不是简单的模仿其他语言,而是借鉴,然后创造出一个伟大的语言。我们确实参考了大量其他的语言设计。比如 Haskell 很多概念就被引入到 Swift 中。Swift 中的 Protocol,就是从 Haskell 的 construct 中得到启发的。

还有其他部分长得像 Dart,亦或是借鉴了 Go 和 C#。这样做也有另一个好处,开发者拿到 Swift 的时候会有种似曾相识的感觉,这样大家也更愿意用 Swift 开发。

Swift vs. Objective-C

Swift 之父 Chris Lattner 访谈录

在 Objective-C 中,会花不少时间修 unrecognized-selector error,但是 Swift 从顶层设计中就排除了这类 bug;可以对字符串使用 switch...case...语句;可以使用 functional programming;可以用 enum 和 protocol。Swift 其实是一门包罗万象的语言,菜鸟和老手写出来的 Swift 可以完全不一样,这取决于经验。

我最近发现,很多 iOS 开发者会把 Swift 当 Objective-C 来写,逻辑结构完全一样,只是换个语法。其实这就意味着他们没有意识到 Swift 的价值 -- 认为 Swift 不过是 Objective-C 的替代品。当开发者深究 Swift 的语法后,他们才会意识到这是一门多么高效的语言。

Swift 目前没有加入动态特性的计划。很多人问为什么 Swift 不能有响应,reflection这些特性。甚至有人写博客说,“迟早有一天,苹果要重写 Swift 的所有架构”,我每次在 WWDC 前看到这些博客都会呵呵。很多人不明白什么叫动态性,也不关心我们发布的 Swift 计划表,只是不停的写博客,预测这个吐槽那个。

我个人可以明确表示,Swift 近期内没有加入动态特性的计划。凡事有轻重缓急,我们得先处理其他事情,比如并发模型,比如在系统端上的优化,比如脚本的适配。不过以后如果有时间,Swift 会加入动态特性的,前提是我们计划表里的事情都做完了

我已经开始关注 RxSwift 了。但是我自己没用响应式编程来开发过产品,所以我对它们的理解来自于博客。RxSwift 看起来很棒,你可以少写很多代码,而且似乎开发效率也会更高。但听说维护和测试起来也很难,有优点也有缺点。如果我有空写一个 App 的话,我肯定回去试试 RxSwift,然后再过来发表观点。我现在不敢说”强烈推荐”,或者“强烈不推荐”之类的话。

Garbage Collection 和 ARC 各有千秋。Objective-C 有 Garbage Collection,后来加入了 ARC 的机制。Swift 则是完全 ARC。 

目前反对 ARC 的理由主要有两个,一是人们觉得 ARC 引入了额外的开销,因为你要维护引用计数嘛。另一个是 ARC 容易造成循环引用。

我个人要强调的是,这些毛病 Garbage Collection 也有。除此之外 Garbage Collection 还不能终止所有的线程,或者在特定的一个时间点终止一个线程。这是因为 Garbage Collection 引入了安全指针(safepoint),这同样也是一笔额外的开销。

ARC 中引用计数的开销在实际开发中影响不大。而且我们对对象的整个生命流程都有掌控,而这是 Garbage Collection 不具备的。实际上我觉得 ARC 中有些额外开销是必须的,那些不必须的开销以后也会慢慢改进的。

至于循环引用的问题。相比于你必须在具体的一行说明,retain/malloc 这个变量,然后再在后面某一行说明,release/free这个变量这种麻烦事,你只需要用 strong 或者 weak 表示你对对象的所有权,你省去了大量思考内存分配的担忧和操作,这难道不是一个巨大的进步吗?

ARC都有那些额外的开销?

它是如何处理 final 的?

Swift 编译流和 Clang 一样都是编译前端,和 Clang 一样代码会被解析成语法数 AST,接下来会比 Clang 多一步,通过 SILGen 生成 SIL, 做些 Swift 特定的优化,SIL 会被传递给 IR 生成阶段生成 LLVM IR,最后由 LLVM 解决余下事情。看到这里大家肯定会好奇 swift 是如何与 C 和 OC 交互的,比如系统底层的模块,这里就要提提 swift 的模块映射了(Module map),它调用 Clang 的模块,将其传入 Clang importer 中生成 AST 来分析,使得 swift 能够和 C/OC 进行交互。

www.uraimo.com/2017/07/22/… 并发模型

www.swift51.com/post/6421.h…  

github.com/ming1016/st… 

ming1016.github.io/2017/03/01/…