内存池:
1.避免频繁分配和释放内存,提高效率
2.避免内存碎片
3.避免内存泄露
//4.设置对齐,高效存取数据。->这点是在malloc也实现了,并没有提高,而是基本的要求
char* p=(char*)malloc(8); memset(p,0,8); *(int*)(p+1)=1; printf("addr:0x%x,convert addr:0x%x,data:%d ",p,p+3,*(int*)(p+1)); int i; for(i=0; i<8; i++) { printf("p[%d]=%x,",i, *(p+i)); } printf(" "); free(p);
对齐: 为了减少CPU访存次数,CPU 的访问内存有大小和地址上的限制,CPU 只能访问对齐地址上的固定长度的数据,不能跨区间访问。所以,代码里对齐值是多少,CPU并不知道,故如果把一个4字节的变量放在非4的倍数的内存地址上,则需要两次预读取才可完成变量访问,便降低了访问速率。
对齐地址->字长为w,CPU.....那么在设计上就假设了对宽度为w的数据的处理最频繁也是最重要的,所以优先提高对w位数据操作的效率来考虑的+CPU在存取数据时使用w字长的寄存器,每次存取固定大小的数据(以4Byte为例)->大多处理器被优化而对特定的缓存块进行内存读写,在特定的内存地址上预取数据(在这里是4的倍数)。
使用缓存->为了提高命中率,同时最少的周期中取出数据。
固定长度->如果真正需要访问的数据并没有占据那个区间的全部字节范围,就按需进行剔除和合并。
Intel建议在定义数据时遵守那几条规则,即把n字节的数据定义在n的倍数的内存地址上进行对齐->跨平台,32位机里虽然long按8字节对齐,仍然需要两次访存。但如果不安8倍地址对齐,在64位机就需要两次访存;而按8倍地址对齐,就需一次访存。
参考:http://bbs.csdn.net/topics/350174356
http://blog.csdn.net/hairetz/article/details/4084088
对象池--与slab分配机制相通:
两者的设计思想相通,对于大小小于页大小的对象(数据结构),一次分配一大块连续的内存空间,使用完后并不释放(放回内存的空闲表中),而是保留在池/slab块中,等下次需要相同大小的对象时,先从池/slab块中分配。
对于应用层对内存空间的申请和释放很方便。但在底层操作系统,在实际分配内存时,都是按照页为单位分配的。这样,多次分配少于一页的空间,各个分配的空间顺序分配存储,若从中释放空间后无法被利用就会产生碎片。而位大小小于一页的固定大小的对象分配一大块空间,使用时从池中取,用完放回池中,被标记为空闲,下次分配时就可填充进入,防止了页内碎片的产生。
这样做,一方面避免了内存的频繁分配和回收(一个是基于物理内存的分配,一个是逻辑层的)的开销,另一方面,减少了页内碎片的产生