Commit 5e6d444e authored by Christoph Lameter's avatar Christoph Lameter Committed by Linus Torvalds

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: default avatarChristoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 45edfa58
...@@ -1577,35 +1577,73 @@ static int slub_nomerge; ...@@ -1577,35 +1577,73 @@ static int slub_nomerge;
* requested a higher mininum order then we start with that one instead of * requested a higher mininum order then we start with that one instead of
* the smallest order which will fit the object. * 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 order;
int rem; int rem;
for (order = max(slub_min_order, fls(size - 1) - PAGE_SHIFT); for (order = max(slub_min_order,
order < MAX_ORDER; order++) { fls(min_objects * size - 1) - PAGE_SHIFT);
order <= max_order; order++) {
unsigned long slab_size = PAGE_SIZE << order; unsigned long slab_size = PAGE_SIZE << order;
if (order < slub_max_order && if (slab_size < min_objects * size)
slab_size < slub_min_objects * size)
continue; continue;
if (slab_size < size) rem = slab_size % size;
continue;
if (order >= slub_max_order) if (rem <= slab_size / fract_leftover)
break; break;
rem = slab_size % size; }
if (rem <= slab_size / 8) return order;
break; }
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;
} }
if (order >= MAX_ORDER)
return -E2BIG;
/*
* 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; 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;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment