Swift 编译优化的系列文章:
编译项设置优化完之后,首要便是代码的优化了。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? = 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。
第九种
揣度中带可选值解包。
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。
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中界说变量时能够不带类型声明,编译器会根据初始化的值去猜想变量类型。这为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文件的编译是很耗时的。我们的项目中删的已经差不多了。
【中】编译优化项
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)")
}