数据的对齐(alignment)是指数据的地址和由硬件条件决定的内存块大小之间的关系。一个变量的地址是它大小的倍数的时候,这就叫做自然对齐(naturally aligned)。例如,对于一个32bit的变量,如果它的地址是4的倍数,-- 就是说,如果地址的低两位是0,那么这就是自然对齐了。所以,如果一个类型的大小是2n个字节,那么它的地址中,至少低n位是0。
#define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1))
应用场景是
m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);
http://www.oschina.net/question/103620_84473
其实很好理解,&~就是抹去last后面的NGX_ALIGNMENT-1位的值
这样就以NGX_ALIGNMENT对齐了,通俗点说就是NGX_ALIGNMENT的整数倍了
前面加NGX_ALIGNMENT-1就是让地址在last的后面
我说个简单的例子。假设我的每个单元都是8个byte对齐的(p是8字节对齐的)。那么我想知道当前一个指针地址,最近的8 byte对齐的位置,那么怎么办?
(
char
*)(((unsigned
long
long
)p) & (~(7)))
是用来对低3位清0 ,并保持高位信息的。
那么如果我想知道,当前p如果不对齐,那么它下一个最近的,8byte对齐的地址,则可以如下设计
(
char
*)(((unsigned
long
long
)p + 7) & (~(7)))
如果我想动态的对2的幂次方,如2,4,8,16,32,64的对齐进行设计,则我们就不用7,我们 如下
(
char
*)(((unsigned
long
long
)p + n - 1) & (~(n - 1)))
nginx 内存池的内存地址对齐和长度按照2的幂取整
内存池的里面返回的地址,都是经过对齐处理的,这样使用这个对齐的地址比如做memcpy的时候,不用跨cache line 性能更好吧。
http://blog.youkuaiyun.com/niitlcj/article/details/9311189
#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_cpuinfo函数,可以获得ngx_cacheline_size的大小,一般intel为64或128
计算宏ngx_align(1, 64)=64,只要输入d<64,则结果总是64,如果输入d=65,则结果为128,以此类推。
进行内存池管理的时候,对于小于64字节的内存,给分配64字节,使之总是cpu二级缓存读写行的大小倍数,从而有利cpu二级缓存取速度和效率。
ngx_cpuinfo函数实际是调用了汇编代码,获取cpu二级缓存大小!