Skip to contentSkip to conversation

+ fix-spellings-of-slab-allocator-section-in-init-kconfig.patch added to -mm tree

PATCH In review [email protected] 7 participants 37 messages May 8, 2007 – May 10, 2007 Memory management

lore
Share & tools
lore

[email protected]

author maintainer tree notice
#0 lore raw

The patch titled
Fix spellings of slab allocator section in init/Kconfig
has been added to the -mm tree. Its filename is
fix-spellings-of-slab-allocator-section-in-init-kconfig.patch

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this

------------------------------------------------------
Subject: Fix spellings of slab allocator section in init/Kconfig
From: Christoph Lameter <[email protected]>

Fix some of the spelling issues. Fix sentences. Discourage SLOB use since SLUB can pack objects denser.

---

 init/Kconfig |   15 +++++++--------
 1 files changed, 7 insertions(+), 8 deletions(-)
init/Kconfig renamed from init/Kconfig~fix-spellings-of-slab-allocator-section-in-init-kconfig +7 -8
diff -puN init/Kconfig~fix-spellings-of-slab-allocator-section-in-init-kconfig init/Kconfig
@@ -523,9 +523,9 @@ config SLAB
 	bool "SLAB"
 	help
 	  The regular slab allocator that is established and known to work
-	  well in all environments. It organizes chache hot objects in
+	  well in all environments. It organizes cache hot objects in
 	  per cpu and per node queues. SLAB is the default choice for
-	  slab allocator.
+	  a slab allocator.
 
 config SLUB
 	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
@@ -535,21 +535,20 @@ config SLUB
 	   instead of managing queues of cached objects (SLAB approach).
 	   Per cpu caching is realized using slabs of objects instead
 	   of queues of objects. SLUB can use memory efficiently
-	   way and has enhanced diagnostics.
+	   and has enhanced diagnostics.
 
 config SLOB
 #
-#	SLOB cannot support SMP because SLAB_DESTROY_BY_RCU does not work
-#	properly.
+#	SLOB does not support SMP because SLAB_DESTROY_BY_RCU is unsupported
 #
 	depends on EMBEDDED && !SMP && !SPARSEMEM
 	bool "SLOB (Simple Allocator)"
 	help
 	   SLOB replaces the SLAB allocator with a drastically simpler
 	   allocator.  SLOB is more space efficient that SLAB but does not
-	   scale well (single lock for all operations) and is more susceptible
-	   to fragmentation. SLOB it is a great choice to reduce
-	   memory usage and code size for embedded systems.
+	   scale well (single lock for all operations) and is also highly
+	   susceptible to fragmentation. SLUB can accomplish a higher object
+	   density. It is usually better to use SLUB instead of SLOB.
 
 endchoice
 

_

Patches currently in -mm which might be from [email protected] are

origin.patch slub-add-support-for-dynamic-cacheline-size-determination.patch slub-add-support-for-dynamic-cacheline-size-determination-fix.patch slub-after-object-padding-only-needed-for-redzoning.patch slub-slabinfo-upgrade.patch slub-use-check_valid_pointer-in-kmem_ptr_validate.patch slub-clean-up-krealloc.patch
slub-clean-up-krealloc-fix.patch slub-get-rid-of-finish_bootstrap.patch
slub-update-comments.patch slub-add-macros-for-scanning-objects-in-a-slab.patch slub-move-resiliency-check-into-sysfs-section.patch slub-introduce-debugslabpage.patch
slub-consolidate-trace-code.patch slub-move-tracking-definitions-and-check_valid_pointer-away-from-debug-code.patch slub-add-config_slub_debug.patch slub-include-lifetime-stats-and-sets-of-cpus--nodes-in-tracking-output.patch slub-include-lifetime-stats-and-sets-of-cpus--nodes-in-tracking-output-fix.patch slub-rework-slab-order-determination.patch fix-spellings-of-slab-allocator-section-in-init-kconfig.patch slub-support-concurrent-local-and-remote-frees-and-allocs-on-a-slab.patch quicklist-support-for-ia64.patch
quicklist-support-for-x86_64.patch slub-exploit-page-mobility-to-increase-allocation-order.patch slub-mm-only-make-slub-the-default-slab-allocator.patch slub-reduce-antifrag-max-order.patch
slub-i386-support.patch
remove-constructor-from-buffer_head.patch slab-shutdown-cache_reaper-when-cpu-goes-down.patch mm-implement-swap-prefetching.patch revoke-core-code-slab-allocators-remove-slab_debug_initial-flag-revoke.patch vmstat-use-our-own-timer-events.patch vmstat-use-our-own-timer-events-fix.patch make-vm-statistics-update-interval-configurable.patch make-vm-statistics-update-interval-configurable-fix.patch move-remote-node-draining-out-of-slab-allocators.patch

#1 lore raw

init/Kconfig config SLUB · line 551

Quoted 10 lines · On Tue, May 08, 2007 at 04:02:20PM -0700, [email protected] wrote:
init/Kconfig renamed from init/Kconfig~fix-spellings-of-slab-allocator-section-in-init-kconfig +3 -3
 	bool "SLOB (Simple Allocator)"
 	help
 	   SLOB replaces the SLAB allocator with a drastically simpler
 	   allocator.  SLOB is more space efficient that SLAB but does not
-	   scale well (single lock for all operations) and is more susceptible
-	   to fragmentation. SLOB it is a great choice to reduce
-	   memory usage and code size for embedded systems.
+	   scale well (single lock for all operations) and is also highly
+	   susceptible to fragmentation. SLUB can accomplish a higher object
+	   density. It is usually better to use SLUB instead of SLOB.

This isn't accurate.

First, SLOB no longer runs on SMP because SLAB grew some RCU-related hair. So it now effectively has no locks at all!

Second, I think the fragmentation issues are exaggerated. Before SLAB was introduced, Linux's kmalloc was the moral equivalent of SLOB (without SLAB emulation) and fragmentation was not the driving force for replacement. Small Linux 1.x machines frequently had uptimes of 1+ years without fragmenting to death. Instead, it was performance with large amounts of RAM - the old kmalloc (and SLOB) have performance proportional to memory size.

