2003.04.21读核日记--发现linux在初始化BUDDY算法的数据结构时很低效
今日读BUDDY内存分配算法,算法确实很不错,但LINUX在初始化BUDDY算法的数据结构时很低效。
我先打个比喻:给你一个大碗,里面装满了大米,现在让你大米转移到
另一个碗里,你是把米从一个碗直接倒到另一个碗里,还是把米一粒一粒从一个碗放到另一个碗里?答案是明确的,直接倒。
而linux在初始化BUDDY算法的数据结构时却选择了类似把米从一个碗一粒一粒放到另一个碗里方法。
好了,看看系统是如何初始化BUDDY算法的数据结构的。
BUDDY在回收页面时一般用free_pages(),free_page(),它们都要实现伙伴的合并。而且最多9-order次合并。
在mem_init()中,通过对所有的动态内存进行逐页扫描,并调用free_page()来把空页一页一页的插入BUDDY中。
事实上,动态内存就那么几大块,所以完全可以用一个递归函数用很少的
次数就可完成工作。
我写了一个:
buddy_init( start_addr,end_addr, order)
//start_addr,end_addr为要释放的内存块首尾,order为要插入的BUDDY槽号
{unsigned long mask=(~0ul)<<order; //生成以order为边界的掩码
page * start,end; //中间以order为边界的大块的首尾地址
if(order==0)
{free_page(start_addr); return; } //递归出口,即只有一页要求释放
//求出start,end;
start=(start_addr+(1<<order)-1)&mask;
end= end_addr&mask;
for(tmp=start,tmp<end,tmp+=1<<order)
{free_pages(tmp,order); //中间以order为边界的大块的释放
}
if(start_addr!=start) //若相等,则说明没有左零头,不用再递归
buddy_init(start_addr,start,order-1);
if(end_addr!=end) //若相等,则说明没有右零头,不用再递归
buddy_init(end,end_addr,order-1);
}
函数写的不严密,但其思想是尽量用free_pages()来大块大块的插入,
因为这样一次最多可释放512页,比一页一页效率高多了。
|