棧是一種很是簡單的數據結構; 數據從棧的頂部推入(push)與彈出(pop); 因爲只可以修改棧的末端,所以能夠經過維護一個指向棧末端的指針來實現這種數據結構;ios
內存分配具有更加動態的生命週期,更復雜的數據結構 在堆上進行內存分配,須要爲對象開闢並鎖定堆當中的一個空閒塊(free block) 爲了線程安全,必須進行鎖定和同步git
引用計數(reference counting)操做自己相對不耗費性能,但因爲使用次數足夠多,所以它帶來的性能影響比較大。引用計數是 Objective-C 和 Swift 中用於肯定什麼時候該釋放對象的安全機制。Swift 當中的引用計數是強制自動管理(ARC, Auto Reference Counting),所以容易被開發者所忽略。github
Swift 中有三種類型的調度(Dispatch)方式:數據庫
V-table: virtual table,虛函數表,記錄了類中全部虛函數的函數指針,也就是說是個函數指針數組的起始位置。swift
Swift 中有兩種類型的對象:數組
class Index {
let section: Int
let item: Int
}
let i = Index(section: 1, item: 2)
let i2 = i
複製代碼
類當中的數據是在堆上分配內存。 Index
這個類包含了兩個屬性,section
和 item
,當該對象被建立時,堆上便開闢了section
和 item
的數據空間,並生成一個指向該對象的指針 i
。若是對其添加一個引用,則 i2
指向堆上相同區域,這兩個對象指針之間是共用同一塊內存空間的,同時會對該對象自動插入持有操做,引用計數+1。緩存
struct Index {
let section: Int
let item: Int
}
let i = Index(section: 1, item: 1)
let i2 = i
複製代碼
一般咱們會說,要編寫性能優異的 Swift 代碼,最簡單的方式儘量使用結構體。安全
結構體儲存在棧上,基於棧進行內存分配,而且一般使用靜態調度或內聯調度。若是將其賦值給另外一個變量 i2
,這會將儲存在棧上的值複製一遍產生新的對象,而不是引用。性能優化
另:。枚舉也是值類型,採用枚舉改進數據模型,避免使用大量的字符串。微信
協議內部會有儲存值的緩存區、元數據,而且要支持動態調度派發,有一個協議記錄表(protocol witness table,也稱做虛函數表),所以協議類型所佔內存要比具體的類、結構體或枚舉要更大。這個能夠簡單瞭解一下,以後考慮另起一篇文章單獨記錄下這個問題。「過早的優化是萬惡之源」,相比面向協議帶來的好處,通常來講能夠不用太過考慮使用協議帶來的細微性能消耗。
即使如此,在面向協議開發的過程當中,也能夠適當地注意如下幾點,在利用協議帶來的好處的同時,避免協議帶來的性能損耗:
: class
做爲約束,採用類協議,如代理(delegate)協議的使用。經過 GCD 將一些耗時操做派發到非主線程,提升 UI 流暢度,響應更及時,優化用戶體驗。
離屏渲染:GPU在當前屏幕緩衝區之外新開闢一個緩衝區進行渲染操做。 離屏渲染須要屢次切換上下文環境:先是從當前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結束之後,將離屏緩衝區的渲染結果顯示到屏幕上又須要將上下文環境從離屏切換到當前屏幕,而上下文環境的切換是一項高開銷的動做。
reuseIdentifier
對 UITableViewCell
進行重用使用循環體時,考慮是否有必要採用 Autorelease Pool 對臨時對象進行釋放,避免佔用過多內存空間。
合理的線程分配,最終目的就是保證主線程儘可能少地處理非 UI 操做,同時將整個 App 中子線程數量控制在合理範圍,以免沒必要要子線程開啓與切換消耗。