Swift内存布局初探
enum
问题实际分配内存为何是25?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| enum TestEnum { case t1(Int, Int, Int) case t2(Int, Int) case t3(Int) case t4(Bool) } print(MemoryLayout<TestEnum>.alignment) print(MemoryLayout<TestEnum>.size) print(MemoryLayout<TestEnum>.stride)
enum Password { case num(Int, Int) case str } print(MemoryLayout<Password>.alignment) print(MemoryLayout<Password>.size) print(MemoryLayout<Password>.stride)
|
Struct
实际分配内存是多少?实际大小是多少?
1 2 3 4 5 6 7 8 9 10 11
| struct Point { let x: Int let y: Int var isHit: Bool }
print(MemoryLayout<Point>.alignment) print(MemoryLayout<Point>.size) print(MemoryLayout<Point>.stride)
|
Class的内存管理
Class 本身也是分配在栈上,在堆上保留class的type信息,type信息里面有一个函数表,class的函数在派发时会按照type信息里面的函数表进行派发。
当子类需要继承父类时,子类只要在自己的type信息中记录自己的信息即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| var name = "Jack" print(Mems.size(ofVal: &name)) class Man { var name = "j" }
var man = Man() print(class_getInstanceSize(type(of: man))) print(class_getInstanceSize(Man.self)) print(Mems.size(ofRef: man))
var isMan = true print(Mems.size(ofVal: &isMan)) class Man2 { var isMan = true }
var man2 = Man2() print(class_getInstanceSize(type(of: man2))) print(class_getInstanceSize(Man2.self)) print(Mems.size(ofRef: man2))
|
协议的内存管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| protocol DragonFire {} extension DragonFire { func fire() {
} }
struct YellowDragon: DragonFire { let year = "8" let teeth = 48 }
print(MemoryLayout<YellowDragon>.size) print(MemoryLayout<DragonFire>.size)
|
协议类型内存管理使用Existential Container 内存模型。
前三个word使用Value buffer 来存储inline的值
第四个word使用Value Witness Table 存储各种操作如allocate、copy、destruct、deallocate等
第五个word使用Protocol Witness Table 来存储协议的函数
泛型的内存管理
泛型采用是和Exsistential Container原理类似的内存管理。
Value Witness Table 和 Protocol Witness Table是作为隐形参数传递到泛型方法里。
不过经过编辑器的层层inline优化后,最终类型会被推导出来,也就不再需要Existential Container 这一套方法了。