内存池的里面返回的地址,都是经过对齐处理的,这样使用这个对齐的地址比如做memcpy的时候,不用跨cache line 性能更好吧。
又学了一招。
看看使用的代码
http://trac.nginx.org/nginx/browser/nginx/trunk/src/core/ngx_palloc.c
内存池的里面返回的地址,都是经过对齐处理的,这样使用这个对齐的地址比如做memcpy的时候,不用跨cache line 性能更好吧。
又学了一招。
看看使用的代码
http://trac.nginx.org/nginx/browser/nginx/trunk/src/core/ngx_palloc.c
#ifndef NGX_ALIGNMENT
#define NGX_ALIGNMENT sizeof(unsigned long) /* platform word */
#endif
#define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1))
#define ngx_align_ptr(p, a) \
(u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
先分析 (((d) + (a - 1)) & ~(a - 1))表达式
理解表达式 ~(a - 1)注意,其中a为2的幂,设右数第n位为非零位,则a-1为右数的n-1位均为1, 则有~(a-1)为最后的n-1位全为0;
显然可得一个数和2的幂进行 减一取反再按位与操作,即为该数减去(其与a求余的值)
这种计算地址或者长度对齐,取整的宏还是很有用的。cpu访问对齐的数据较快,不对齐的的int之类的,有可能区要多次内存访问才能取到值。
向上取整倍数,ngx_align内存对齐的宏,对于a,传入CPU的二级cache的line大小,通过ngx_cpuinf函数,可以获得ngx_cacheline_size的大小,一般intel为64或128
计算宏ngx_align(1, 64)=64,只要输入d<64,则结果总是64,如果输入d=65,则结果为128,以此类推。
进行内存池管理的时候,对于小于64字节的内存,给分配64字节,使之总是cpu二级缓存读写行的大小倍数,从而有利cpu二级缓存取速度和效率。
ngx_cpuinfo函数实际是调用了汇编代码,获取cpu二级缓存大小!
//==================================================
上面式子,当a等于2的幂的时候,比如,4,8,16等值时,
d加上(a-1) 之后的值肯定要比最小的a的倍数要大的。因为a为2的幂,所以(a - 1) 刚好后面几位都是连续的1,取反之后再相与一下之后,就把小于a的余数部分丢掉了。 不过如果a不是2的幂,比如a=3, d=1 ,那么推算一下,上面的计算就不成立了。
这种计算地址或者长度对齐,取整的宏还是很有用的。cpu访问对齐的数据跟快把,不对齐的的int之类的,有可能区要多次内存访问才能取到值出来。 写个简单的字符串内存池,AllocateString时打算把所有的字符串放到一个连续的内存块上,觉得还是把长度取整一下比较好。这样后续的对字符串的memcpy就是内存字对齐,更好吧。
//=================================================