栈是一种很是简单的数据结构; 数据从栈的顶部推入(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 中子线程数量控制在合理范围,以免没必要要子线程开启与切换消耗。