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 { |