Swift 编译优化的系列文章:

Swift 编译优化(1) – 编译过程

Swift 编译优化(2) – 耗时核算

Swift 编译优化(3) – 编译装备

Swift 编译优化(4) – 代码优化

编译项设置优化完之后,首要便是代码的优化了。Swift 耗时的首要便是类型查看,那么代码优化的重点便是 查看哪些表达式、函数 类型查看占用太长时刻。

我们将代码编译优化的等级分为 【高】【中】【低】,逐一验证剖析。

【高】编译优化项

杂乱的运算

一个核算式

尽量不要超过两种运算符号,不要进行过屡次运算。

第一种

这是一个最简略的类型揣度。

func dictTest1() {
let _ = [
 "x": 1.0,
 "y": 2.0,
 "w": 3.0,
 "h": 4.0
]
}

阐明信息: 体系只需简略的类型揣度即可,由于比较简略,以体系的能力很轻松的就揣度出来了。

编译耗时: 1ms。

第二种

在第一种的基础上,x的值运用加法核算出来。

func dictTest2() {
let _ = [
 "x": 1.0 + 1,
 "y": 2.0 ,
 "w": 3.0,
 "h": 4.0
]
}

阐明信息: 同一种运算办法得到的值,仍是该类型。所以体系仍是很简单的就揣度出来了。

编译耗时: 1ms。

第三种

在第二种的基础上,x的值运用 加法减法 核算出来。

func dictTest3() {
let _ = [
 "x": 1.0 + 1 - 1,
 "y": 2.0 ,
 "w": 3.0,
 "h": 4.0
]
}

阐明信息: 两种运算办法(加法 和 减法),会影响编译耗时。

编译耗时: 8ms。

第四种

func dictTest4() {
let _ = [
 "x": 1.0 + 1 - 1 + 3 * 3,
 "y": 2.0 ,
 "w": 3.0,
 "h": 4.0
]
}

阐明信息: 三种运算办法(加法 , 减法 和 乘法),会严重影响编译耗时。

编译耗时: 695ms。

第五种

func dictTest5() {
 let _ = [
   "x": 1.0 + 1 - 1 + 3 * 3,
   "y": 1.0 + 1 - 1 + 3 * 3,
   "w": 3.0,
   "h": 4.0
 ]
}

阐明信息: 两个值的三种运算办法(加法 , 减法 和 乘法),会严重影响编译耗时。

编译耗时: 1382ms。

第六种

func dictTest6() {
 let x = 1.0 + 1 - 1 + 3 * 3
 let y = 1.0 + 1 - 1 + 3 * 3
 let _ = [
   "x": x,
   "y": y,
   "w": 3.0,
   "h": 4.0
 ]
}

阐明信息: 将x和y,拿出来独自运算,由于削减了揣度的层级(削减了字典的类型揣度量),但是削减有限。

编译耗时: 1362ms。

第七种

测验发现,一个核算有四种运算符号,就 Run 不动了。

func dictTest7() {
 let x = 1.0 + 1 - 1 + 3 * 3 + 3 / 2
 let _ = [
   "x": x,
   "y": 2.0 ,
   "w": 3.0,
   "h": 4.0
 ]
}

长时刻的等待之后,编译器会报错:

The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

第八种

揣度中带可选值解包。

let value: CGFloat? = 4let _ = [
 "x": 1.0 + 1 - 1 + 3 * 3,
 "y": 1.0 + 1 - 1 + 3 * 3,
 "w": CGFloat((value ?? 0) * 4 - 5),
 "h": 4.0
]

阐明信息: 可选值的解包也会影响编译时刻。

编译耗时: 1461ms。

第九种

揣度中带可选值解包。

let value: CGFloat? = 4
let _ = [
    "x": 1.0 + 1 - 1 + 3 * 3,
    "y": 1.0 + 1 - 1 + 3 * 3,
    "w": CGFloat((value ?? 0) * 4 - 5),
    "h": 4.0
]

阐明信息: 可选值的解包也会影响编译时刻。

编译耗时: 1461ms。

Swift 编译优化(4) - 代码优化

String的拼接

// 编译耗时: 0ms
func stringTest1() {
    let str = "123"
}
// 编译耗时: 6ms
func stringTest2() {
    let str = "123" + "456"
}
// 编译耗时: 1ms
func stringTest3() {
    let str1 = "123"
    let str2 = "456"
    let str = "(str1) + (str2)"
}
// 编译耗时: 5ms
func stringTest4() {
    let str1 = "123"
    let str2 = "456"
    let str = str1.appending(str2)
}

字符串的拼接中,优先选择 "(str1) + (str2)" 这种办法。

Swift 编译优化(4) - 代码优化

类型揣度

在Swift中界说变量时能够不带类型声明,编译器会根据初始化的值去猜想变量类型。这为Swift开发者供给便利的一起,也增加了编译器的负担。

