linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christoph Lameter <clameter@sgi.com>
To: Jens Axboe <jens.axboe@oracle.com>
Cc: Andi Kleen <andi@firstfloor.org>,
	Pekka Enberg <penberg@cs.helsinki.fi>,
	David Chinner <dgc@sgi.com>, David Miller <davem@davemloft.net>,
	cebbert@redhat.com, willy@linux.intel.com,
	nickpiggin@yahoo.com.au, hch@lst.de, mel@skynet.ie,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	suresh.b.siddha@intel.com
Subject: Re: SLUB performance regression vs SLAB
Date: Fri, 5 Oct 2007 12:32:57 -0700 (PDT)	[thread overview]
Message-ID: <Pine.LNX.4.64.0710051231280.17562@schroedinger.engr.sgi.com> (raw)
In-Reply-To: <Pine.LNX.4.64.0710051229570.17562@schroedinger.engr.sgi.com>

Patch 2/2


SLUB: Allow foreign objects on the per cpu object lists.

In order to free objects we need to touch the page struct of the page that the
object belongs to. If this occurs too frequently then we could generate a bouncing
cacheline.

We do not want that to occur too frequently. We can avoid the page struct touching
for per cpu objects. Now we extend that to allow a limited number of objects that are
not part of the cpu slab. Allow up to 4 times the objects that fit into a page
in the per cpu list.

If the objects are allocated before we need to free them then we have saved touching
a page struct twice. The objects are presumably cache hot, so it is performance wise
good to recycle these locally.

Foreign objects are drained before deactivating cpu slabs and if too many objects
accumulate.

For kmem_cache_free() this also has the beneficial effect of getting virt_to_page()
operations eliminated or grouped together which may help reduce the cache footprint
and increase the speed of virt_to_page() lookups (they hopefully all come from the
same pages).

For kfree() we may have to do virt_to_page() in the worst case twice. Once grouped
together.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/slub_def.h |    1 
 mm/slub.c                |   82 ++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 68 insertions(+), 15 deletions(-)

Index: linux-2.6.23-rc8-mm2/include/linux/slub_def.h
===================================================================
--- linux-2.6.23-rc8-mm2.orig/include/linux/slub_def.h	2007-10-04 22:42:08.000000000 -0700
+++ linux-2.6.23-rc8-mm2/include/linux/slub_def.h	2007-10-04 22:43:19.000000000 -0700
@@ -16,6 +16,7 @@ struct kmem_cache_cpu {
 	struct page *page;
 	int node;
 	int remaining;
+	int drain_limit;
 	unsigned int offset;
 	unsigned int objsize;
 };
Index: linux-2.6.23-rc8-mm2/mm/slub.c
===================================================================
--- linux-2.6.23-rc8-mm2.orig/mm/slub.c	2007-10-04 22:42:08.000000000 -0700
+++ linux-2.6.23-rc8-mm2/mm/slub.c	2007-10-04 22:56:49.000000000 -0700
@@ -187,6 +187,12 @@ static inline void ClearSlabDebug(struct
  */
 #define MAX_PARTIAL 10
 
+/*
+ * How many times the number of objects per slab can accumulate on the
+ * per cpu objects list before we drain it.
+ */
+#define DRAIN_FACTOR 4
+
 #define DEBUG_DEFAULT_FLAGS (SLAB_DEBUG_FREE | SLAB_RED_ZONE | \
 				SLAB_POISON | SLAB_STORE_USER)
 
@@ -1375,6 +1381,54 @@ static void unfreeze_slab(struct kmem_ca
 	}
 }
 
