譯文出自:掘金翻譯計畫
譯者:iweslie
校對者:cloxnu
在程式設計中,函式內聯是一種編譯器優化技術,它通過使用方法的內容替換直接呼叫該方法,就相當於假裝該方法並不存在一樣,這種做法在很大程度上優化了效能。
例如,請看一下**:
func
calculateandprintsomething()
print("準備列印一些數字")
calculateandprintsomething()
print("完成")
複製**
假設calculateandprintsomething()
沒有在其他任何地方使用過,很明顯該方法不需要存在於編譯後的二進位制檔案中,它存在的目的只是為了使你更加易於閱讀。
通過使用函式內聯,swift 編譯器可以通過將呼叫這個方法替換為呼叫它裡面的具體內容,從而消除那些不必要的開銷:
// 上面的示例轉化為編譯後二進位制版本
print("準備列印一些數字")
var num = 1
num *= 10
num /= 5
print("我的數字:\(num)")
print("完成")
複製**
基於你選擇的優化級別,這個過程由 swift 編譯器自動完成的,通過支援內聯來優化速度(-o
),或者不進行內聯來優化二進位製包的大小(-osize
),因為內聯乙個經常呼叫且內容很多的方法會導致大量的重複**和更大的二進位製包。
儘管編譯器可以自己進行內聯,不過你還是可以 swift 中使用@inline
註解來強制內聯,它有兩種用法:
@inline(__always)
:如果可以的話,指示編譯器始終內聯方法。
@inline(never)
:指示編譯器永不內聯方法。
現在你可能會問:到底怎麼選擇呢?
根據蘋果工程師的說法,答案基本上是 never。儘管該屬性可用於公共或廣泛使用的 swift 源**,但它還沒有正式支援公共使用。它從來沒有打算過要公開,jordan rose 也曾說到:設定它不被公開是有原因的。如果你要使用它,可能會出現許多已知和未知的問題。
但由於該屬性可以公開使用,為了學習新的東西,我會去嘗試一下它,而且我實際上發現了這個註解在 ios 專案中一些很實用的地方。
編譯器將根據專案的優化設定做出內聯決策,但在某些情況下,你可能需要一種方法來手動決策。這時@inline
就可以幫助到你。
例如,在優化速度時,似乎編譯器會對一些內容並不是很短的方法進行內聯,從而導致二進位制大小增加。在這種情況下,@inline(never)
可用於防止這個,同時保證二進位制檔案的速度。
另乙個更實際的例子是,你可能想防止黑客接觸到乙個包含某種敏感資訊的方法,它是否會使**變慢或包變大都無關緊要。你肯定會嘗試混淆你的**來使**更難理解,或者可以選擇混淆工具,例如 swiftshield,但@inline(__always)
可以輕鬆實現這一點而同時不會損害你的**,我將在下面詳細介紹了這個例子:
func
isusersubscribed
() -> bool
func
play
(song: song)
else
}複製**
現在看看給isusersubscribed(_ :)
新增了@inline(__always)
後會發生什麼:
@inline(__always) func
isusersubscribed
() -> bool
func
play
(song: song)
else
}複製**
同樣的play(_:)
方法裡現在不包括對訂閱狀態的判斷。這個方法呼叫完全被其內部的 「複雜的驗證」 所取代,這樣反編譯後看起來變得更加複雜,訂閱也更加難以破解。
好處是,由於每次呼叫isusersubscribed(_:)
都被複雜的驗證取代,因此就沒有一種方法可以解鎖應用程式的整個訂閱,黑客現在必須破解每乙個進行驗證的方法。當然,多處的重複的**也意味著我們的二進位制檔案會變得更大。
請注意,使用@inline(__always)
並不能保證編譯器會真正內聯你的方法。它的規則是未知的,例如在無法避免動態派發的情況下就無法進行內聯。
由於@inline
沒有得到官方支援,你真的不應該在實際的專案中使用它,這篇文章使用它的目的只是為了學習新東西。
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計畫 對譯文進行修改並 pr,也可獲得相應獎勵積分。文章開頭的本文永久鏈結即為本文在 github 上的 markdown 鏈結。
譯 Swift 上的高效能陣列
譯文出自 掘金翻譯計畫 譯者 jingzhilehuakai 校對者 rickeyboy cbangchen 對於日常應用開發,考慮陣列效能是一件不會經常發生的事。如果你正在實現需要擴充套件的演算法,也許高效能陣列就能出現在你腦海中。也許你正在寫更偏向於底層的 比如乙個框架,這時任何的效能缺陷都會產...
強制解包看 Swift 的設計
property nonatomic,copy nsstring foo 它轉成 swift 就變成了這樣 var foo string 這樣看上去合情合理。swift 中有 string?和 string 兩種形式,但 oc 中沒有 nsstring?和 nsstring 當 swift 無法區分...
強制解包看 Swift 的設計
1 property nonatomic,copy nsstring foo 它轉成 swift 就變成了這樣 var foo string 這樣看上去合情合理。swift 中有 string?和 string 兩種形式,但 oc 中沒有 nsstring?和 nsstring 當 swift 無法...