Linuxメモリフラグメント率の実現方法


最近、システムfreeのメモリフラグメント率が高い場合、現在のシステムのメモリフラグメント率を計算することによってlmkを起動してプロセスを殺し、メモリを解放する目的を達成するpatchが見られました.メモリフラグメント率の概念は、ある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つの連続ページを申請する場合、現在のfreeページは50個あり、free blockも50個である.この場合50/3=16個は、進一法で計算する.
さらに1を加えると、現在のfree pageのページ数はrequestのサイズに対して17個に分けることができるが、連続していない場合、フラグメント率は(1-17/50)*1000であり、free blockが大きいほどフラグメント率が大きくなり、free block個数が少ないほどフラグメント率が小さくなることがわかる.