+static void __slab_free(struct kmem_cache *s, struct page *page,
+				void *x, void *addr, unsigned int offset);
+
+/*
+ * Drain freelist of objects foreign to the slab. Interrupts must be off.
+ *
+ * This is called
+ *
+ * 1. Before taking the slub lock when a cpu slab is to be deactivated.
+ *    Deactivation can only deal with native objects on the freelist.
+ *
+ * 2. If the number of objects in the per cpu structures grows beyond
+ *    3 times the objects that fit in a slab. In that case we need to throw
+ *    some objects away. Stripping the foreign objects does the job and
+ *    localizes any new the allocations.
+ */
+static void drain_foreign(struct kmem_cache *s, struct kmem_cache_cpu *c, void *addr)
+{
+	void **freelist = c->freelist;
+
+	if (unlikely(c->node < 0)) {
+		/* Slow path user */
+		__slab_free(s, virt_to_head_page(freelist), freelist, addr, c->offset);
+		freelist = NULL;
+		c->remaining--;
+	}
+
+	if (!freelist)
+		return;
+
+	c->freelist = NULL;
+	c->remaining = 0;
+
+	while (freelist) {
+		void **object = freelist;
+		struct page *page = virt_to_head_page(freelist);
+
+		freelist = freelist[c->offset];
+		if (page == c->page) {
+			/* Local object. Keep for future allocations */
+			object[c->offset] = c->freelist;
+			c->freelist = object;
+			c->remaining++;
+		} else
+			__slab_free(s, page, object, NULL, c->offset);
+	}
+}
+
 /*
  * Remove the cpu slab
  */
