[PATCH] page allocator: heuristic to reduce fragmentation in buddy

From: Corrado Zoccolo
Date: Mon Nov 30 2009 - 11:42:05 EST


In order to reduce fragmentation, we classify freed pages in two
groups, according to their probability of being part of a high
order merge.
Pages belonging to a compound whose buddy is free are more likely
to be part of a high order merge, so they will be added at the tail
of the freelist. The remaining pages will, instead, be put at the
front of the freelist.

In this way, the pages that are more likely to cause a big merge are
kept free longer. Consequently we tend to aggregate the long-living
allocations on a subset of the compounds, reducing the fragmentation.

Signed-off-by: Corrado Zoccolo <czoccolo@xxxxxxxxx>
---
mm/page_alloc.c | 20 +++++++++++++++++---
1 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2bc2ac6..0f273af 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -451,6 +451,8 @@ static inline void __free_one_page(struct page *page,
int migratetype)
{
unsigned long page_idx;
+ unsigned long combined_idx;
+ bool combined_free = false;

if (unlikely(PageCompound(page)))
if (unlikely(destroy_compound_page(page, order)))
@@ -464,7 +466,6 @@ static inline void __free_one_page(struct page *page,
VM_BUG_ON(bad_range(zone, page));

while (order < MAX_ORDER-1) {
- unsigned long combined_idx;
struct page *buddy;

buddy = __page_find_buddy(page, page_idx, order);
@@ -481,8 +482,21 @@ static inline void __free_one_page(struct page *page,
order++;
}
set_page_order(page, order);
- list_add(&page->lru,
- &zone->free_area[order].free_list[migratetype]);
+
+ if (order < MAX_ORDER-1) {
+ struct page *combined_page, *combined_buddy;
+ combined_idx = __find_combined_index(page_idx, order);
+ combined_page = page + combined_idx - page_idx;
+ combined_buddy = __page_find_buddy(combined_page, combined_idx, order + 1);
+ combined_free = page_is_buddy(combined_page, combined_buddy, order + 1);
+ }
+
+ if (combined_free)
+ list_add_tail(&page->lru,
+ &zone->free_area[order].free_list[migratetype]);
+ else
+ list_add(&page->lru,
+ &zone->free_area[order].free_list[migratetype]);
zone->free_area[order].nr_free++;
}

--
1.6.2.5




--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/