从削减编译时刻的视点考虑:给每个变量界说都加上类型声明,这样编译器负担最小。

为了写 “Swift” 代码,关于简略的变量界说,添不添加类型声明,编译时刻都差不多。

但关于下面杂乱的类型,最好仍是加上类型。

// 办法编译耗时为: 8ms
func functionOne() {
    let myCompany = [
        "employees": [
            "employee 1": ["attribute": "value"],
            "employee 2": ["attribute": "value"],
            "employee 3": ["attribute": "value"],
            "employee 4": ["attribute": "value"],
            "employee 5": ["attribute": "value"],
            "employee 6": ["attribute": "value"],
            "employee 7": ["attribute": "value"],
            "employee 8": ["attribute": "value"],
            "employee 9": ["attribute": "value"],
            "employee 10": ["attribute": "value"],
            "employee 11": ["attribute": "value"],
            "employee 12": ["attribute": "value"],
            "employee 13": ["attribute": "value"],
            "employee 14": ["attribute": "value"],
            "employee 15": ["attribute": "value"],
            "employee 16": ["attribute": "value"],
            "employee 17": ["attribute": "value"],
            "employee 18": [1, 2, 3],
            "employee 19": "2",
            "employee 20": 1,
        ]
    ]
}

让体系揣度类型,该办法编译耗时为: 8ms。

//办法编译耗时为: 4ms
func functionTwo() {
    let myCompany1: [String: Any] = [
        "employees": [
            "employee 1": ["attribute": "value"],
            "employee 2": ["attribute": "value"],
            "employee 3": ["attribute": "value"],
            "employee 4": ["attribute": "value"],
            "employee 5": ["attribute": "value"],
            "employee 6": ["attribute": "value"],
            "employee 7": ["attribute": "value"],
            "employee 8": ["attribute": "value"],
            "employee 9": ["attribute": "value"],
            "employee 10": ["attribute": "value"],
            "employee 11": ["attribute": "value"],
            "employee 12": ["attribute": "value"],
            "employee 13": ["attribute": "value"],
            "employee 14": ["attribute": "value"],
            "employee 15": ["attribute": "value"],
            "employee 16": ["attribute": "value"],
            "employee 17": ["attribute": "value"],
            "employee 18": [1, 2, 3],
            "employee 19": "2",
            "employee 20": 1,
        ]
    ]
}

告知体系明确的类型,该办法编译耗时为: 4ms。

CGSize,CGRect,Dictionary,Array

不要在实现中,有核算,解包,三目运算等。

❌❌❌❌❌❌
let size = CGSize(width: 50 / 3 + 3, height: 2 + 4 - 4)
let rect = CGRect(x: isTrue ? 40 : 30, y: 50 * 3 + 20, width: 5, height: 5)
let dict = [
    "a": (5 + 3 / 2) + min(3, value * 3)
]

删去Xib

xib文件的编译是很耗时的。我们的项目中删的已经差不多了。

Xib的编译耗时

【中】编译优化项

Array的拼接

推荐运用append(contentsOf: arr2)的办法。

func functionOne() {
    let arr1 = [1, 2, 3, 4]
    let arr2 = [5, 6, 7, 8]
    let arr = arr1 + arr2
}

该办法编译耗时 8秒

func functionTwo() {
    var arr1 = [1, 2, 3, 4]
    let arr2 = [5, 6, 7, 8]
    arr1.append(contentsOf: arr2)
}

该办法编译耗时 4秒

转换为String

let intA = 1
let string = String(intA)

这样转换成字符串,耗时 1ms

let intA = 1
let string = "(intA)"

这样转换成字符串,耗时 8ms

提前核算

不要在一个表达式中既做判别,又做核算。 如果条件允许,避免核算。 越杂乱的核算,编译耗时越长。

// 编译耗时:5ms
func functionOne() {
    let time = 10000
    if time > 60 * 60 * 24 + 3 {
    }
}
// 编译耗时:1ms
func functionTwo() {
    let time = 10000
    let limit = 60 * 60 * 24 + 3
    if time > limit {
    }
}
// 编译耗时:0ms
func functionThree() {
    let time = 10000
    if time > 8643 { // 60 * 60 * 24 + 3
    }
}

【低】编译优化项

三元运算符【低】

let letter = someBoolean ? "a" : "b"

三目运算符写法愈加简洁,但会增加编译时刻,如果想要削减编译时刻,能够改写为下面的写法。

var letter = ""
if someBoolean { 
  letter = "a"
} else {
  letter = "b"
}

实测数据,没有实质的区别。 等待持续验证。

可选解包【低】

let v = optionalString ?? ""

这是 Swift 中的特殊语法,在运用 optional 类型时能够经过这样的办法设置 default value。但是这种写法实质上也是三目运算符。

if let string = optionalString {
    print("(string)")
}