Third, I don't think it's possible even in theory for a SLAB-like allocator to be as efficient as SLOB simply due to the constraints of putting only objects of the same size on a given page. So consider me skeptical on the density claim.

It is usually better to use SLUB simply because you're more likely to have 1GB of RAM rather than 4MB.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#2 lore raw
Quoted 3 lines

(without SLAB emulation) and fragmentation was not the driving force for replacement. Small Linux 1.x machines frequently had uptimes of 1+ years without fragmenting to death. Instead, it was performance with

8MB for a bit over 3 years.... (1.2.13lmp)

The fragmentation issue I think is overbaked. A lot of the academic work argues that there is pretty much no long term difference between first fit, best fit, and most of the clever algorithms (obviously stupid ones like "take the middle out of the biggest space allocator" do perform worse). For MMUless boxes fragmentation is a big issue but not for normal systems.

Alan

#3 lore raw
Quoted 4 lines · Alan Cox
Quoted 3 lines

(without SLAB emulation) and fragmentation was not the driving force for replacement. Small Linux 1.x machines frequently had uptimes of 1+ years without fragmenting to death. Instead, it was performance with

Quoted 8 lines

8MB for a bit over 3 years.... (1.2.13lmp)

The fragmentation issue I think is overbaked. A lot of the academic work argues that there is pretty much no long term difference between first fit, best fit, and most of the clever algorithms (obviously stupid ones like "take the middle out of the biggest space allocator" do perform worse). For MMUless boxes fragmentation is a big issue but not for normal systems.

Further, the received wisdom that fragmentation of SLAB-like systems is better is not above doubt. Our own issues with dcache fragmentation suggest it's far from perfect.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#4 lore raw
Quoted 3 lines · Matt Mackall

Further, the received wisdom that fragmentation of SLAB-like systems is better is not above doubt. Our own issues with dcache fragmentation suggest it's far from perfect.

I guess that you have not seen the slab defrag code for SLUB then.

#5 lore raw
In reply to Matt Mackall
Quoted 2 lines · Matt Mackall

First, SLOB no longer runs on SMP because SLAB grew some RCU-related hair. So it now effectively has no locks at all!

Well it seems that SLOB was not well maintained. RCU has been around for a long time and SLOB has not been updated to cope with it.

Quoted 4 lines

Third, I don't think it's possible even in theory for a SLAB-like allocator to be as efficient as SLOB simply due to the constraints of putting only objects of the same size on a given page. So consider me skeptical on the density claim.

SLUB can put 32 objects sized 128 byte each in a 4k page. Can SLOB do the same?

Quoted 2 lines

It is usually better to use SLUB simply because you're more likely to have 1GB of RAM rather than 4MB.

SLUB should be perfectly fine for that environment provided you adjust the cacheline alignment and switch off SLUB debugging. define L1_CACHE_BYTES to be 4 or so.

#6 lore raw
Quoted 7 lines · Christoph Lameter
Quoted 2 lines · Matt Mackall

First, SLOB no longer runs on SMP because SLAB grew some RCU-related hair. So it now effectively has no locks at all!

Well it seems that SLOB was not well maintained. RCU has been around for a long time and SLOB has not been updated to cope with it.

RCU's incursion into SLAB that broke SLOB is relatively new. And it only broke for people using SMP or SPARSEMEM. Intersection with target audience of SLOB: ~0.

Quoted 7 lines
Quoted 4 lines

Third, I don't think it's possible even in theory for a SLAB-like allocator to be as efficient as SLOB simply due to the constraints of putting only objects of the same size on a given page. So consider me skeptical on the density claim.

SLUB can put 32 objects sized 128 byte each in a 4k page. Can SLOB do the same?

Yes. It can in fact put 512 8-byte objects in a 4k page. More importantly, it can put 2 1k objects and 16 128-byte objects on the same page instead of on two pages.

Quoted 6 lines
Quoted 2 lines

It is usually better to use SLUB simply because you're more likely to have 1GB of RAM rather than 4MB.

SLUB should be perfectly fine for that environment provided you adjust the cacheline alignment and switch off SLUB debugging. define L1_CACHE_BYTES to be 4 or so.

Perhaps. We'll need to look at some numbers.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#7 lore raw
Quoted 6 lines · Matt Mackall
Quoted 5 lines · Christoph Lameter
Quoted 2 lines · Matt Mackall

First, SLOB no longer runs on SMP because SLAB grew some RCU-related hair. So it now effectively has no locks at all!

Quoted 6 lines
Quoted 2 lines

Well it seems that SLOB was not well maintained. RCU has been around for a long time and SLOB has not been updated to cope with it.

RCU's incursion into SLAB that broke SLOB is relatively new. And it only broke for people using SMP or SPARSEMEM. Intersection with target audience of SLOB: ~0.

New meaning in the last 3 years?

Quoted 4 lines
Quoted 2 lines

SLUB can put 32 objects sized 128 byte each in a 4k page. Can SLOB do the same?

Yes. It can in fact put 512 8-byte objects in a 4k page. More

So can SLUB.

Quoted 2 lines

importantly, it can put 2 1k objects and 16 128-byte objects on the same page instead of on two pages.

That SLUB cannot do. And I do not believe you. SLOB must have some way to distinguish the objects and their sizes since kfree does not include size information. You can mix slabs of different size on the same page without metadata. Magic?

So how does kfree then know how to free the object? There must be some way where you get the metainformation. What is the point of your 8 byte metadata that keeps getting inserted? That does not consume memory on a page?

#8 lore raw

From: Christoph Lameter <[email protected]>
Date: Tue, 8 May 2007 18:32:35 -0700 (PDT)

Quoted 9 lines

That SLUB cannot do. And I do not believe you. SLOB must have some way to distinguish the objects and their sizes since kfree does not include size information. You can mix slabs of different size on the same page without metadata. Magic?

