[swift 進階]讀書筆記-第九章:泛型 C9P4 泛型的工做方式 How Generics Work

第九章:泛型 Generics

9.4 泛型的工做方式(How Generics Work)

本小節講了一些關於泛型底層的知識點和一些特殊狀況下的使用。能夠當作擴充知識面去學習。git

咱們先看看一個最簡單的泛型函數的底層實現

func min<T: Comparable>(_ x: T, _ y: T) -> T { 
    returny<x?y:x
}
複製代碼

編譯器沒法爲這個函數直接生產代碼,緣由以下:github

1.編譯器不知道T的```變量大小```

2.編譯器不知道須要調用的<函數是否有重載,因此也不知道須要調用的```函數的地址```
複製代碼

swift 爲函數引入了一套間接的中間層來解決這個問題,引入了一個容器,編譯器會把泛型放到這個容器中 對於泛型的參數,編譯器還維護了一個或者多個目睹表(witness table),包括一個值目睹表,以及每一個協議約束的協議目睹表。 這些表將運行時的函數動態派發到正確的實現中。 表裏實際上放的都是指針。同時還記錄了類型大小和對齊方式swift

泛型特化

光看泛型特化這個詞很難理解它的用法和意思,後面咱們會講。app

使用泛型特化的緣由: 你們先了解一個swift的設計目標: "編譯一次,動態派發" swift 泛型API只須要知道泛型函數或者類型的聲明,並不關心實現。 因此結果的代碼不是那麼直接。這會致使運行時性能低函數

swift庫中有不少泛型的使用,性能開銷很容易疊加。性能

這裏就引入了泛型特化(generic specialization) 來避免這個沒必要要的開銷。 泛型特化的本質: 編譯器按照具體的參數類型將函數進行複製。 文章一開始的例子中,可能針對於Int的參數類型特化出一個方法是這樣的學習

func min(_ x: Int, _ y: Int) -> Int { 
        returny<x?y:x
    }
複製代碼

泛型特化不只能去掉虛擬派發的開銷, 還可讓內聯等進一步優化成爲可能優化

泛型特化的決定在編譯時進行。特化的參數類型極可能是你常常使用的具體類型, 若是你常常使用Int 只用過一次float 那麼就會特化出上面的函數。spa

缺點:泛型定義和調用在同一個文件中時,泛型特化才能工做,只能在模塊內使用😅(標準庫中的泛型方法除外,由於標準庫的定義對於全部模塊都是可見的)設計

全模塊優化

由於泛型特化是一個很嚴重的限制,因此編譯器引入了一個標誌來啓用全模塊優化

能夠經過向 swiftc 傳遞 -whole-module-optimization 來開啓全模塊優化

通常都是在發佈版本中進行這項操做,

優勢:大幅度提高性能 缺點:會帶來更長的編譯時間

@_specialize 關鍵字

@_specialize 是一個非官方的標籤,計劃未來會引入到標準庫中。 做用:將你的泛型代碼進行指定版本的特化,使其在其餘模塊中也可用。(你必需要指明想要進行特化的類型列表) 使用以下:

@_specialize(exported: true, where T == Int)
@_specialize(exported: true, where T == String) 
public func min<T: Comparable>(_ x: T, _ y: T) -> T {
    returny<x?y:x 
}
複製代碼

over~

文章源文件地址,你們若是有更好的想法和觀點歡迎交流

相關文章
相關標籤/搜索