ios 底层原理之alloc探究(二)
上一章节我们通过汇编跑流程找到 alloc 底层的核心方法 _class_createInstanceFromZone 本章主要研究当对象申请内存时到底如何去计算。
准备工作
1.了解基本数据类型占用字节数
2.了解LLDB 指令
数据的存储规律
内存对⻬的原则
1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第
一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要
从该成员大小或者成员的子成员大小(只要该成员有子成员
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从
其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b
里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:结构体的总大小,必须是其内部最大成员的整数倍,不足补齐。
举例1:
struct Struct1 {
double a; // 8 [0 7] 【以第一个成员变量offset 为0的位置开始存储】。
char b; // 1 [8] 【char 需要1字节,也即是8必须是1的整数倍才能开始存储。】
int c; // 4 (9 10 11 [12 13 14 15] 【9,10,11 并不能整除4 所以数据c 存储从12位开始存储,】
short d; // 2 [16 17] 24 【当数据d 被存储完成后,此时总共所占用的字节是17,又因为结构体的总大小要保证是最大成员变量的整数倍,17/8=2......1 所以当前结构体的的大小为 24字节】
}struct1;
举例2:
struct Struct2 {
double a; // 8 [0 7]
int b; // 4 [8 9 10 11]
char c; // 1 [12]
short d; // 2 (13 [14 15] 16
}struct2; 通过计算可得结构大小为 16字节。
发现:当结构体中的成员变量的排列顺序不同,对应的存储大小也不相同。
疑问:刚才我们在上面打印person 时,我们也对位置以及顺序做过调整,但是发现 数据的存储很有规律,这是为什么呢?oc 做的优化,所以,我们平时在开发过程中对于对象的属性,并不需要排序。
举例3:
struct Struct3 {
double a; // 8 [0-7]
int b; // 4 [8 ,9,10,11]
char c; // 1 [12]
short d; // 2 (13 [14 ,15]
int e; // 4 [16,17,18,19]
struct Struct1 str; // 24 (21 ,22,23 [24 ,48]
}struct3; 【48】
【这里为什么从24位开始,因为通过对齐原则发现:struct1为结构体,所以要找该结构体最大的成员变量(即8字节的整数倍开始存储)24 开始,接下来同样按照单个成员去排列,相当于把str的元素罗列到struct3 int e 下面 继续排列,只是有一点注意,当出现结构体为成员时,要以子结构体中的最大成员对齐第一个元素,所以struct3最终大小为48】
为什么要遵循内存对齐原则?
我们一个一个去取不香吗?就好比举例1:
struct Struct1 {
double a; // 8 [0 7]
char b; // 1 [8]
int c; // 4 (9 10 11 [12 13 14 15]
short d; // 2 [16 17] 24
}struct1;
如果我们就按照顺序存入数据 其实只需要 15个字节,反而遵循原则后又变大了,为什么呢?其实我们对于数据的操作不光光只考虑存入,最关键的是读取。电脑在对数据的处理方面并不能像人一样灵活,只能通过程序去控制。(按照以剩余最大的数取)
假设,我们就按照 8,1,4,2 这个顺序去存储,那么计算机如何去读取呢?
第一次:肯定是用8个字节长度去读,第二次,用4个字节长度去读,但是读取不到,然后程序会告诉他用1个字节长度去读,第三次读取成功,以此类推,读完共需要 7次在能把所有的数据读完。
但是如果按照内存对齐原则需要读几次呢?第一次我以8去读,第三次以4去读这时我们的1能不能读出来呢?答案能,因为,我们在存入4的时候,是不是空了三个,正好加上1就是是四个长度,能把1取出来,4也是一次取出,2也是共需要4次取出全部数据。
相差近一倍的读取效率。那为什么空出的刚好和旁边的数据储存能拼在一起呢?
在看基本数据的存储需要的字节,1,2,4,8 2的0 ,2的1 2的2 2的3 所以这四个数有对应的排列组合规律。
结论:通过遵循内存对齐原则,大大的缩短的读取时间(以空间换时间),加快程序优化。
为什么对象以16字节对齐,但成员变量确以8字节对齐?
在上一章我们了解到对象在申请内存的时候是以16字节对齐,因为成员变量以8字节对齐更能提高读取效率(因大部分成员变量都是8字节,所以效率更高,那为什么不用16字节对齐,大部分都是8字节,如果用16字节,将造成大量的空间浪费),那为什么对象要用16字节对齐呢?不能用8字节对齐吗?8字节对齐肯定是可以的。那我们就先讲讲以八字节对齐,
看图解。
那就先到这,未完待续。。。