public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Pekka Enberg" <penberg@cs.helsinki.fi>
To: akpm@osdl.org
Cc: linux-kernel@vger.kernel.org, manfred@colorfullife.com
Subject: [patch 04/10] slab: cache_estimate cleanup
Date: Sat, 14 Jan 2006 14:46:04 +0200	[thread overview]
Message-ID: <20060114122415.163755000@localhost> (raw)
In-Reply-To: 20060114122249.246354000@localhost

From: Steven Rostedt <rostedt@goodmis.org>

This patch cleans up cache_estimate() in mm/slab.c and improves the
algorithm from O(n) to O(1). We first calculate the maximum number of
objects a slab can hold after struct slab and kmem_bufctl_t for each
object has been given enough space. After that, to respect alignment
rules, we decrease the number of objects if necessary. As required
padding is at most align-1 and memory of obj_size is at least align,
it is always enough to decrease number of objects by one.

The optimization was originally made by Balbir Singh with more 
improvements from Steven Rostedt. Manfred Spraul provider further
modifications: no loop at all for the off-slab case and added comments
to explain the background.

Acked-by: Balbir Singh <bsingharora@gmail.com>
Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
---

 mm/slab.c |   87 ++++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 62 insertions(+), 25 deletions(-)

Index: 2.6/mm/slab.c
===================================================================
--- 2.6.orig/mm/slab.c
+++ 2.6/mm/slab.c
@@ -700,32 +700,69 @@ kmem_cache_t *kmem_find_general_cachep(s
 }
 EXPORT_SYMBOL(kmem_find_general_cachep);
 
-/* Cal the num objs, wastage, and bytes left over for a given slab size. */
-static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
-			   int flags, size_t *left_over, unsigned int *num)
+static size_t slab_mgmt_size(size_t nr_objs, size_t align)
 {
-	int i;
-	size_t wastage = PAGE_SIZE << gfporder;
-	size_t extra = 0;
-	size_t base = 0;
-
-	if (!(flags & CFLGS_OFF_SLAB)) {
-		base = sizeof(struct slab);
-		extra = sizeof(kmem_bufctl_t);
-	}
-	i = 0;
-	while (i * size + ALIGN(base + i * extra, align) <= wastage)
-		i++;
-	if (i > 0)
-		i--;
-
-	if (i > SLAB_LIMIT)
-		i = SLAB_LIMIT;
-
-	*num = i;
-	wastage -= i * size;
-	wastage -= ALIGN(base + i * extra, align);
-	*left_over = wastage;
+	return ALIGN(sizeof(struct slab)+nr_objs*sizeof(kmem_bufctl_t), align);
+}
+
+/* Calculate the number of objects and left-over bytes for a given
+   buffer size. */
+static void cache_estimate(unsigned long gfporder, size_t buffer_size,
+			   size_t align, int flags, size_t *left_over,
+			   unsigned int *num)
+{
+	int nr_objs;
+	size_t mgmt_size;
+	size_t slab_size = PAGE_SIZE << gfporder;
+
+	/*
+	 * The slab management structure can be either off the slab or
+	 * on it. For the latter case, the memory allocated for a
+	 * slab is used for:
+	 *
+	 * - The struct slab
+	 * - One kmem_bufctl_t for each object
+	 * - Padding to respect alignment of @align
+	 * - @buffer_size bytes for each object
+	 *
+	 * If the slab management structure is off the slab, then the
+	 * alignment will already be calculated into the size. Because
+	 * the slabs are all pages aligned, the objects will be at the
+	 * correct alignment when allocated.
+	 */
+	if (flags & CFLGS_OFF_SLAB) {
+		mgmt_size = 0;
+		nr_objs = slab_size / buffer_size;
+
+		if (nr_objs > SLAB_LIMIT)
+			nr_objs = SLAB_LIMIT;
+	} else {
+		/*
+		 * Ignore padding for the initial guess. The padding
+		 * is at most @align-1 bytes, and @buffer_size is at
+		 * least @align. In the worst case, this result will
+		 * be one greater than the number of objects that fit
+		 * into the memory allocation when taking the padding
+		 * into account.
+		 */
+		nr_objs = (slab_size - sizeof(struct slab)) /
+			  (buffer_size + sizeof(kmem_bufctl_t));
+
+		/*
+		 * This calculated number will be either the right
+		 * amount, or one greater than what we want.
+		 */
+		if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size
+		       > slab_size)
+			nr_objs--;
+
+		if (nr_objs > SLAB_LIMIT)
+			nr_objs = SLAB_LIMIT;
+
+		mgmt_size = slab_mgmt_size(nr_objs, align);
+	}
+	*num = nr_objs;
+	*left_over = slab_size - nr_objs*buffer_size - mgmt_size;
 }
 
 #define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg)

--


  parent reply	other threads:[~2006-01-14 12:47 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-01-14 12:46 [patch 00/10] slab updates Pekka Enberg
2006-01-14 12:46 ` [patch 01/10] slab: distinguish between object and buffer size Pekka Enberg
2006-01-14 12:46 ` [patch 02/10] slab: minor cleanup to kmem_cache_alloc_node Pekka Enberg
2006-01-14 12:46 ` [patch 03/10] slab: have index_of bug at compile time Pekka Enberg
2006-01-14 12:46 ` Pekka Enberg [this message]
2006-01-16  2:38   ` [patch 04/10] slab: cache_estimate cleanup Andrew Morton
2006-01-16  7:00     ` Pekka J Enberg
2006-01-14 12:46 ` [patch 06/10] slab: extract slab_{put|get}_obj Pekka Enberg
2006-01-14 12:46 ` [patch 05/10] slab: extract slab_destroy_objs() Pekka Enberg
2006-01-18 18:31   ` Christoph Lameter
2006-01-19  9:07     ` Pekka J Enberg
2006-01-20  5:18     ` Horst von Brand
2006-01-14 12:46 ` [patch 08/10] slab: extract virt_to_{cache|slab} Pekka Enberg
2006-01-14 12:46 ` [patch 07/10] slab: reduce inlining Pekka Enberg
2006-01-14 12:46 ` [patch 10/10] slab: replace kmem_cache_t with struct kmem_cache Pekka Enberg
2006-01-14 12:46 ` [patch 09/10] slab: rename ac_data to cpu_cache_get Pekka Enberg

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=20060114122415.163755000@localhost \
    --to=penberg@cs.helsinki.fi \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=manfred@colorfullife.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