nginx 内存对齐 cpu l2 cache line ngx_align

数据的对齐(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.csdn.net/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二级缓存大小!

你可能感兴趣的:(nginx 内存对齐 cpu l2 cache line ngx_align)