Redis
1.内存地址对齐
内存地址对齐,是一种在计算机内存中排列数据、访问数据的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐。当今的计算机在计算机内存中读写数据时是按照字(word)大小块来进行操作的(在32位系统中, 数据总线宽度位32,每次读取4字节,地址总线宽度为32,因此最大的寻址空间为2的32次方=4GB,但是最低两位A[0],A[1]不用于寻址,A[2-31]才能与存储器相连,因此只能访问4的倍数的地址空间,但是总的寻址空间还是2的30次方*字长=4GB,因此在内存中所有存放的基本类型数据的首地址的最低两位都是0,除结构体中的成员变量)。
基本类型数据对齐就是数据在内存中的偏移地址必须等于一个字的倍数,按这种存储数据的方式,可以提升系统在读取数据时的性能。为了对齐数据,可能必须在上一个数据结束和下一个数据开始的地方插入一些没有用处字节,这就是结构体数据对齐。
假设计算机的字大小为4个字节,因此变量在内存中的首地址是满足4地址对齐,CPU只能对4的倍数的地址进行读取,而每次能读取4个字节大小的数据。假设有一个整型的数据a的首地址不是4的倍数,为0X00FFFFF3,则该整型数据存储在地址范围为0X00FFFFF3~0X00FFFFF6的存储空间里,而CPU每次只能对4的倍数内存地址进行读取,因此想要读取a的数据,CPU要分别在0X00FFFFF0和0X00FFFFF4进行两次内存读取,而且还要对两次读取的数据进行处理才能得到a的数据,而一个程序的瓶颈往往不是CPU的速度,而是取决于内存的带宽,因为CPU的处理速度要远远大于从内存中读取数据的速度,因此减少对内存空间的访问是提高程序性能的关键。因此采取地址对齐策略是提高程序性能的关键。
当结构体某一个成员后面紧跟一个要求比较大的地址对齐成员时,这时要插入一些没有实际意义的填充(Padding),而且总的结构体大小必须为最大对齐的倍数。
同样一个结构体,调整内部成员的顺序可以改变结构体的大小。
struct test1
{
char c;
short b;
int i;
char d;
}Node;
这个结构体在编译以后,为了字节对齐,会被整理成这个样子:
struct test1
{
char c;
char padding[1];
short b;
int i;
char d;
char padding[3];
}Node;
编译后大小由8字节变成了12字节。如果顺序如下:
struct test2
{
char c;
char d;
short b;
int i;
}Node;
那么编译前后大小都是8字节。编译后不用填充字节就能保持所有的成员都按各自默认的地址对齐。这样可以节约很多内存,一般的结构体成员按照默认对齐字节递增或是递减的顺序排放,会使总的填充字节数最少。
空结构体的空间是一个字节
struct s{};
sizeof(s);结果为1
有static的结构体
struct s
{
char a;
long b;
static long c;
}
静态变量存放在全局数据内,而sizeof计算栈中分配的空间的大小,故不在计算内。该结构体大小为4+4=8。
2.内存分区
(1)栈区(stack):由编译器自动分配释放,存