# Swift语法对编译速度的影响

使用Swift初期会惊艳于它强大的表达力，发现原来很啰嗦的逻辑可以用一两句话写完时，工具的强大导致自己会情不自禁的写一些“聪明”的代码。但是Swift毕竟是一个婴儿时期的语言，编译器对于这些极简的代码的处理能力是一个容易被忽略的副作用。

在混编Swift两年后，工程的编译速度到了忍无可忍的程度。通过网上搜寻“如何提高Xcode编译速度”把能做的优化都做了之后，还是没有得到根本的提升。直到发现了这篇文章[Regarding Swift build time optimizations](https://link.juejin.im?target=https%3A%2F%2Fmedium.com%2F%40RobertGummesson%2Fregarding-swift-build-time-optimizations-fc92cdd91e31)，它采用了一个[开源工具](https://link.juejin.im?target=https%3A%2F%2Fgithub.com%2FRobertGummesson%2FBuildTimeAnalyzer-for-Xcode)来检测每一个Swift方法的编译时间，从而定位耗时。我通过对耗时语法的修改，成功的把一个超过4年多庞大工程的编译速度缩短了30%。

下面介绍一下这次优化中遇到的有坑的语法：

## 1. 避免在Array/Dictionary literals里使用复杂运算，如`??`(Nil Coalescing Operator), 随元素个数耗时成指数式增长

```
var a: String?
var b: String?
var c: String?
var d: String?
var e: String?
var f: String?
var g: String?

let _ = [
    "a": a ?? "", // 1 ms
    "b": b ?? "", // 3 ms
    "c": c ?? "", // 11 ms
    "d": d ?? "", // 48 ms
    "e": e ?? "", // 274 ms
    "f": f ?? "", // 1339 ms
    "g": g ?? "", // 6550 ms
]
```

**解决方案:** 用传统的键值对赋值

```
var dict = [String: String]()
dict["a"] = a ?? "" // 30 ms
dict["b"] = b ?? "" // 27 ms
dict["c"] = c ?? "" // 25 ms
dict["d"] = d ?? "" // 27 ms
dict["e"] = e ?? "" // 26 ms
dict["f"] = f ?? "" // 26 ms
dict["g"] = g ?? "" // 28 ms
```

## 2. 浮点数参与的数学函数后追加算数运算, 耗时增长幅度匪夷所思

```
min(1, 2.0)
    + 1 // 10 ms
    + 2 // 35 ms
    + 3 // 352 ms
    + 4 // 6092 ms
```

**解决方案:** 数学函数独立运算，用结果做算数运算

```
let a = min(1, 2.0)
a + 1 + 2 + 3 + 4 // 11 ms
```

## 3. 避免在有??的情况下使用 + 来拼接字符串

```
var a: String?

let _ = (a ?? "")
    + "1" // 27 ms
    + "2" // 101 ms
    + "3" // 1043 ms
    + "4" // 编译超时
```

**解决方案:** 采用`\()`(String Interpolation)

```
let _ = "\(a ?? "")1234" // 73 ms
```

## 另外介绍一个hack的设置

在User-Defined里添加`SWIFT_WHOLE_MODULE_OPTIMIZATION = YES`可以在debug选择Onone的前提下[享受到优化](https://link.juejin.im/?target=https%3A%2F%2Fjobs.zalando.com%2Ftech%2Fblog%2Fimproving-swift-compilation-times-from-12-to-2-minutes%2F)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://philm.gitbook.io/philm-ios-wiki/mei-zhou-yue-du/swift-yu-fa-dui-bian-yi-su-du-de-ying-xiang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