@@ -1405,6 +1459,7 @@ static void deactivate_slab(struct kmem_
 
 static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
 {
+	drain_foreign(s, c, NULL);
 	slab_lock(c->page);
 	deactivate_slab(s, c);
 }
@@ -1480,6 +1535,7 @@ static void *__slab_alloc(struct kmem_ca
 	if (!c->page)
 		goto new_slab;
 
+	drain_foreign(s, c, NULL);
 	slab_lock(c->page);
 	if (unlikely(!node_match(c, node)))
 		goto another_slab;
@@ -1553,6 +1609,7 @@ debug:
 	c->page->inuse++;
 	c->page->freelist = object[c->offset];
 	c->node = -1;
+	c->remaining = s->objects * 64;
 	slab_unlock(c->page);
 	return object;
 }
@@ -1676,8 +1733,8 @@ debug:
  * If fastpath is not possible then fall back to __slab_free where we deal
  * with all sorts of special processing.
  */
-static void __always_inline slab_free(struct kmem_cache *s,
-			struct page *page, void *x, void *addr)
+static void __always_inline slab_free(struct kmem_cache *s, void *x,
+								void *addr)
 {
 	void **object = (void *)x;
 	unsigned long flags;
@@ -1686,23 +1743,17 @@ static void __always_inline slab_free(st
 	local_irq_save(flags);
 	debug_check_no_locks_freed(object, s->objsize);
 	c = get_cpu_slab(s, smp_processor_id());
-	if (likely(page == c->page && c->node >= 0)) {
-		object[c->offset] = c->freelist;
-		c->freelist = object;
-		c->remaining++;
-	} else
-		__slab_free(s, page, x, addr, c->offset);
-
+	object[c->offset] = c->freelist;
+	c->freelist = object;
+	c->remaining++;
+	if (unlikely(c->remaining >= c->drain_limit))
+		drain_foreign(s, c, addr);
 	local_irq_restore(flags);
 }
 
 void kmem_cache_free(struct kmem_cache *s, void *x)
 {
-	struct page *page;
-
-	page = virt_to_head_page(x);
-
-	slab_free(s, page, x, __builtin_return_address(0));
+	slab_free(s, x, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
@@ -1879,6 +1930,7 @@ static void init_kmem_cache_cpu(struct k
 	c->node = 0;
 	c->offset = s->offset / sizeof(void *);
 	c->objsize = s->objsize;
+	c->drain_limit = DRAIN_FACTOR * s->objects;
 }
 
 static void init_kmem_cache_node(struct kmem_cache_node *n)
@@ -2626,7 +2678,7 @@ void kfree(const void *x)
 		put_page(page);
 		return;
 	}
-	slab_free(page->slab, page, (void *)x, __builtin_return_address(0));
+	slab_free(page->slab, (void *)x, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(kfree);
 


  reply	other threads:[~2007-10-05 19:32 UTC|newest]

Thread overview: 110+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-19  3:36 [00/17] [RFC] Virtual Compound Page Support Christoph Lameter
2007-09-19  3:36 ` [01/17] Vmalloc: Move vmalloc_to_page to mm/vmalloc Christoph Lameter
2007-09-19  3:36 ` [02/17] Vmalloc: add const Christoph Lameter
2007-09-19  3:36 ` [03/17] is_vmalloc_addr(): Check if an address is within the vmalloc boundaries Christoph Lameter
2007-09-19  6:32   ` David Rientjes
2007-09-19  7:24     ` Anton Altaparmakov
2007-09-19  8:09       ` David Rientjes
2007-09-19  8:44         ` Anton Altaparmakov
2007-09-19  9:19           ` David Rientjes
2007-09-19 13:23             ` Anton Altaparmakov
2007-09-19 17:29           ` Christoph Lameter
2007-09-19 17:52             ` Anton Altaparmakov
2007-09-19 17:29       ` Christoph Lameter
2007-09-19 17:52         ` Anton Altaparmakov
2007-09-19  3:36 ` [04/17] vmalloc: clean up page array indexing Christoph Lameter
2007-09-19  3:36 ` [05/17] vunmap: return page array Christoph Lameter
2007-09-19  8:05   ` KAMEZAWA Hiroyuki
2007-09-19 22:15     ` Christoph Lameter
2007-09-20  0:47       ` KAMEZAWA Hiroyuki
2007-09-19  3:36 ` [06/17] vmalloc_address(): Determine vmalloc address from page struct Christoph Lameter
2007-09-19  3:36 ` [07/17] GFP_VFALLBACK: Allow fallback of compound pages to virtual mappings Christoph Lameter
2007-09-19  3:36 ` [08/17] Pass vmalloc address in page->private Christoph Lameter
2007-09-19  3:36 ` [09/17] VFALLBACK: Debugging aid Christoph Lameter
2007-09-19  3:36 ` [10/17] Use GFP_VFALLBACK for sparsemem Christoph Lameter
2007-09-19  3:36 ` [11/17] GFP_VFALLBACK for zone wait table Christoph Lameter
2007-09-19  3:36 ` [12/17] Virtual Compound page allocation from interrupt context Christoph Lameter
2007-09-19  3:36 ` [13/17] Virtual compound page freeing in " Christoph Lameter
2007-09-18 20:36   ` Nick Piggin
2007-09-20 17:50     ` Christoph Lameter
2007-09-19  3:36 ` [14/17] Allow bit_waitqueue to wait on a bit in a vmalloc area Christoph Lameter
2007-09-19  4:12   ` Gabriel C
2007-09-19 17:40     ` Christoph Lameter
2007-09-19  3:36 ` [15/17] SLUB: Support virtual fallback via SLAB_VFALLBACK Christoph Lameter
2007-09-27 21:42   ` Nick Piggin
2007-09-28 17:33     ` Christoph Lameter
2007-09-28  5:14       ` Nick Piggin
2007-10-01 20:50         ` Christoph Lameter
2007-10-02  8:43           ` Nick Piggin
2007-10-04 16:16           ` SLUB performance regression vs SLAB Matthew Wilcox
2007-10-04 17:38             ` Christoph Lameter
2007-10-04 17:50               ` Arjan van de Ven
2007-10-04 17:58                 ` Christoph Lameter
2007-10-04 18:26                 ` Peter Zijlstra
2007-10-04 20:48                 ` David Miller
2007-10-04 20:58                   ` Matthew Wilcox
2007-10-04 21:05                     ` David Miller
2007-10-04 21:11                     ` Christoph Lameter
2007-10-04 18:32               ` Matthew Wilcox
2007-10-04 17:49                 ` Christoph Lameter
2007-10-04 19:28                   ` Matthew Wilcox
2007-10-04 19:05                     ` Christoph Lameter
2007-10-04 19:46                       ` Siddha, Suresh B
2007-10-04 20:55                     ` David Miller
2007-10-04 21:02                       ` Chuck Ebbert
2007-10-04 21:11                         ` David Miller
2007-10-04 21:47                           ` Chuck Ebbert
2007-10-04 22:07                             ` David Miller
2007-10-04 22:23                               ` David Chinner
2007-10-05  6:48                                 ` Jens Axboe
2007-10-05  9:19                                   ` Pekka Enberg
2007-10-05  9:28                                     ` Jens Axboe
2007-10-05 11:12                                       ` Andi Kleen
2007-10-05 12:39                                         ` Jens Axboe
2007-10-05 19:31                                           ` Christoph Lameter
2007-10-05 19:32                                             ` Christoph Lameter [this message]
2007-10-05 11:56                                   ` Matthew Wilcox
2007-10-05 12:37                                     ` Jens Axboe
2007-10-05 19:27                                     ` Christoph Lameter
2007-10-05 20:32                         ` Peter Zijlstra
2007-10-05 21:31                           ` David Miller
2007-10-04 21:05                       ` Matthew Wilcox
2007-10-05  2:43                         ` Christoph Lameter
2007-10-05  2:53                           ` Arjan van de Ven
2007-09-28 17:55       ` [15/17] SLUB: Support virtual fallback via SLAB_VFALLBACK Peter Zijlstra
2007-09-28 18:20         ` Christoph Lameter
2007-09-28 18:25           ` Peter Zijlstra
2007-09-28 18:41             ` Christoph Lameter
2007-09-28 20:22               ` Nick Piggin
2007-09-28 21:14               ` Mel Gorman
2007-09-28 20:59             ` Mel Gorman
2007-09-29  8:13             ` Andrew Morton
2007-09-29  8:47               ` Peter Zijlstra
2007-09-29  8:53                 ` Peter Zijlstra
2007-09-29  9:01                   ` Andrew Morton
2007-09-29  9:14                     ` Peter Zijlstra
2007-09-29  9:27                       ` Andrew Morton
2007-09-28 20:19                         ` Nick Piggin
2007-09-29 19:20                           ` Andrew Morton
2007-09-29 19:09                             ` Nick Piggin
2007-09-30 20:12                               ` Andrew Morton
2007-09-30  4:16                                 ` Nick Piggin
2007-09-29  9:00                 ` Andrew Morton
2007-10-01 20:55                   ` Christoph Lameter
2007-10-01 21:30                     ` Andrew Morton
2007-10-01 21:38                       ` Christoph Lameter
2007-10-01 21:45                         ` Andrew Morton
2007-10-01 21:52                           ` Christoph Lameter
2007-10-02  9:19                       ` Peter Zijlstra
2007-09-29  8:45           ` Peter Zijlstra
2007-10-01 21:01             ` Christoph Lameter
2007-10-02  8:37               ` Nick Piggin
2007-09-28 21:05       ` Mel Gorman
2007-10-01 21:10         ` Christoph Lameter
2007-09-19  3:36 ` [16/17] Allow virtual fallback for buffer_heads Christoph Lameter
2007-09-19  3:36 ` [17/17] Allow virtual fallback for dentries Christoph Lameter
2007-09-19  7:34 ` [00/17] [RFC] Virtual Compound Page Support Anton Altaparmakov
2007-09-19  8:34   ` Eric Dumazet
2007-09-19 17:33     ` Christoph Lameter
2007-09-19  8:24 ` Andi Kleen
2007-09-19 17:36   ` 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=Pine.LNX.4.64.0710051231280.17562@schroedinger.engr.sgi.com \
    --to=clameter@sgi.com \
    --cc=andi@firstfloor.org \
    --cc=cebbert@redhat.com \
    --cc=davem@davemloft.net \
    --cc=dgc@sgi.com \
    --cc=hch@lst.de \
    --cc=jens.axboe@oracle.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mel@skynet.ie \
    --cc=nickpiggin@yahoo.com.au \
    --cc=penberg@cs.helsinki.fi \
    --cc=suresh.b.siddha@intel.com \
    --cc=willy@linux.intel.com \
    /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;
as well as URLs for NNTP newsgroup(s).