Linux内存碎片率的实现方式

最近看到一个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个数越少,碎片率越小。

你可能感兴趣的:(Linux,memory,management)