最近看到一个patch,当系统free内存碎片率较高时,通过计算当前系统的内存碎片率来启动lmk来杀进程,以达到释放内存的目的。内存碎片率的概念是相对某个size的连续free内存块而言的,其值从0~1000,值越大,说明内存碎片率越高。
内存碎片率的计算函数位于vmstat.c的函数中,具体如下:
int fragmentation_index(struct zone *zone, unsigned int order)
{
struct contig_page_info info;
fill_contig_page_info(zone, order, &info);//初始化当前zone下的contig_page_info结构体
return __fragmentation_index(order, &info);//计算当前zone相对于某个order下的内存碎片率
}
主要涉及到2个函数fill_contig_page_info()和__fragmentation_index():
static void fill_contig_page_info(struct zone *zone,
unsigned int suitable_order,
struct contig_page_info *info)
{
unsigned int order;
info->free_pages = 0;//当前zone下的free page个数
info->free_blocks_total = 0;//当前zone下free page block的个数,反映在buddyinfo里面就是每个order值的下的block个数相加
info->free_blocks_suitable = 0;//相对于suitable_order而言,当前zone下能划分出2的suitable_order次方连续的free page的内存块数量
for (order = 0; order < MAX_ORDER; order++) {
unsigned long blocks;
/* Count number of free blocks */
blocks = zone->free_area[order].nr_free;
info->free_blocks_total += blocks;
/* Count free base pages */
info->free_pages += blocks << order;
/* Count the suitable free blocks */
if (order >= suitable_order)
info->free_blocks_suitable += blocks <<
(order - suitable_order);
}
}
static int __fragmentation_index(unsigned int order, struct contig_page_info *info)
{
unsigned long requested = 1UL << order;//需要申请连续多少个page
if (!info->free_blocks_total)//当前free page block个数为0表示当前zone下面无free page,则直接返回0
return 0;
/* Fragmentation index only makes sense when a request would fail */
if (info->free_blocks_suitable)//如果当前zone有满足要求的连续free page block,则不用计算碎片率
return -1000;
/*
* Index is between 0 and 1 so return within 3 decimal places
*
* 0 => allocation would fail due to lack of memory
* 1 => allocation would fail due to fragmentation
*/
return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total);//当前zone相对于order的碎片率
}
1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total);
碎片率计算公式看起来很复杂,适当分解下:
内存碎片率=1000-(1000+1000*zone free page数/申请连续page block的page数)/free block个数
处理下为:1000*(1-(1+free page/request)/free block)
从以上公式可以得出,free block的值越大会导致内存碎片率越大,free block越小,则内存碎片率越小。
比如当要申请3个连续page,当前free page有50个,free block也为50个,此时50/3=16个,采用进一法来计算,再加1,可以理解为当前free page的页数相对于request的大小可以分为17个,但是都不连续,则碎片率就是(1 - 17/50)*1000,可见free block越大,碎片率越大,free block个数越少,碎片率越小。