So how does kfree then know how to free the object? There must be some way where you get the metainformation. What is the point of your 8 byte metadata that keeps getting inserted? That does not consume memory on a page?

SLOB uses metadata, but that metadata seemingly only needs to be uptodate in freed objects.

SLOB seems to look at the descriptor in the previous blob to figure out how big the being-freed blob is. That's actually kind of clever :-)

#9 lore raw
Quoted 3 lines · David Miller

SLOB seems to look at the descriptor in the previous blob to figure out how big the being-freed blob is. That's actually kind of clever :-)

We were assuming that the objects are actually allocated. How does it figure out the previous blobs boundaries without metadata?

#10 lore raw

From: Christoph Lameter <[email protected]>
Date: Tue, 8 May 2007 18:53:28 -0700 (PDT)

Quoted 8 lines · David Miller
Quoted 4 lines

SLOB seems to look at the descriptor in the previous blob to figure out how big the being-freed blob is. That's actually kind of clever :-)

We were assuming that the objects are actually allocated. How does it figure out the previous blobs boundaries without metadata?

The page is filled entirely with descriptors in the not-in-use regions of the page aparently. So "freed_object - 1" will always give you a descriptor.

I'm just reading over the code to figure out what to type to you, you could read the code too it's not very complicated :-)

#11 lore raw
Quoted 2 lines · David Miller

I'm just reading over the code to figure out what to type to you, you could read the code too it's not very complicated :-)

I have read it numerous times and my conclusion is that it uses the descriptors for that purpose. But Matt claims they are not necessary. So I am just trying to figure out how one can get to that conclusion.

#12 lore raw

From: Christoph Lameter <[email protected]>
Date: Tue, 8 May 2007 18:57:04 -0700 (PDT)

Quoted 8 lines · David Miller
Quoted 3 lines

I'm just reading over the code to figure out what to type to you, you could read the code too it's not very complicated :-)

I have read it numerous times and my conclusion is that it uses the descriptors for that purpose. But Matt claims they are not necessary. So I am just trying to figure out how one can get to that conclusion.

He is saying the metadata is not necessary for allocated objects. At least that's my take.

#13 lore raw
Quoted 7 lines · David Miller

From: Christoph Lameter <[email protected]>
Date: Tue, 8 May 2007 18:57:04 -0700 (PDT)

Quoted 3 lines · David Miller
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

I'm just reading over the code to figure out what to type to you, you could read the code too it's not very complicated :-)

I have read it numerous times and my conclusion is that it uses the descriptors for that purpose. But Matt claims they are not necessary. So I am just trying to figure out how one can get to that conclusion.

He is saying the metadata is not necessary for allocated objects. At least that's my take.

Right. You only need to know blob boundaries for free blobs (so you can allocate from or merge to). For allocated blobs, you know the start (which is the address of the memory), and the end (which is the start + the size contained in kmem_cache structure).

Signature · 1 line
SUSE Labs, Novell Inc.
#14 lore raw
Quoted 4 lines · Nick Piggin

Right. You only need to know blob boundaries for free blobs (so you can allocate from or merge to). For allocated blobs, you know the start (which is the address of the memory), and the end (which is the start + the size contained in kmem_cache structure).

For kmalloc caches you will not have the object size on kfree. In that case the slob_t structure is needed before the object.

#15 lore raw
In reply to David Miller
Quoted 9 lines · David Miller

From: Christoph Lameter <[email protected]>
Date: Tue, 8 May 2007 18:32:35 -0700 (PDT)

Quoted 3 lines

That SLUB cannot do. And I do not believe you. SLOB must have some way to distinguish the objects and their sizes since kfree does not include size information. You can mix slabs of different size on the same page without metadata. Magic?

So how does kfree then know how to free the object? There must be some way where you get the metainformation. What is the point of your 8 byte metadata that keeps getting inserted? That does not consume memory on a page?

Quoted 6 lines

SLOB uses metadata, but that metadata seemingly only needs to be uptodate in freed objects.

SLOB seems to look at the descriptor in the previous blob to figure out how big the being-freed blob is. That's actually kind of clever :-)

You know how big the being-freed blob is because the kmem cache structure contains that. The free metadata is just needed for free area management.

BTW, we _really_ should be doing RCU properly in slob, because you technically can't noop RCU on UP (even though the current users may be safe...).

Patch attached to do that.

Signature · 1 line
SUSE Labs, Novell Inc.
mm/slob.c +40 -6
Index: linux-2.6/mm/slob.c
===================================================================
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/timer.h>
+#include <linux/rcupdate.h>
 
 struct slob_block {
 	int units;
@@ -53,6 +54,11 @@
 };
 typedef struct bigblock bigblock_t;
 
+struct slob_rcu {
+	struct rcu_head rcu_head;
+	int size;
+};
+
 static slob_t arena = { .next = &arena, .units = 1 };
 static slob_t *slobfree = &arena;
 static bigblock_t *bigblocks;
