static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
//如果size为常量,比如以这种方式调用kmalloc(32,GFP_KERNEL);
//__builtin_constant_p来确定size是否为常量
if (__builtin_constant_p(size))
{ //找到合适的大小的普通高速缓冲区索引
int i = 0;
#define CACHE(x) /
if (size <= x) /
goto found; /
else /
i++;
#include <linux/kmalloc_sizes.h>
#undef CACHE
return NULL;
found:
//获取普通高速缓冲区描述符指针
cachep = malloc_sizes[i].cs_cachep;
ret = kmem_cache_alloc_notrace(cachep, flags);
return ret;
}
//如果size为变量,则调用__kmalloc分配对象
return __kmalloc(size, flags);
}
在/linux/kmalloc_sizes.h中,定义了一些宏,如下:
……
CACHE(256)
CACHE(512)
……
所以宏展开后变成:
……
if(32<=256)
goto found;
else
i++;
if(32<=512)
goto found;
else
i++;
……
如果size为变量,比如以这种方式调用kmalloc(a,GPF_KERNEL);
则获取高速缓冲区描述符的索引的代码如下:
struct cache_sizes *csizep = malloc_sizes;
while (size > csizep->cs_size)
csizep++;
到底加入常量编译器特性有多少性能提高呢:
只好用个demo来测试了:
Demo1代表常量处理的过程:
int i=0;
#define CACHE(x) /
if (1024<= x) / //1024代表常量size
goto found; /
else /
i++;
CACHE(32)
CACHE(64)
CACHE(96)
CACHE(128)
CACHE(192)
CACHE(256)
CACHE(512)
CACHE(1024)
CACHE(2048)
found:
printf("i=%d/n",i);
return 0;
Demo2代表变量处理的过程:
int a[10]={32,64,96,128,256,512,1024,2048,};
int b=1024;//b代表变量size
int* p=a;
while(b>*p)
p++;
printf("%d/n",*p);
这两段demo都用gcc –S demo1.c demo2.c处理下生成汇编文件,如下:
Demo1.s:
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
//i=0
movl $0, -4(%ebp)
//把i地址赋给寄存器eax
leal -4(%ebp), %eax
//递增i的值
incl (%eax)
leal -4(%ebp), %eax
incl (%eax)
leal -4(%ebp), %eax
incl (%eax)
leal -4(%ebp), %eax
incl (%eax)
leal -4(%ebp), %eax
incl (%eax)
leal -4(%ebp), %eax
incl (%eax)
leal -4(%ebp), %eax
incl (%eax)
//编译器优化的结果就是:if else判断被优化成7次直接的i++。
.L3:
。。。。。。//打印代码略去
Demo2.s:
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
//局部变量b赋值为1024
movl $1024, -4(%ebp)
//获取数组a的开始地址
movl $a, -8(%ebp)
.L2:
//把数组a中某元素的地址赋给edx
movl -8(%ebp), %edx
//把变量b的值赋给eax
movl -4(%ebp), %eax
比较数组a中的元素与b值的大小
cmpl (%edx), %eax
jg .L4
jmp .L3
.L4:
//获取数组的下一个元素
leal -8(%ebp), %eax
addl $4, (%eax)
jmp .L2
.L3:
。。。。。。//打印代码略去
所以demo1只用了14条指令(每次递增2条指令)来获取高速缓冲区的索引。
Demo2每次比较用7条指令*比较次数7=49条指令来获取高速缓冲区的索引。