- 原文地址:On Performant Arrays in Swift
- 原文做者:JORDAN SMITH
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:jingzhilehuakai
- 校對者:RickeyBoy cbangchen
對於平常應用開發,考慮數組性能是一件不會常常發生的事。若是你正在實現須要擴展的算法,也許高性能數組就能出如今你腦海中。也許你正在寫更偏向於底層的代碼,好比一個框架,這時任何的性能缺陷都會產生複合效應。當數組性能變得重要的時候,瞭解一些優化數組性能的方式也是很不錯的。讓咱們來深刻的瞭解一下 Swift 中的數組吧。前端
Array
不是 Swift 惟一提供的數組類型。你可能已經注意到 ArraySlice
類型,它能在不復制數組的狀況下,展現出數組的局部片斷。另外還有 ContiguousArray
類型。和名字所暗示的不一樣,它實際上是 Swift 中最簡單的數組類型。相比標準的數組,它能夠有更好的性能表現,而即使沒有,也至少能夠提供與 Array
相同性能水平的表現。同時也暴露出相同的接口。因此,爲何不用 ContiguousArray
去替代 Array
呢?react
let deliciousArray = ContiguousArray<String>(arrayLiteral: "🌮", "🥞", "🥖")複製代碼
好吧,由於 Objective-C 的兼容性,Array
能無縫對接成一個 NSArray
。在底層,一個 Array
實例只要它的元素類型是 class 或是遵循了 Objective-C 兼容協議的類型,就會將數組數據存儲在 NSArray
中。只要不是這種狀況(例如數組元素爲值類型的數組),這個數組就不會被存儲在 NSArray
中,而且性能變得和 ContiguousArray
至關。android
爲了比較性能,咱們運行了這樣一個測試,向每一個數組的實例中添加一百萬個單獨的引用類型,而後刪除。這些引用類型會在開始計時前進行預構建,而結果爲超過 100 次的運行後獲得的平均值。下面的值是在設置了編譯器優化的狀況下得到的。總的來講,你能夠看到,若是數組性能是瓶頸的話,在數組元素爲引用類型或 @objc
類型的前提下,切換爲 ContiguousArray
的使用大約能得到 2 倍性能的提高。ios
Array | ContiguousArray |
---|---|
58.9 ms | 30.3 ms |
看起來 Swift 數組分配的內存與它的長度成正比。若是是這種狀況,添加或刪除一個元素將須要分配或釋放內存,並對數組長度的每個變化都形成性能損失。相反,提早分配最少的內存空間是更有意義的,這樣就能夠在不引發內存管理性能損失的狀況下進行接下來的幾個新增操做。這其實是 Swift 所作的:以一種智能的方式進行內存分配,來讓分配性能消耗保持在最低的水平。git
儘管有智能內存分配,但若是清楚地知道數組應該被定義持有的內存大小,纔是內存分配最有效的方式。這樣,只須要一個內存分配就能夠了。 Swift 數組提供了定義和預留容量的能力,並且這樣作能夠實現較小的性能增益。github
var healthyArray = ["🍉", "🥕"]
healthyArray.reserveCapacity(50)複製代碼
運行另外一個測試,再次向一個數組中添加和刪除一百萬個引用類型,產生如下的結果。該測試是針對連續數組有無預留內存容量的狀況。算法
Without Reserved Capacity | With Reserved Capacity |
---|---|
29.7 ms | 27.3 ms |
若是你想訪問原始內存來增強數組,你也能夠這麼作。對於標準的數組操做,它不會提供太多的性能增益。對於非標準的狀況,用這種方式訪問或修改數據多是有必要的,或者是對性能有益的。swift
var balancedDietArray = ["🥖", "🍩", "🍗"]
balancedDietArray.withUnsafeMutableBufferPointer { arrayPointer in
arrayPointer[1] = "🍇"
}複製代碼
若是你想了解更多關於 Swift 數組是如何工做的,能夠在這裏找到更多的內容:Swift Array Design。後端
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、React、前端、後端、產品、設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。數組