From: Christoph Lameter <clameter@sgi.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@vger.kernel.org
Cc: suresh.b.siddha@intel.com
Cc: corey.d.gough@intel.com
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: akpm@linux-foundation.org
Subject: [patch 04/10] SLUB: Move page->offset to kmem_cache_cpu->offset
Date: Sat, 07 Jul 2007 20:49:56 -0700 [thread overview]
Message-ID: <20070708035016.869389788@sgi.com> (raw)
In-Reply-To: 20070708034952.022985379@sgi.com
[-- Attachment #1: slub_move_offset_to_cpu --]
[-- Type: text/plain, Size: 8228 bytes --]
We need the offset during slab_alloc and slab_free. In both cases we also
reference the cacheline of the kmem_cache_cpu structure. We can therefore
move the offset field into the kmem_cache_cpu structure freeing up 16 bits
in the page flags.
Moving the offset allows an allocation from slab_alloc() without
touching the page struct in the hot path.
The only thing left in slab_free() that touches the page struct cacheline for
per cpu freeing is the checking of SlabDebug(page). The next patch deals with
that.
Use the available 16 bits to broaden page->inuse. That way we can have more
than 64k objects per slab and can get rid of the checks for that limitation.
No need anymore to shrink the order of slabs if we boot with 2M sized slabs
(slub_min_order=9).
No need anymore to switch off the offset calculation for very large slabs
since the field in the kmem_cache_cpu structure is 32 bits and so the offset
field can now handle slab sizes of up to 8GB.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
include/linux/mm_types.h | 5 ---
include/linux/slub_def.h | 1
mm/slub.c | 75 ++++++++++-------------------------------------
3 files changed, 19 insertions(+), 62 deletions(-)
Index: linux-2.6.22-rc6-mm1/mm/slub.c
===================================================================
--- linux-2.6.22-rc6-mm1.orig/mm/slub.c 2007-07-06 23:35:49.000000000 -0700
+++ linux-2.6.22-rc6-mm1/mm/slub.c 2007-07-07 12:02:41.000000000 -0700
@@ -207,11 +207,6 @@ static inline void ClearSlabDebug(struct
#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
#endif
-/*
- * The page->inuse field is 16 bit thus we have this limitation
- */
-#define MAX_OBJECTS_PER_SLAB 65535
-
/* Internal SLUB flags */
#define __OBJECT_POISON 0x80000000 /* Poison object */
@@ -741,11 +736,6 @@ static int check_slab(struct kmem_cache
slab_err(s, page, "Not a valid slab page");
return 0;
}
- if (page->offset * sizeof(void *) != s->offset) {
- slab_err(s, page, "Corrupted offset %lu",
- (unsigned long)(page->offset * sizeof(void *)));
- return 0;
- }
if (page->inuse > s->objects) {
slab_err(s, page, "inuse %u > max %u",
s->name, page->inuse, s->objects);
@@ -884,8 +874,6 @@ bad:
slab_fix(s, "Marking all objects used");
page->inuse = s->objects;
page->freelist = NULL;
- /* Fix up fields that may be corrupted */
- page->offset = s->offset / sizeof(void *);
}
return 0;
}
@@ -1001,30 +989,12 @@ __setup("slub_debug", setup_slub_debug);
static void kmem_cache_open_debug_check(struct kmem_cache *s)
{
/*
- * The page->offset field is only 16 bit wide. This is an offset
- * in units of words from the beginning of an object. If the slab
- * size is bigger then we cannot move the free pointer behind the
- * object anymore.
- *
- * On 32 bit platforms the limit is 256k. On 64bit platforms
- * the limit is 512k.
- *
- * Debugging or ctor may create a need to move the free
- * pointer. Fail if this happens.
+ * Enable debugging if selected on the kernel commandline.
*/
- if (s->objsize >= 65535 * sizeof(void *)) {
- BUG_ON(s->flags & (SLAB_RED_ZONE | SLAB_POISON |
- SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
- BUG_ON(s->ctor);
- }
- else
- /*
- * Enable debugging if selected on the kernel commandline.
- */
- if (slub_debug && (!slub_debug_slabs ||
- strncmp(slub_debug_slabs, s->name,
- strlen(slub_debug_slabs)) == 0))
- s->flags |= slub_debug;
+ if (slub_debug && (!slub_debug_slabs ||
+ strncmp(slub_debug_slabs, s->name,
+ strlen(slub_debug_slabs)) == 0))
+ s->flags |= slub_debug;
}
#else
static inline void setup_object_debug(struct kmem_cache *s,
@@ -1109,7 +1079,6 @@ static struct page *new_slab(struct kmem
atomic_long_inc(&n->nr_slabs);
page->inuse = 0;
- page->offset = s->offset / sizeof(void *);
page->slab = s;
start = page_address(page);
@@ -1410,10 +1379,10 @@ static void deactivate_slab(struct kmem_
/* Retrieve object from cpu_freelist */
object = c->freelist;
- c->freelist = c->freelist[page->offset];
+ c->freelist = c->freelist[c->offset];
/* And put onto the regular freelist */
- object[page->offset] = page->freelist;
+ object[c->offset] = page->freelist;
page->freelist = object;
page->inuse--;
}
@@ -1509,7 +1478,7 @@ load_freelist:
goto debug;
object = c->page->freelist;
- c->freelist = object[c->page->offset];
+ c->freelist = object[c->offset];
c->page->inuse = s->objects;
c->page->freelist = NULL;
c->node = page_to_nid(c->page);
@@ -1561,7 +1530,7 @@ debug:
goto another_slab;
c->page->inuse++;
- c->page->freelist = object[c->page->offset];
+ c->page->freelist = object[c->offset];
slab_unlock(c->page);
return object;
}
@@ -1592,7 +1561,7 @@ static void __always_inline *slab_alloc(
else {
object = c->freelist;
- c->freelist = object[c->page->offset];
+ c->freelist = object[c->offset];
}
local_irq_restore(flags);
@@ -1625,7 +1594,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
* handling required then we can return immediately.
*/
static void __slab_free(struct kmem_cache *s, struct page *page,
- void *x, void *addr)
+ void *x, void *addr, unsigned int offset)
{
void *prior;
void **object = (void *)x;
@@ -1635,7 +1604,7 @@ static void __slab_free(struct kmem_cach
if (unlikely(SlabDebug(page)))
goto debug;
checks_ok:
- prior = object[page->offset] = page->freelist;
+ prior = object[offset] = page->freelist;
page->freelist = object;
page->inuse--;
@@ -1695,10 +1664,10 @@ static void __always_inline slab_free(st
local_irq_save(flags);
c = get_cpu_slab(s, smp_processor_id());
if (likely(page == c->page && !SlabDebug(page))) {
- object[page->offset] = c->freelist;
+ object[c->offset] = c->freelist;
c->freelist = object;
} else
- __slab_free(s, page, x, addr);
+ __slab_free(s, page, x, addr, c->offset);
local_irq_restore(flags);
}
@@ -1794,8 +1763,7 @@ static inline int slab_order(int size, i
* If we would create too many object per slab then reduce
* the slab order even if it goes below slub_min_order.
*/
- while (min_order > 0 &&
- (PAGE_SIZE << min_order) >= MAX_OBJECTS_PER_SLAB * size)
+ while (min_order > 0 && PAGE_SIZE << min_order)
min_order--;
for (order = max(min_order,
@@ -1812,9 +1780,6 @@ static inline int slab_order(int size, i
if (rem <= slab_size / fract_leftover)
break;
- /* If the next size is too high then exit now */
- if (slab_size * 2 >= MAX_OBJECTS_PER_SLAB * size)
- break;
}
return order;
@@ -1894,6 +1859,7 @@ static void init_kmem_cache_cpu(struct k
{
c->page = NULL;
c->freelist = NULL;
+ c->offset = s->offset / sizeof(void *);
c->node = 0;
}
@@ -2115,14 +2081,7 @@ static int calculate_sizes(struct kmem_c
*/
s->objects = (PAGE_SIZE << s->order) / size;
- /*
- * Verify that the number of objects is within permitted limits.
- * The page->inuse field is only 16 bit wide! So we cannot have
- * more than 64k objects per slab.
- */
- if (!s->objects || s->objects > MAX_OBJECTS_PER_SLAB)
- return 0;
- return 1;
+ return !!s->objects;
}
Index: linux-2.6.22-rc6-mm1/include/linux/mm_types.h
===================================================================
--- linux-2.6.22-rc6-mm1.orig/include/linux/mm_types.h 2007-07-06 23:35:49.000000000 -0700
+++ linux-2.6.22-rc6-mm1/include/linux/mm_types.h 2007-07-06 23:35:50.000000000 -0700
@@ -24,10 +24,7 @@ struct page {
* to show when page is mapped
* & limit reverse map searches.
*/
- struct { /* SLUB uses */
- short unsigned int inuse;
- short unsigned int offset;
- };
+ unsigned int inuse; /* SLUB: Nr of objects */
};
union {
struct {
Index: linux-2.6.22-rc6-mm1/include/linux/slub_def.h
===================================================================
--- linux-2.6.22-rc6-mm1.orig/include/linux/slub_def.h 2007-07-06 23:35:49.000000000 -0700
+++ linux-2.6.22-rc6-mm1/include/linux/slub_def.h 2007-07-07 12:01:39.000000000 -0700
@@ -15,6 +15,7 @@ struct kmem_cache_cpu {
void **freelist;
struct page *page;
int node;
+ unsigned int offset;
/* Lots of wasted space */
} ____cacheline_aligned_in_smp;
--
next prev parent reply other threads:[~2007-07-08 3:51 UTC|newest]
Thread overview: 86+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-08 3:49 [patch 00/10] [RFC] SLUB patches for more functionality, performance and maintenance Christoph Lameter
2007-07-08 3:49 ` [patch 01/10] SLUB: Direct pass through of page size or higher kmalloc requests Christoph Lameter
2007-07-08 3:49 ` [patch 02/10] SLUB: Avoid page struct cacheline bouncing due to remote frees to cpu slab Christoph Lameter
2007-07-08 3:49 ` [patch 03/10] SLUB: Do not use page->mapping Christoph Lameter
2007-07-08 3:49 ` Christoph Lameter [this message]
2007-07-08 3:49 ` [patch 05/10] SLUB: Avoid touching page struct when freeing to per cpu slab Christoph Lameter
2007-07-08 3:49 ` [patch 06/10] SLUB: Place kmem_cache_cpu structures in a NUMA aware way Christoph Lameter
2007-07-08 3:49 ` [patch 07/10] SLUB: Optimize cacheline use for zeroing Christoph Lameter
2007-07-08 3:50 ` [patch 08/10] SLUB: Single atomic instruction alloc/free using cmpxchg Christoph Lameter
2007-07-08 3:50 ` [patch 09/10] Remove the SLOB allocator for 2.6.23 Christoph Lameter
2007-07-08 7:51 ` Ingo Molnar
2007-07-08 9:43 ` Nick Piggin
2007-07-08 9:54 ` Ingo Molnar
2007-07-08 10:23 ` Nick Piggin
2007-07-08 10:42 ` Ingo Molnar
2007-07-08 18:02 ` Andrew Morton
2007-07-09 2:57 ` Nick Piggin
2007-07-09 11:04 ` Pekka Enberg
2007-07-09 11:16 ` Nick Piggin
2007-07-09 12:47 ` Pekka Enberg
2007-07-09 13:46 ` Pekka J Enberg
2007-07-09 16:08 ` Christoph Lameter
2007-07-10 8:17 ` Pekka J Enberg
2007-07-10 8:27 ` Nick Piggin
2007-07-10 9:31 ` Pekka Enberg
2007-07-10 10:09 ` Nick Piggin
2007-07-10 12:02 ` Matt Mackall
2007-07-10 12:57 ` Pekka J Enberg
2007-07-10 22:12 ` Christoph Lameter
2007-07-10 22:40 ` Matt Mackall
2007-07-10 22:50 ` Christoph Lameter
2007-07-09 16:06 ` Christoph Lameter
2007-07-09 16:51 ` Andrew Morton
2007-07-09 17:26 ` Christoph Lameter
2007-07-09 18:00 ` Andrew Morton
2007-07-10 1:43 ` Nick Piggin
2007-07-10 1:56 ` Christoph Lameter
2007-07-10 2:02 ` Nick Piggin
2007-07-10 2:11 ` Christoph Lameter
2007-07-10 7:09 ` Nick Piggin
2007-07-10 22:09 ` Christoph Lameter
2007-07-10 23:12 ` Matt Mackall
2007-07-10 8:32 ` Matt Mackall
2007-07-10 9:01 ` Håvard Skinnemoen
2007-07-10 9:11 ` Nick Piggin
2007-07-10 9:21 ` Håvard Skinnemoen
2007-07-11 1:37 ` Christoph Lameter
2007-07-11 2:06 ` Matt Mackall
2007-07-11 18:06 ` Christoph Lameter
2007-07-11 18:25 ` Pekka J Enberg
2007-07-11 18:33 ` Christoph Lameter
2007-07-11 18:36 ` Pekka J Enberg
2007-07-12 0:33 ` Nick Piggin
2007-07-09 23:09 ` Matt Mackall
2007-07-10 1:41 ` Nick Piggin
2007-07-10 1:51 ` Christoph Lameter
2007-07-10 1:58 ` Nick Piggin
2007-07-10 6:22 ` Matt Mackall
2007-07-10 7:03 ` Nick Piggin
2007-07-10 2:32 ` Matt Mackall
2007-07-09 21:57 ` Matt Mackall
2007-07-09 12:31 ` Matthieu CASTET
2007-07-09 16:00 ` Christoph Lameter
2007-07-09 20:52 ` Matt Mackall
2007-07-08 3:50 ` [patch 10/10] Remove slab in 2.6.24 Christoph Lameter
2007-07-08 4:37 ` [patch 00/10] [RFC] SLUB patches for more functionality, performance and maintenance David Miller
2007-07-09 15:45 ` Christoph Lameter
2007-07-09 19:43 ` David Miller
2007-07-09 21:21 ` Christoph Lameter
2007-07-08 11:20 ` Andi Kleen
2007-07-09 15:50 ` Christoph Lameter
2007-07-09 15:59 ` Martin Bligh
2007-07-09 18:11 ` Christoph Lameter
2007-07-09 21:00 ` Martin Bligh
2007-07-09 21:44 ` Mathieu Desnoyers
2007-07-09 21:55 ` Christoph Lameter
2007-07-09 22:58 ` Mathieu Desnoyers
2007-07-09 23:08 ` Christoph Lameter
2007-07-10 5:16 ` [PATCH] x86_64 - Use non locked version for local_cmpxchg() Mathieu Desnoyers
2007-07-10 20:46 ` Christoph Lameter
2007-07-10 0:55 ` [patch 00/10] [RFC] SLUB patches for more functionality, performance and maintenance Christoph Lameter
2007-07-10 8:27 ` Mathieu Desnoyers
2007-07-10 18:38 ` Christoph Lameter
2007-07-10 20:59 ` Mathieu Desnoyers
2007-08-13 22:18 ` Mathieu Desnoyers
2007-08-13 22:28 ` Christoph Lameter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070708035016.869389788@sgi.com \
--to=clameter@sgi.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox