jemalloc源码解读(四)长度对齐算法
来源:互联网 发布:python 面向对象 pdf 编辑:程序博客网 时间:2024/05/17 03:37
在现代计算架构中,从内存中读取数据,基本上都是按2^N个字节来从主存加载CPU中。这个值,基本是cache line的大小。也就是说,如果一块内存是是在同一块cache line之内是最快的。目前来说,多数PC的cache line值是128个字节。 对于首地址也是一样的。在32位机器上,如果有4个字节的内存块,跨2个cache line,那么被加载到CPU的时候,需要2次内存缺失中断。
好了,言归正传。对于任何一种小内存请求,都不会按实际大小分配,首先会按照一定规则进行对齐。这种对齐的规则比较复杂,一般会依照系统页大小,机器字大小,和系统特性来定制。通常来说,会在不同区间采用不同的步长。举个例子:
序号大小区间字节对齐0[0--16]81(16 , 128]162(128 , 256]323(256 , 512]64由于每个区间的步长不一样,又被划分成更多的区间。比如(256 , 320]之间长度请求,实际被分配应该是320个字节,而不是512。而1个字节的请求,总是被分配8个字节。
对于任意一个请求Size,为了快速得到他实际应该要被分配的实际长度。这个已经很难通过算法来完成了,因为这个区间的划分有一定不确定性,需要根据经验值来 调整。在jemalloc和tcmalloc他们都采用同样的算法,就是二次查表法。首先建立两个数组 size_to_index和 class_to_size ,size_to_index保存class_to_size的下标,而class_to_size保存对齐后的长度。从jemalloc的size_classes.h和arena.h中挖了一段代码出来,稍微修改后,如下:
typedef unsigned char uint8_t ;#defineSIZE_CLASSES\ SIZE_CLASS(0,8,8)\ SIZE_CLASS(1,8,16)\ SIZE_CLASS(2,16,32)\ SIZE_CLASS(3,16,48)\ SIZE_CLASS(4,16,64)\ SIZE_CLASS(5,16,80)\ SIZE_CLASS(6,16,96)\ SIZE_CLASS(7,16,112)\ SIZE_CLASS(8,16,128)\ SIZE_CLASS(9,32,160)\ SIZE_CLASS(10,32,192)\ SIZE_CLASS(11,32,224)\ SIZE_CLASS(12,32,256)\ SIZE_CLASS(13,64,320)\ SIZE_CLASS(14,64,384)\ SIZE_CLASS(15,64,448)\ SIZE_CLASS(16,64,512)\ SIZE_CLASS(17,128,640)\ SIZE_CLASS(18,128,768)\ SIZE_CLASS(19,128,896)\ SIZE_CLASS(20,128,1024)\ SIZE_CLASS(21,256,1280)\ SIZE_CLASS(22,256,1536)\ SIZE_CLASS(23,256,1792)\ SIZE_CLASS(24,256,2048)\ SIZE_CLASS(25,512,2560)\ SIZE_CLASS(26,512,3072)\ SIZE_CLASS(27,512,3584)\#defineNBINS28#defineSMALL_MAXCLASS3584const uint8_tsmall_size2bin[] = {#defineS2B_8(i)i,#defineS2B_16(i)S2B_8(i) S2B_8(i)#defineS2B_32(i)S2B_16(i) S2B_16(i)#defineS2B_64(i)S2B_32(i) S2B_32(i)#defineS2B_128(i)S2B_64(i) S2B_64(i)#defineS2B_256(i)S2B_128(i) S2B_128(i)#defineS2B_512(i)S2B_256(i) S2B_256(i)#defineS2B_1024(i)S2B_512(i) S2B_512(i)#defineS2B_2048(i)S2B_1024(i) S2B_1024(i)#defineS2B_4096(i)S2B_2048(i) S2B_2048(i)#defineS2B_8192(i)S2B_4096(i) S2B_4096(i)#defineSIZE_CLASS(bin, delta, size)\S2B_##delta(bin)SIZE_CLASSES#undef S2B_8#undef S2B_16#undef S2B_32#undef S2B_64#undef S2B_128#undef S2B_256#undef S2B_512#undef S2B_1024#undef S2B_2048#undef S2B_4096#undef S2B_8192#undef SIZE_CLASS};typedef struct __arena_bin_info_t{ size_t reg_size ;} arena_bin_info_t ;arena_bin_info_tarena_bin_info[NBINS];void bin_info_init(void){arena_bin_info_t *bin_info;size_t prev_run_size = 4096;#defineSIZE_CLASS(bin, delta, size)\bin_info = &arena_bin_info[bin];\bin_info->reg_size = size;SIZE_CLASSES#undef SIZE_CLASS}void test_size_class() { FILE * file = fopen("small_size2bin.txt" , "w+b") ; size_t size = sizeof(small_size2bin) ; fprintf(file , "sizeof[small_size2bin] = %u \n" , size) ; for(size_t idx = 0 ; idx < size ; ++idx) { fprintf(file , "idx[%u] , value[%hhu] \n" , idx , small_size2bin[idx]) ; } fclose(file) ;}void test_reg_size() { memset(arena_bin_info , 0 , sizeof(arena_bin_info)) ; bin_info_init() ; FILE * file = fopen("arena_bin_info.txt" , "w+b") ; size_t size = sizeof(arena_bin_info) ; fprintf(file , "sizeof[arena_bin_info] = %u , count[%u]\n" , size , NBINS) ; for(size_t idx = 0 ; idx < NBINS ; ++idx) { fprintf(file , "idx[%u] , reg_size[%hhu] \n" , idx , arena_bin_info[idx].reg_size) ; } fclose(file) ;}
代码中的数组small_size2bin等价于 size_to_index,arena_bin_info数组等价于class_to_size。
依据这两个数据,对于任何一个长度,要得到对应的对齐长度,就很简单了,如下:
size_t align(size_t size){ return arena_bin_info[size_to_index[size >> 3]] ;}
这个算法是一致的,但是建立class_to_size和size_to_index结果的算法,却不一样。jemalloc用宏的方式,显示指定每个区间的步长的。tcmalloc的算法比较先进,下面是他的算法,详细参见gperftools的common.cc文件的AlignmentForSize函数:
1、如果Size > MaxSize,那么就以PageSize对齐
2、如果Size >= 128 ,从32开始,以2的倍数,增长步长。如下表
这种算法见LgFloor函数,他的主要原则就是保证内存浪费利率控制1/8。因此,步长/区间上限=1/8。
3、如果Size >= 16,那么按16对齐
4、小于16就按8对齐。
- jemalloc源码解读(四)长度对齐算法
- jemalloc源码解读(五)内存布局
- jemalloc源码解读(六)基数树
- jemalloc源码解读(一)内存页的地址
- jemalloc源码解读(二)内存页的管理
- jemalloc源码解读(三)内存页的管理的另解
- AFNetwork 3.0 源码解读(四)AFURLResponseSerialization
- MPAndroidChart系列源码解读(四)
- jquery3.0源码解读(四)Callbacks
- THUCTC源码解读(四)
- jieba分词源码解读四
- 比特币源码解读四
- Netty源码解读(四)Netty与Reactor模式
- Netty源码解读(四)Netty与Reactor模式
- Netty源码解读(四)Netty与Reactor模式
- Netty源码解读(四)Netty与Reactor模式
- AFNetworking 3.0 源码解读(四)之 AFURLResponseSerialization
- Netty源码解读(四)Netty与Reactor模式
- 推荐二级页面新
- 如何在windows上开发php模块
- MySql按列分组然后求和
- Next higher number with same number of set bits
- jsp基础知识点详解
- jemalloc源码解读(四)长度对齐算法
- C++实现字符串替换的两种方法
- Domino导出excel
- vi /etc/sysconfig/network
- 8中nosql产品简介
- android学习笔记之获取手机屏幕大小
- 乘法运算
- JSP和JSTL获取服务器参数
- [译]在Tiled Map中使用碰撞检测(一) 创建基于Tiled Map的游戏