WWDC 2016 416
WWDC 慢慢補
補了半個去年 WWDC 影片,提到一些有關於 swift performance,主要影響的部分分別為 Allocation, Reference Count, Method Dispatch
Allocation
應該是影響效能最重的部分,以軟體來講大概是指宣告成區域變數或全域變數
1 | func nothing() { |
更精確地講的話是指你的變數是存放在 stack 還是 heap 中,放在 heap 的話就如同 c lang 做 memory allocation 去申請一塊記憶體位置,不用的時候還得 free 掉,還牽扯到多執行緒共用要不要 lock 等等問題。
所以 c(變數) 是個 pointer 而資料是在 heap 內,s(變數) 的話是位於 stack,應此只要移動 SP 就做完事了。
Reference Count
經歷過 ARC 的人應該會有感覺,但要有更深體會應該要體驗 MRC 才會更有感覺(開始玩已是 ARC 時代),前年的 WWDC 其實也有提道要使用 value type,用 refference type 的話 compiler 會幫你使用前加上 obj.retain() 使用後加上 obj.release()
1 | for c in classes { |
1 |
|
Method Dispatch
分成 static & dynamic,基本上 class func 預設是 dynamic,影響在於 compiler 有沒有能力幫你做優化,影片例子是 function inline
class 如果要變成 static dispatch 可以使用 final class or final func
1 | func action1() {action2()} |
1 | do_some_thing() |
String VS Hashable
String 屬於比較特殊的 struct,他跟 class 一樣會被宣告在 heap 區,受到 alloc & free 的管理。
1 | enum Color {case blue,green,gray} |
透過 Hashable 取代掉 String
1 | struct Attributes:Hashable { |
減少 struct 內的 class
struct 內的 class 其實也會受到 ARC 管理,使用前後也會被隱含加入 retain() & release(),去 class 可以減少 ARC 的隱含成本。
1 | struct Attachment { |
1 | enum MimeType:String { |
protocol VS class
官方有在推薦使用 protocol 而非 class 繼承方式,已知說 class allocation 在 heap 且 call function by V-Table(啥?)
那 protocol + struct 真的會比 class 快?
以下分別是 protocol + struct & class 的定義 :
1 | class ClassDrawable { |
1 | protocol Drawable { |
接著要提到 protocol 的實作部分,會因為你的實作甚至比 class 還慢上許多
EC (Existential Container)
影響最大的部分在於 EC,他應該是屬於 5 Word 大小的 struct
其中 Value Buffer 佔了 3 Word,且他專門負責存放 data。
- 如果你的
struct data <= 3 Word,data可以完整的放到Value Buffer - 反之你的 struct data 會被 allocate 在 heap,Value Buffer 只留下指標指過去。
(感覺比 class 還嚴重,一樣放到heap,還多了EC, PWT, VWT)
| Existential Container | 單位 |
|---|---|
Value Buffer |
3 Word |
vwt: |
1 Word |
pwt: |
1 Word |
PWT (Protocol Witness Table)
| Protocol Witness Table(pwt) |
|---|
draw: |
...: |
VWT (Value Witness Table)
| Value Witness Table(vwt) |
|---|
allocate: |
copy: |
destruct: |
deallocate: |
Generic VS protocol
1 | let drawable:Drawable = Line() |
1 | func drawing<T:Drawable>(drawable:T) -> Int { |