@@ -242,6 +248,7 @@
 
 struct kmem_cache {
 	unsigned int size, align;
+	unsigned long flags;
 	const char *name;
 	void (*ctor)(void *, struct kmem_cache *, unsigned long);
 	void (*dtor)(void *, struct kmem_cache *, unsigned long);
@@ -259,6 +266,11 @@
 	if (c) {
 		c->name = name;
 		c->size = size;
+		if (flags & SLAB_DESTROY_BY_RCU) {
+			/* leave room for rcu header at the start of object */
+			c->size += sizeof(struct slob_rcu);
+		}
+		c->flags = flags;
 		c->ctor = ctor;
 		c->dtor = dtor;
 		/* ignore alignment unless it's forced */
@@ -281,11 +293,14 @@
 {
 	void *b;
 
-	if (c->size < PAGE_SIZE)
+	if (c->size < PAGE_SIZE) {
 		b = slob_alloc(c->size, flags, c->align);
-	else
+	} else
 		b = (void *)__get_free_pages(flags, find_order(c->size));
 
+	if (unlikely(c->flags & SLAB_DESTROY_BY_RCU))
+		b += sizeof(struct slob_rcu);
+
 	if (c->ctor)
 		c->ctor(b, c, SLAB_CTOR_CONSTRUCTOR);
 
@@ -303,15 +318,34 @@
 }
 EXPORT_SYMBOL(kmem_cache_zalloc);
 
+static void __kmem_cache_free(void *b, int size)
+{
+	if (size < PAGE_SIZE)
+		slob_free(b, size);
+	else
+		free_pages((unsigned long)b, find_order(size));
+}
+
+static void kmem_rcu_free(struct rcu_head *head)
+{
+	struct slob_rcu *slob_rcu = (struct slob_rcu *)head;
+
+	__kmem_cache_free(head, slob_rcu->size);
+}
+
 void kmem_cache_free(struct kmem_cache *c, void *b)
 {
 	if (c->dtor)
 		c->dtor(b, c, 0);
 
-	if (c->size < PAGE_SIZE)
-		slob_free(b, c->size);
-	else
-		free_pages((unsigned long)b, find_order(c->size));
+	if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
+		struct slob_rcu *slob_rcu;
+		b -= sizeof(struct slob_rcu);
+		slob_rcu = b;
+		slob_rcu->size = c->size;
+		call_rcu(&slob_rcu->rcu_head, kmem_rcu_free);
+	} else
+		__kmem_cache_free(b, c->size);
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
init/Kconfig +1 -1
Index: linux-2.6/init/Kconfig
===================================================================
@@ -476,7 +476,7 @@
 
 config SLAB
 	default y
-	bool "Use full SLAB allocator" if (EMBEDDED && !SMP && !SPARSEMEM)
+	bool "Use full SLAB allocator" if (EMBEDDED && !SPARSEMEM)
 	help
 	  Disabling this replaces the advanced SLAB allocator and
 	  kmalloc support with the drastically simpler SLOB allocator.
#16 lore raw
Quoted 3 lines · Nick Piggin

BTW, we _really_ should be doing RCU properly in slob, because you technically can't noop RCU on UP (even though the current users may be safe...).

Thanks. Hugh was pretty convinced it was unneeded:

http://marc.info/?l=linux-mm&m=116413907023393&w=2

And since I didn't care much about the SMP case, I didn't pursue it.

This almost looks reasonable. I think HW_ALIGN | RCU is going to make it break though:

mm/slob.c line 303

Quoted 3 lines
mm/slob.c +3 -0
+	if (unlikely(c->flags & SLAB_DESTROY_BY_RCU))
+		b += sizeof(struct slob_rcu);
+

That could be dealt with by putting the slob_rcu at the end of the object and having the RCU helper function use ->size to work backward to the actual pointer.

mm/slob.c line 339

Quoted 4 lines

void kmem_cache_free(struct kmem_cache *c, void *b) {

mm/slob.c +0 -0
 	if (c->dtor)
 		c->dtor(b, c, 0);

I think if we want RCU to actually work, we want to run ->dtor in __kmem_cache_free?

mm/slob.c line 345

Quoted 9 lines
mm/slob.c +5 -4
-	if (c->size < PAGE_SIZE)
-		slob_free(b, c->size);
-	else
-		free_pages((unsigned long)b, find_order(c->size));
+	if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
+		struct slob_rcu *slob_rcu;
+		b -= sizeof(struct slob_rcu);
+		slob_rcu = b;
+		slob_rcu->size = c->size;

Which means just store c in the header^Wfooter, then we can retrieve the size and the dtor in the RCU helper.

We might as well add slab_is_available and make the damn thing work on sparsemem again too.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#17 lore raw
Quoted 7 lines · Matt Mackall
Quoted 3 lines · Nick Piggin

BTW, we _really_ should be doing RCU properly in slob, because you technically can't noop RCU on UP (even though the current users may be safe...).

Quoted 5 lines

Thanks. Hugh was pretty convinced it was unneeded:

http://marc.info/?l=linux-mm&m=116413907023393&w=2

And since I didn't care much about the SMP case, I didn't pursue it.

Sure the anonvma cache is OK on UP, but I'm just saying that in the general case, you cannot noop RCU on UP systems.

SLAB_DESTROY_BY_RCU is quite a nice way to mitigate some RCU freeing overheads for small objects, so I'd expect it may see wider use in future. Maybe all those users would be fine too, but it's a bit nasty to have already tricky RCU semantics deviate...

Quoted 4 lines

This almost looks reasonable. I think HW_ALIGN | RCU is going to make it break though:

Quoted 8 lines

Review

Quoted 3 lines
(quoted diff) +3 -0
+	if (unlikely(c->flags & SLAB_DESTROY_BY_RCU))
+		b += sizeof(struct slob_rcu);
+

That could be dealt with by putting the slob_rcu at the end of the object and having the RCU helper function use ->size to work backward to the actual pointer.

Sure, OK.

Quoted 8 lines
Quoted 4 lines

void kmem_cache_free(struct kmem_cache *c, void *b)

{
	if (c->dtor)
		c->dtor(b, c, 0);

I think if we want RCU to actually work, we want to run ->dtor in __kmem_cache_free?

Yeah, thinko... thanks.

Quoted 5 lines
Quoted 5 lines
(quoted diff) +1 -4
-	if (c->size < PAGE_SIZE)
-		slob_free(b, c->size);
-	else
-		free_pages((unsigned long)b, find_order(c->size));
+	if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
Quoted 8 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+		struct slob_rcu *slob_rcu;
+		b -= sizeof(struct slob_rcu);
+		slob_rcu = b;
+		slob_rcu->size = c->size;

Which means just store c in the header^Wfooter, then we can retrieve the size and the dtor in the RCU helper.

OK, updated patch (about-to-be-tested) attached.

Signature · 1 line
SUSE Labs, Novell Inc.
mm/slob.c +34 -3
Index: linux-2.6/mm/slob.c
===================================================================
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/timer.h>
+#include <linux/rcupdate.h>
 
 struct slob_block {
 	int units;
@@ -53,6 +54,11 @@
 };
 typedef struct bigblock bigblock_t;
 
+struct slob_rcu {
+	struct rcu_head rcu_head;
+	struct kmem_cache *c;
+};
+
 static slob_t arena = { .next = &arena, .units = 1 };
 static slob_t *slobfree = &arena;
 static bigblock_t *bigblocks;
@@ -242,6 +248,7 @@
 
 struct kmem_cache {
 	unsigned int size, align;
+	unsigned long flags;
 	const char *name;
 	void (*ctor)(void *, struct kmem_cache *, unsigned long);
 	void (*dtor)(void *, struct kmem_cache *, unsigned long);
@@ -259,6 +266,11 @@
 	if (c) {
 		c->name = name;
 		c->size = size;
+		if (flags & SLAB_DESTROY_BY_RCU) {
+			/* leave room for rcu footer at the end of object */
+			c->size += sizeof(struct slob_rcu);
+		}
+		c->flags = flags;
 		c->ctor = ctor;
 		c->dtor = dtor;
 		/* ignore alignment unless it's forced */
@@ -281,9 +293,9 @@
 {
 	void *b;
 
-	if (c->size < PAGE_SIZE)
+	if (c->size < PAGE_SIZE) {
 		b = slob_alloc(c->size, flags, c->align);
-	else
+	} else
 		b = (void *)__get_free_pages(flags, find_order(c->size));
 
 	if (c->ctor)
@@ -303,7 +315,7 @@
 }
 EXPORT_SYMBOL(kmem_cache_zalloc);
 
-void kmem_cache_free(struct kmem_cache *c, void *b)
+static void __kmem_cache_free(struct kmem_cache *c, void *b)
 {
 	if (c->dtor)
 		c->dtor(b, c, 0);
@@ -313,6 +325,25 @@
 	else
 		free_pages((unsigned long)b, find_order(c->size));
 }
+
+static void kmem_rcu_free(struct rcu_head *head)
+{
+	struct slob_rcu *slob_rcu = (struct slob_rcu *)head;
+	void *b = (void *)slob_rcu - slob_rcu->c->size;
+
+	__kmem_cache_free(b, slob_rcu->c);
+}
+
+void kmem_cache_free(struct kmem_cache *c, void *b)
+{
+	if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
+		struct slob_rcu *slob_rcu;
+		slob_rcu = b + c->size;;
+		slob_rcu->c = c;
+		call_rcu(&slob_rcu->rcu_head, kmem_rcu_free);
+	} else
+		__kmem_cache_free(b, c);
+}
 EXPORT_SYMBOL(kmem_cache_free);
 
 unsigned int kmem_cache_size(struct kmem_cache *c)
init/Kconfig +1 -1
Index: linux-2.6/init/Kconfig
===================================================================
@@ -476,7 +476,7 @@
 
 config SLAB
 	default y
-	bool "Use full SLAB allocator" if (EMBEDDED && !SMP && !SPARSEMEM)
+	bool "Use full SLAB allocator" if (EMBEDDED && !SPARSEMEM)
 	help
 	  Disabling this replaces the advanced SLAB allocator and
 	  kmalloc support with the drastically simpler SLOB allocator.
#18 lore raw
Quoted 4 lines · Nick Piggin

SLAB_DESTROY_BY_RCU is quite a nice way to mitigate some RCU freeing overheads for small objects, so I'd expect it may see wider use in future. Maybe all those users would be fine too, but it's a bit nasty to have already tricky RCU semantics deviate...

Signal handling is using RCU too right?

Quoted 4 lines
Quoted 2 lines

I think if we want RCU to actually work, we want to run ->dtor in __kmem_cache_free?

Yeah, thinko... thanks.

According to SLAB code: RCU cannot have a dtor.

kmem_cache_create()

if (flags & SLAB_DESTROY_BY_RCU)
BUG_ON(dtor);

#19 lore raw
In reply to Nick Piggin

mm/slob.c line 332

Quoted 4 lines · Nick Piggin
mm/slob.c +4 -0
+static void kmem_rcu_free(struct rcu_head *head)
+{
+	struct slob_rcu *slob_rcu = (struct slob_rcu *)head;
+	void *b = (void *)slob_rcu - slob_rcu->c->size;

No, I forgot that c->size includes the size of struct slob_rcu here. Will send updated patch which is tested and includes SOB.

Quoted 3 lines
mm/slob.c +3 -0
+
+	__kmem_cache_free(b, slob_rcu->c);
+}
Signature · 1 line
SUSE Labs, Novell Inc.
author maintainer
#20 lore raw
In reply to Nick Piggin
Quoted 5 lines · On Wed, 09 May 2007 12:02:29 +1000 Nick Piggin <[email protected]> wrote:

BTW, we _really_ should be doing RCU properly in slob, because you technically can't noop RCU on UP (even though the current users may be safe...).

Patch attached to do that.

Does it work?

#21 lore raw
Quoted 4 lines · Andrew Morton

On Wed, 09 May 2007 12:02:29 +1000
Nick Piggin <[email protected]> wrote:

Quoted 8 lines
Quoted 5 lines

BTW, we _really_ should be doing RCU properly in slob, because you technically can't noop RCU on UP (even though the current users may be safe...).

Patch attached to do that.

Does it work?

That one booted my desktop (very slowly) but as Matt pointed out, it broke alignment on RCU slabs. The last version I posted should work and has the alignment problem fixed. I can retest and resubmit it to you if you like, I was just waiting on an ack from Matt.

Signature · 1 line
SUSE Labs, Novell Inc.
Acked-by
#22 lore raw
Quoted 12 lines · Nick Piggin
Quoted 11 lines · Andrew Morton
Quoted 5 lines · On Wed, 09 May 2007 12:02:29 +1000 Nick Piggin <[email protected]> wrote:

BTW, we _really_ should be doing RCU properly in slob, because you technically can't noop RCU on UP (even though the current users may be safe...).

Patch attached to do that.

Quoted 6 lines
Quoted 1 line

Does it work?

That one booted my desktop (very slowly) but as Matt pointed out, it broke alignment on RCU slabs. The last version I posted should work and has the alignment problem fixed. I can retest and resubmit it to you if you like, I was just waiting on an ack from Matt.

Looks good to me, but haven't had time to actually test it.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#23 lore raw

PATCH 1/1 slob: implement RCU freeing

Quoted 3 lines · Matt Mackall

Looks good to me, but haven't had time to actually test it.

Updated to current, added a comment, and test booted it again. Works OK.

Signature · 1 line
SUSE Labs, Novell Inc.

The SLOB allocator should implement SLAB_DESTROY_BY_RCU correctly, because even on UP, RCU freeing semantics are not equivalent to simply freeing immediately. This also allows SLOB to be used on SMP.

init/Kconfig +4 -7
Index: linux-2.6/init/Kconfig
===================================================================
@@ -519,7 +519,8 @@
 	  slab allocator.
 
 config SLUB
-	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
+#	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
+	depends on EXPERIMENTAL
 	bool "SLUB (Unqueued Allocator)"
 	help
 	   SLUB is a slab allocator that minimizes cache line usage
@@ -529,15 +530,11 @@
 	   way and has enhanced diagnostics.
 
 config SLOB
-#
-#	SLOB cannot support SMP because SLAB_DESTROY_BY_RCU does not work
-#	properly.
-#
-	depends on EMBEDDED && !SMP && !SPARSEMEM
+	depends on EMBEDDED && !SPARSEMEM
 	bool "SLOB (Simple Allocator)"
 	help
 	   SLOB replaces the SLAB allocator with a drastically simpler
-	   allocator.  SLOB is more space efficient that SLAB but does not
+	   allocator.  SLOB is more space efficient than SLAB but does not
 	   scale well (single lock for all operations) and is more susceptible
 	   to fragmentation. SLOB it is a great choice to reduce
 	   memory usage and code size for embedded systems.
mm/slob.c +45 -7

84 lines not on this page · raw message

#24 lore raw

Re: [patch] slob: implement RCU freeing

init/Kconfig

Quoted 35 lines · Nick Piggin
Quoted 3 lines · Matt Mackall

Looks good to me, but haven't had time to actually test it.

Updated to current, added a comment, and test booted it again. Works OK.

------------------------------------------------------------------------

The SLOB allocator should implement SLAB_DESTROY_BY_RCU correctly, because even on UP, RCU freeing semantics are not equivalent to simply freeing immediately. This also allows SLOB to be used on SMP.

Index: linux-2.6/init/Kconfig
===================================================================

init/Kconfig +2 -1
@@ -519,7 +519,8 @@
 	  slab allocator.
 
 config SLUB
-	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
+#	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
+	depends on EXPERIMENTAL
 	bool "SLUB (Unqueued Allocator)"
 	help
 	   SLUB is a slab allocator that minimizes cache line usage
@@ -529,15 +530,11 @@

Ooops, sorry this hunk leaked in because I wanted to test compile slub :P

Signature · 7 lines
SUSE Labs, Novell Inc.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#25 lore raw

Re: [patch] slob: implement RCU freeing

In reply to Nick Piggin

mm/slob.c line 303

Quoted 10 lines · Nick Piggin
mm/slob.c +6 -0
@@ -283,6 +295,12 @@
 	if (c) {
 		c->name = name;
 		c->size = size;
+		if (flags & SLAB_DESTROY_BY_RCU) {
+			BUG_ON(c->dtor);
+			/* leave room for rcu footer at the end of object */
+			c->size += sizeof(struct slob_rcu);
+		}
+		c->flags = flags;

might want to put this hunt below

mm/slob.c line 305

Quoted 2 lines
mm/slob.c +0 -0
 		c->ctor = ctor;
 		c->dtor = dtor;

here; for c->dtor is not initialised quite yet at the BUG_ON site.

mm/slob.c line 306

Quoted 1 line
mm/slob.c +0 -0
 		/* ignore alignment unless it's forced */

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#26 lore raw

Re: [patch] slob: implement RCU freeing

Quoted 18 lines · Peter Zijlstra

Review line 303

Quoted 10 lines · Nick Piggin
(quoted diff) +6 -0
@@ -283,6 +295,12 @@
 	if (c) {
 		c->name = name;
 		c->size = size;
+		if (flags & SLAB_DESTROY_BY_RCU) {
+			BUG_ON(c->dtor);
+			/* leave room for rcu footer at the end of object */
+			c->size += sizeof(struct slob_rcu);
+		}
+		c->flags = flags;

might want to put this hunt below

Quoted 5 lines

Review line 305

Quoted 2 lines
(quoted diff) +0 -0
 		c->ctor = ctor;
 		c->dtor = dtor;

here; for c->dtor is not initialised quite yet at the BUG_ON site.

Indeed, how's this?

Signature · 1 line
SUSE Labs, Novell Inc.
mm/slob.c +1 -1
Index: linux-2.6/mm/slob.c
===================================================================
@@ -296,7 +296,7 @@ struct kmem_cache *kmem_cache_create(con
 		c->name = name;
 		c->size = size;
 		if (flags & SLAB_DESTROY_BY_RCU) {
-			BUG_ON(c->dtor);
+			BUG_ON(dtor);
 			/* leave room for rcu footer at the end of object */
 			c->size += sizeof(struct slob_rcu);
 		}
#27 lore raw

Re: [patch] slob: implement RCU freeing

Quoted 8 lines · Nick Piggin

Indeed, how's this?

plain text document attachment (slob-add-rcu-fix.patch)
Index: linux-2.6/mm/slob.c
===================================================================

mm/slob.c struct kmem_cache *kmem_cache_create(con · line 302

Quoted 8 lines
mm/slob.c +1 -1
@@ -296,7 +296,7 @@ struct kmem_cache *kmem_cache_create(con
 		c->name = name;
 		c->size = size;
 		if (flags & SLAB_DESTROY_BY_RCU) {
-			BUG_ON(c->dtor);
+			BUG_ON(dtor);
 			/* leave room for rcu footer at the end of object */
 			c->size += sizeof(struct slob_rcu);
 		}

works for me :-)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#28 lore raw
In reply to Christoph Lameter
Quoted 8 lines · Christoph Lameter
Quoted 6 lines · Matt Mackall
Quoted 5 lines · Christoph Lameter
Quoted 2 lines · Matt Mackall

First, SLOB no longer runs on SMP because SLAB grew some RCU-related hair. So it now effectively has no locks at all!

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Well it seems that SLOB was not well maintained. RCU has been around for a long time and SLOB has not been updated to cope with it.

RCU's incursion into SLAB that broke SLOB is relatively new. And it only broke for people using SMP or SPARSEMEM. Intersection with target audience of SLOB: ~0.

New meaning in the last 3 years?

Whatever. I've already told you why it's a dontcare. I'm basically done with this thread until some actual memory usage numbers are injected into it.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

SLUB can put 32 objects sized 128 byte each in a 4k page. Can SLOB do the same?

Yes. It can in fact put 512 8-byte objects in a 4k page. More

So can SLUB.

Not without at least a bit per-object of overhead. So you can either fit 512 objects in 4160 bytes or 504 objects in 4k.

Quoted 8 lines
Quoted 2 lines

importantly, it can put 2 1k objects and 16 128-byte objects on the same page instead of on two pages.

That SLUB cannot do. And I do not believe you. SLOB must have some way to distinguish the objects and their sizes since kfree does not include size information. You can mix slabs of different size on the same page without metadata. Magic?

Quoted 4 lines

So how does kfree then know how to free the object? There must be some way where you get the metainformation. What is the point of your 8 byte metadata that keeps getting inserted? That does not consume memory on a page?

I've already explained this to you once tonight and there's only 8k of code to read. It's also explained in the comment at the top:

* SLAB is emulated on top of SLOB by simply calling constructors and
* destructors for every SLAB allocation. Objects are returned with
* the 8-byte alignment unless the SLAB_HWCACHE_ALIGN flag is
* set, in which case the low-level allocator will fragment blocks to
* create the proper alignment. Again, objects of page-size or greater
* are allocated by calling __get_free_pages. As SLAB objects know
* their size, no separate size bookkeeping is necessary and there is
* essentially no allocation space overhead.

For the kmalloc case, we do have an 8-byte header, which works out to be about 1/8th of the slop that mainline kmalloc over SLAB has on average due to power of two cache sizes. So in both cases, less overhead than SLAB and different-sized objects can be comingled. SLUB would be awfully hard-pressed to have lower space overhead.

Compare:

void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags) {
...

                b = slob_alloc(c->size, flags, c->align);

...
}

void kmem_cache_free(struct kmem_cache *c, void *b) {
...

                slob_free(b, c->size);

...
}

vs.

void *__kmalloc(size_t size, gfp_t gfp)
{
...

                m = slob_alloc(size + SLOB_UNIT, gfp, 0);
                return m ? (void *)(m + 1) : 0;

...
}

void kfree(const void *block)
{
...

        slob_free((slob_t *)block - 1, 0);

...
}

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#29 lore raw
Quoted 6 lines · Matt Mackall
Quoted 3 lines
Quoted 1 line

Yes. It can in fact put 512 8-byte objects in a 4k page. More

So can SLUB.

Not without at least a bit per-object of overhead. So you can either fit 512 objects in 4160 bytes or 504 objects in 4k.

Slub uses a linked list pointer in the page struct which is NULL if all objects are allocated. There is no bit per object overhead.

Quoted 2 lines

For the kmalloc case, we do have an 8-byte header, which works out to be about 1/8th of the slop that mainline kmalloc over SLAB has on

Exactly. That overhead does not exist in SLUB. Thus SLOB is less efficient than SLUB.

Quoted 3 lines

average due to power of two cache sizes. So in both cases, less overhead than SLAB and different-sized objects can be comingled. SLUB would be awfully hard-pressed to have lower space overhead.

Its simple and easy to do and it was done in SLUB.

#30 lore raw
Quoted 11 lines · Christoph Lameter
Quoted 6 lines · Matt Mackall
Quoted 3 lines
Quoted 1 line

Yes. It can in fact put 512 8-byte objects in a 4k page. More

So can SLUB.

Not without at least a bit per-object of overhead. So you can either fit 512 objects in 4160 bytes or 504 objects in 4k.

Quoted 8 lines

Slub uses a linked list pointer in the page struct which is NULL if all objects are allocated. There is no bit per object overhead.

Quoted 2 lines

For the kmalloc case, we do have an 8-byte header, which works out to be about 1/8th of the slop that mainline kmalloc over SLAB has on

Exactly. That overhead does not exist in SLUB. Thus SLOB is less efficient than SLUB.

What you trade for that is that one page page can only serve one slab. For small systems, I would not be surprised if that was less space efficient, even just looking at kmalloc caches in isolation. Or do you have numbers to support your conclusion?

Signature · 1 line
SUSE Labs, Novell Inc.
#31 lore raw
Quoted 4 lines · Nick Piggin
Quoted 2 lines

Exactly. That overhead does not exist in SLUB. Thus SLOB is less efficient than SLUB.

What you trade for that is that one page page can only serve one slab.

Right.

Quoted 3 lines

For small systems, I would not be surprised if that was less space efficient, even just looking at kmalloc caches in isolation. Or do you have numbers to support your conclusion?

No I do not have any number beyond the efficiency calculations based on whole slabs. We would have to do some experiments to figure out how much space is actually wasted through partial slabs.

If you just do straight allocation on a UP system then there is at maximum one partial slab per slabcache with SLUB.

The situation becomes different with allocation and frees. Then we may have lots of partial slabs that we allocate from. But the SLOB approach also will have holes to manage. So I do not see how this could be a benefit unless you only have a few precious pages and you need to put multiple object sizes into it. A 4M system still has 1000 pages.

#32 lore raw
Quoted 7 lines · Christoph Lameter
Quoted 3 lines · Nick Piggin

For small systems, I would not be surprised if that was less space efficient, even just looking at kmalloc caches in isolation. Or do you have numbers to support your conclusion?

Quoted 5 lines

No I do not have any number beyond the efficiency calculations based on whole slabs. We would have to do some experiments to figure out how much space is actually wasted through partial slabs.

If you just do straight allocation on a UP system then there is at maximum one partial slab per slabcache with SLUB.

The situation becomes different with allocation and frees. Then we may have lots of partial slabs that we allocate from.

Yeah, but even then I think the SLUB approach is a very nice one for a general purpose system. Don't get me wrong, SLOB definitely is not good for that :)

Quoted 1 line

But the SLOB approach also will have holes to manage. So I do not see how this could be a benefit unless you only have a few precious pages and you need to put multiple object sizes into it. A 4M system still has 1000 pages.

Right, and it takes a long long time to do anything on my 4G system ;)

But that 4MB system might not even have 50 pages that you'd want to use for slab.

Signature · 1 line
SUSE Labs, Novell Inc.
#33 lore raw
Quoted 2 lines · Nick Piggin

But that 4MB system might not even have 50 pages that you'd want to use for slab.

The problem here is that you trade off more objects (SLUB) against more flexibility (SLOB). We need some experiments with 4M systems to see how this works out. It may be better to be able to allocate more objects. I estimate that we will have a need for about 30 active slabs (note the low number comes about because SLUB will merge similar slabs together into one) on such a system. Most of those can have two pages. So you will likely still be better off with SLUB than SLOB.

#34 lore raw
In reply to Christoph Lameter
Quoted 9 lines · Christoph Lameter
Quoted 4 lines · Nick Piggin
Quoted 2 lines

Exactly. That overhead does not exist in SLUB. Thus SLOB is less efficient than SLUB.

What you trade for that is that one page page can only serve one slab.

Right.

Quoted 7 lines
Quoted 3 lines

For small systems, I would not be surprised if that was less space efficient, even just looking at kmalloc caches in isolation. Or do you have numbers to support your conclusion?

No I do not have any number beyond the efficiency calculations based on whole slabs. We would have to do some experiments to figure out how much space is actually wasted through partial slabs.

The expectation would be (PAGE_SIZE + (PAGE_SIZE % size))/2 on average per cache.

Quoted 5 lines

The situation becomes different with allocation and frees. Then we may have lots of partial slabs that we allocate from. But the SLOB approach also will have holes to manage. So I do not see how this could be a benefit unless you only have a few precious pages and you need to put multiple object sizes into it. A 4M system still has 1000 pages.

A 4M system has approximately zero pages free once you've actually got stuff running in userspace. The marginal utility of each page is very high.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#35 lore raw
In reply to Christoph Lameter
Quoted 11 lines · Christoph Lameter
Quoted 6 lines · Matt Mackall
Quoted 3 lines
Quoted 1 line

Yes. It can in fact put 512 8-byte objects in a 4k page. More

So can SLUB.

Not without at least a bit per-object of overhead. So you can either fit 512 objects in 4160 bytes or 504 objects in 4k.

Slub uses a linked list pointer in the page struct which is NULL if all objects are allocated. There is no bit per object overhead.

Ahh, I'd forgotten about that feature.

Quoted 5 lines
Quoted 2 lines

For the kmalloc case, we do have an 8-byte header, which works out to be about 1/8th of the slop that mainline kmalloc over SLAB has on

Exactly. That overhead does not exist in SLUB. Thus SLOB is less efficient than SLUB.

What size object does kmalloc(80) return? In SLAB, the answer is 128 bytes with 48 bytes of slack space. In SLOB, the answer is 88 for 8 bytes of slack space. Looks like SLUB is in the same camp as SLAB here:

+/*
+ * We keep the general caches in an array of slab caches that are used for
+ * 2^x bytes of allocations.
+ */
+extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
...
+ if (size <= 128) return 7;

As I pointed out in our private thread, according to these measurements:

http://lwn.net/Articles/124374/

total bytes allocated: 47118848   
slack bytes allocated:  8717262
number of allocs:        132796

...the average kmalloc allocation with SLAB is 355 bytes with an average slack of 66 bytes. As SLUB uses the same kmalloc cache size strategy, I expect the same there.

SLOB's kmalloc overhead is 8 bytes, always. That's 1/8th the average SLAB kmalloc overhead.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#36 lore raw
Quoted 7 lines · Matt Mackall
Quoted 2 lines

Exactly. That overhead does not exist in SLUB. Thus SLOB is less efficient than SLUB.

What size object does kmalloc(80) return? In SLAB, the answer is 128 bytes with 48 bytes of slack space. In SLOB, the answer is 88 for 8 bytes of slack space. Looks like SLUB is in the same camp as SLAB here:

There is a 96 sized general slab. So it would go up to that size. But you can create a 80 byte slab of course. And that may cost minimal overhead since 80 byte slabs may be merged. If one already exist then you get it for free.

Review

Quoted 7 lines
(quoted diff) +6 -0
+/*
+ * We keep the general caches in an array of slab caches that are used for
+ * 2^x bytes of allocations.
+ */
+extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
..
+	if (size <=        128) return 7;

96 please. You skipped the first part.

Quoted 2 lines

SLOB's kmalloc overhead is 8 bytes, always. That's 1/8th the average SLAB kmalloc overhead.

SLUB can generate an 80 byte slab with minimal overhead if you wanted. But yes I agree the flexbility there is an advantage if you have objects of various sizes.