diff options
author | Christoph Lameter <clameter@sgi.com> | 2007-05-09 13:32:46 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 23:30:46 +0400 |
commit | 5e6d444ea1f72b8148354a9baf0ea8fa3dd0425b (patch) | |
tree | c9c07fd97acd925bfb9c4964240799414243d399 | |
parent | 45edfa580b8e638c44ec26872bfe75b307ba12d1 (diff) | |
download | linux-5e6d444ea1f72b8148354a9baf0ea8fa3dd0425b.tar.xz |
SLUB: rework slab order determination
In some cases SLUB is creating uselessly slabs that are larger than
slub_max_order. Also the layout of some of the slabs was not satisfactory.
Go to an iterarive approach.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/slub.c | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/mm/slub.c b/mm/slub.c index ae2831027802..c81f52a72153 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1577,37 +1577,75 @@ static int slub_nomerge; * requested a higher mininum order then we start with that one instead of * the smallest order which will fit the object. */ -static int calculate_order(int size) +static inline int slab_order(int size, int min_objects, + int max_order, int fract_leftover) { int order; int rem; - for (order = max(slub_min_order, fls(size - 1) - PAGE_SHIFT); - order < MAX_ORDER; order++) { - unsigned long slab_size = PAGE_SIZE << order; + for (order = max(slub_min_order, + fls(min_objects * size - 1) - PAGE_SHIFT); + order <= max_order; order++) { - if (order < slub_max_order && - slab_size < slub_min_objects * size) - continue; + unsigned long slab_size = PAGE_SIZE << order; - if (slab_size < size) + if (slab_size < min_objects * size) continue; - if (order >= slub_max_order) - break; - rem = slab_size % size; - if (rem <= slab_size / 8) + if (rem <= slab_size / fract_leftover) break; } - if (order >= MAX_ORDER) - return -E2BIG; return order; } +static inline int calculate_order(int size) +{ + int order; + int min_objects; + int fraction; + + /* + * Attempt to find best configuration for a slab. This + * works by first attempting to generate a layout with + * the best configuration and backing off gradually. + * + * First we reduce the acceptable waste in a slab. Then + * we reduce the minimum objects required in a slab. + */ + min_objects = slub_min_objects; + while (min_objects > 1) { + fraction = 8; + while (fraction >= 4) { + order = slab_order(size, min_objects, + slub_max_order, fraction); + if (order <= slub_max_order) + return order; + fraction /= 2; + } + min_objects /= 2; + } + + /* + * We were unable to place multiple objects in a slab. Now + * lets see if we can place a single object there. + */ + order = slab_order(size, 1, slub_max_order, 1); + if (order <= slub_max_order) + return order; + + /* + * Doh this slab cannot be placed using slub_max_order. + */ + order = slab_order(size, 1, MAX_ORDER, 1); + if (order <= MAX_ORDER) + return order; + return -ENOSYS; +} + /* * Figure out what the alignment of the objects will be. */ |