Mailing List Archive

PATCH killing dead code and design errors in pre6
This is a multi-part message in MIME format.
--------------E21141A3ED9088585281D8D9
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hello Everybody!
The following simple patch is a correction of a design error
in the slab implementation.
Several YEARS ago it got introduced into the general linux kernel.
It is providing a mechanism of constructors and destructors for the
objects allocaed and deallocated. However still after YEARS I found
actually only one place in the kernel where it was used!
READ TWICE: Only one.
And there only the constructor was present and even the usage of it
was bogous at least. (Please see the corresponding comment in the
patch.)
READ TWICE: bogous.
There where good reaons why nobody hessitated to use this crap.
1. In linux all the major objects of special purpose nature are using
thin wrapper founctions for allocation and deallocation around the
generic allocator functions. This is accomplishing the very benefits
promised by the generic stuff without actually penalizing the general
case with care about checks for the existence of
constructors/destructors
atomic non atomic out of order calls any many many other checks.
2. The comment I have added to the place where the constructor mechanism
was previously used explains why it was bogous there. And it's quite
easy to introduce errors of the same kind by the usage of them in other
places. (If anybody had dared to actually use them!)
So my conclusion is there was once again somone blindly following
bad designs (however prominent doesn't matter for me.). And yes the
explanation above is a strong evidence that the Bonwick paper is
containing many many other lies too. (In esp. the whole colouring thing
seems to be a good joke resulting in optimizations only visibly in the
laboratory.)
So Linus please apply this straight forward patch before the next
release.
You told you where loving removing dead code :-). And this
patch doesn't change anything at all. It's just deleting and giving
at least me 16443 bytes of precious memmory back (OK __init not taked
into account).
It's stable the diff was produced under a kernel compiled with it.
And this mail will be send by it too. In the meantime the CD-ROM
drive of the very same mashine is plaing the "Sunday" album from
Faithless oh and X11 is running really:-).
BTW> The whole slab.c seems to be an enormous mess after second look....
The style it was done seems to come from the Lord of Coding himself.
Sombody was trying to accompilsh the Ultimate Truth with it. Of course
without thinking about esthetics, size, and actual usfullness of the
many
dead features it is providing. In whole it gives me the impression
that the epoche of Baroq is still not quite that long ago past ;-)
Marcin
PS. Yes I preffer a Techno allocator over one from Mozart.
--------------E21141A3ED9088585281D8D9
Content-Type: text/plain; charset=us-ascii;
name="diff-pre6"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="diff-pre6"
diff -urN linux-orig/fs/buffer.c linux/fs/buffer.c
--- linux-orig/fs/buffer.c Mon Jan 11 00:52:30 1999
+++ linux/fs/buffer.c Tue Jan 12 20:58:31 1999
@@ -1553,8 +1553,7 @@

bh_cachep = kmem_cache_create("buffer_head",
sizeof(struct buffer_head),
- 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!bh_cachep)
panic("Cannot create buffer head SLAB cache\n");
/*
diff -urN linux-orig/fs/dcache.c linux/fs/dcache.c
--- linux-orig/fs/dcache.c Mon Jan 11 00:52:30 1999
+++ linux/fs/dcache.c Tue Jan 12 21:00:02 1999
@@ -911,19 +911,14 @@
int i;
struct list_head *d = dentry_hashtable;

- /*
- * A constructor could be added for stable state like the lists,
- * but it is probably not worth it because of the cache nature
- * of the dcache.
+ /*
* If fragmentation is too bad then the SLAB_HWCACHE_ALIGN
* flag could be removed here, to hint to the allocator that
- * it should not try to get multiple page regions.
+ * it should not try to get multiple page regions.
*/
- dentry_cache = kmem_cache_create("dentry_cache",
+ dentry_cache = kmem_cache_create("dentry",
sizeof(struct dentry),
- 0,
- SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if (!dentry_cache)
panic("Cannot create dentry cache");

diff -urN linux-orig/fs/dquot.c linux/fs/dquot.c
--- linux-orig/fs/dquot.c Tue Dec 29 20:07:37 1998
+++ linux/fs/dquot.c Tue Jan 12 23:32:26 1999
@@ -1163,17 +1163,20 @@

void __init dquot_init_hash(void)
{
- printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
-
+ /* This is the very second only place where we don't align upon
+ * cache line boundary. The +4 looks very suspicious to me...
+ */
dquot_cachep = kmem_cache_create("dquot", sizeof(struct dquot),
sizeof(unsigned long) * 4,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ SLAB_HWCACHE_ALIGN);

if (!dquot_cachep)
panic("Cannot create dquot SLAB cache\n");

memset(dquot_hash, 0, sizeof(dquot_hash));
memset((caddr_t)&dqstats, 0, sizeof(dqstats));
+
+ printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
}

/*
diff -urN linux-orig/fs/file_table.c linux/fs/file_table.c
--- linux-orig/fs/file_table.c Tue Dec 29 20:10:48 1998
+++ linux/fs/file_table.c Tue Jan 12 20:57:11 1999
@@ -52,8 +52,7 @@
void __init file_table_init(void)
{
filp_cache = kmem_cache_create("filp", sizeof(struct file),
- 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!filp_cache)
panic("VFS: Cannot alloc filp SLAB cache.");
/*
diff -urN linux-orig/include/linux/slab.h linux/include/linux/slab.h
--- linux-orig/include/linux/slab.h Mon Jan 11 01:04:59 1999
+++ linux/include/linux/slab.h Tue Jan 12 21:07:36 1999
@@ -39,18 +39,11 @@
#define SLAB_HIGH_PACK 0x00004000UL /* XXX */
#endif

-/* flags passed to a constructor func */
-#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */
-#define SLAB_CTOR_ATOMIC 0x002UL /* tell constructor it can't sleep */
-#define SLAB_CTOR_VERIFY 0x004UL /* tell constructor it's a verify call */
-
/* prototypes */
extern long kmem_cache_init(long, long);
extern void kmem_cache_sizes_init(void);
extern kmem_cache_t *kmem_find_general_cachep(size_t);
-extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
- void (*)(void *, kmem_cache_t *, unsigned long),
- void (*)(void *, kmem_cache_t *, unsigned long));
+extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long);
extern int kmem_cache_shrink(kmem_cache_t *);
extern void *kmem_cache_alloc(kmem_cache_t *, int);
extern void kmem_cache_free(kmem_cache_t *, void *);
@@ -60,6 +53,8 @@
extern void kfree_s(const void *, size_t);

extern void kmem_cache_reap(int);
+
+/* interface to the /proc fs */
extern int get_slabinfo(char *);

/* System wide caches */
diff -urN linux-orig/kernel/fork.c linux/kernel/fork.c
--- linux-orig/kernel/fork.c Mon Jan 11 00:52:33 1999
+++ linux/kernel/fork.c Tue Jan 12 20:41:21 1999
@@ -124,8 +124,7 @@
int i;

uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct),
- 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!uid_cachep)
panic("Cannot create uid taskcount SLAB cache\n");

@@ -632,11 +631,9 @@

void __init filescache_init(void)
{
- files_cachep = kmem_cache_create("files_cache",
+ files_cachep = kmem_cache_create("files",
sizeof(struct files_struct),
- 0,
- SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if (!files_cachep)
panic("Cannot create files cache");
}
diff -urN linux-orig/kernel/signal.c linux/kernel/signal.c
--- linux-orig/kernel/signal.c Tue Dec 29 20:10:31 1998
+++ linux/kernel/signal.c Tue Jan 12 23:35:42 1999
@@ -20,12 +20,6 @@

#define DEBUG_SIG 0

-#if DEBUG_SIG
-#define SIG_SLAB_DEBUG (SLAB_DEBUG_FREE | SLAB_RED_ZONE /* | SLAB_POISON */)
-#else
-#define SIG_SLAB_DEBUG 0
-#endif
-
static kmem_cache_t *signal_queue_cachep;

int nr_queued_signals;
@@ -33,11 +27,25 @@

void __init signals_init(void)
{
+
+ /*
+ * 12/01/1999 Marcin Dalecki <dalecki@cs.net.pl>:
+ *
+ * The alignment parameters passed to kmem_cache_create passed here
+ * look *very* suspicious to me. Anybody else is just using
+ * (...,...,0,SLAB_HWCACHE_ALIGN). Maybe if we could use it here to,
+ * we would have a small penalty here, but the simplifications possible
+ * in the whole slab mechanism which this would just benefit everything
+ * else much more significantly.
+ *
+ * Richard would it be OK?
+ */
+
signal_queue_cachep =
kmem_cache_create("signal_queue",
sizeof(struct signal_queue),
__alignof__(struct signal_queue),
- SIG_SLAB_DEBUG, NULL, NULL);
+ 0);
}


diff -urN linux-orig/mm/mmap.c linux/mm/mmap.c
--- linux-orig/mm/mmap.c Tue Dec 29 20:09:49 1998
+++ linux/mm/mmap.c Tue Jan 12 20:43:29 1999
@@ -708,15 +708,13 @@
{
vm_area_cachep = kmem_cache_create("vm_area_struct",
sizeof(struct vm_area_struct),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!vm_area_cachep)
panic("vma_init: Cannot alloc vm_area_struct cache.");

mm_cachep = kmem_cache_create("mm_struct",
sizeof(struct mm_struct),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!mm_cachep)
panic("vma_init: Cannot alloc mm_struct cache.");
}
diff -urN linux-orig/mm/slab.c linux/mm/slab.c
--- linux-orig/mm/slab.c Tue Dec 29 20:09:49 1998
+++ linux/mm/slab.c Tue Jan 12 23:03:08 1999
@@ -116,7 +116,7 @@
* 0 if you wish to reduce memory usage.
*
* SLAB_DEBUG_SUPPORT - 1 for kmem_cache_create() to honour; SLAB_DEBUG_FREE,
- * SLAB_DEBUG_INITIAL, SLAB_RED_ZONE & SLAB_POISON.
+ * SLAB_RED_ZONE & SLAB_POISON.
* 0 for faster, smaller, code (especially in the critical paths).
*
* SLAB_STATS - 1 to collect stats for /proc/slabinfo.
@@ -135,11 +135,11 @@
/* Legal flag mask for kmem_cache_create(). */
#if SLAB_DEBUG_SUPPORT
#if 0
-#define SLAB_C_MASK (SLAB_DEBUG_FREE|SLAB_DEBUG_INITIAL|SLAB_RED_ZONE| \
+#define SLAB_C_MASK (SLAB_DEBUG_FREE|SLAB_RED_ZONE| \
SLAB_POISON|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP| \
SLAB_HIGH_PACK)
#endif
-#define SLAB_C_MASK (SLAB_DEBUG_FREE|SLAB_DEBUG_INITIAL|SLAB_RED_ZONE| \
+#define SLAB_C_MASK (SLAB_DEBUG_FREE|SLAB_RED_ZONE| \
SLAB_POISON|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP)
#else
#if 0
@@ -233,8 +233,6 @@
unsigned long c_dflags; /* dynamic flags */
size_t c_org_size;
unsigned long c_gfporder; /* order of pgs per slab (2^n) */
- void (*c_ctor)(void *, kmem_cache_t *, unsigned long); /* constructor func */
- void (*c_dtor)(void *, kmem_cache_t *, unsigned long); /* de-constructor func */
unsigned long c_align; /* alignment of objs */
size_t c_colour; /* cache colouring range */
size_t c_colour_next;/* cache colouring */
@@ -377,7 +375,7 @@
/* growing */ 0,
/* dflags */ 0,
/* org_size, gfp */ 0, 0,
-/* ctor, dtor, align */ NULL, NULL, L1_CACHE_BYTES,
+/* align */ L1_CACHE_BYTES,
/* colour, colour_next */ 0, 0,
/* failures */ 0,
/* name */ "kmem_cache",
@@ -459,7 +457,7 @@
unsigned int found = 0;

cache_slabp = kmem_cache_create("slab_cache", sizeof(kmem_slab_t),
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if (cache_slabp) {
char **names = cache_sizes_name;
cache_sizes_t *sizes = cache_sizes;
@@ -471,7 +469,7 @@
* allow tighter packing of the smaller caches. */
if (!(sizes->cs_cachep =
kmem_cache_create(*names++, sizes->cs_size,
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL)))
+ 0, SLAB_HWCACHE_ALIGN)))
goto panic_time;
if (!found) {
/* Inc off-slab bufctl limit until the ceiling is hit. */
@@ -603,46 +601,6 @@
static void
kmem_slab_destroy(kmem_cache_t *cachep, kmem_slab_t *slabp)
{
- if (cachep->c_dtor
-#if SLAB_DEBUG_SUPPORT
- || cachep->c_flags & (SLAB_POISON | SLAB_RED_ZONE)
-#endif /*SLAB_DEBUG_SUPPORT*/
- ) {
- /* Doesn't use the bufctl ptrs to find objs. */
- unsigned long num = cachep->c_num;
- void *objp = slabp->s_mem;
- do {
-#if SLAB_DEBUG_SUPPORT
- if (cachep->c_flags & SLAB_RED_ZONE) {
- if (*((unsigned long*)(objp)) != SLAB_RED_MAGIC1)
- printk(KERN_ERR "kmem_slab_destroy: "
- "Bad front redzone - %s\n",
- cachep->c_name);
- objp += BYTES_PER_WORD;
- if (*((unsigned long*)(objp+cachep->c_org_size)) !=
- SLAB_RED_MAGIC1)
- printk(KERN_ERR "kmem_slab_destroy: "
- "Bad rear redzone - %s\n",
- cachep->c_name);
- }
- if (cachep->c_dtor)
-#endif /*SLAB_DEBUG_SUPPORT*/
- (cachep->c_dtor)(objp, cachep, 0);
-#if SLAB_DEBUG_SUPPORT
- else if (cachep->c_flags & SLAB_POISON) {
- if (kmem_check_poison_obj(cachep, objp))
- printk(KERN_ERR "kmem_slab_destroy: "
- "Bad poison - %s\n", cachep->c_name);
- }
- if (cachep->c_flags & SLAB_RED_ZONE)
- objp -= BYTES_PER_WORD;
-#endif /* SLAB_DEBUG_SUPPORT */
- objp += cachep->c_offset;
- if (!slabp->s_index)
- objp += sizeof(kmem_bufctl_t);
- } while (--num);
- }
-
slabp->s_magic = SLAB_MAGIC_DESTROYED;
if (slabp->s_index)
kmem_cache_free(cachep->c_index_cachep, slabp->s_index);
@@ -676,9 +634,8 @@
* NOTE: The 'name' is assumed to be memory that is _not_ going to disappear.
*/
kmem_cache_t *
-kmem_cache_create(const char *name, size_t size, size_t offset,
- unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long),
- void (*dtor)(void*, kmem_cache_t *, unsigned long))
+kmem_cache_create(const char *name, size_t size,
+ size_t offset, unsigned long flags)
{
const char *func_nm= KERN_ERR "kmem_create: ";
kmem_cache_t *searchp;
@@ -708,41 +665,11 @@
goto opps;
}

- if (dtor && !ctor) {
- /* Decon, but no con - doesn't make sense */
- printk("%sDecon but no con - %s\n", func_nm, name);
- goto opps;
- }
-
if (offset < 0 || offset > size) {
printk("%sOffset weird %d - %s\n", func_nm, (int) offset, name);
offset = 0;
}

-#if SLAB_DEBUG_SUPPORT
- if ((flags & SLAB_DEBUG_INITIAL) && !ctor) {
- /* No constructor, but inital state check requested */
- printk("%sNo con, but init state check requested - %s\n", func_nm, name);
- flags &= ~SLAB_DEBUG_INITIAL;
- }
-
- if ((flags & SLAB_POISON) && ctor) {
- /* request for poisoning, but we can't do that with a constructor */
- printk("%sPoisoning requested, but con given - %s\n", func_nm, name);
- flags &= ~SLAB_POISON;
- }
-#if 0
- if ((flags & SLAB_HIGH_PACK) && ctor) {
- printk("%sHigh pack requested, but con given - %s\n", func_nm, name);
- flags &= ~SLAB_HIGH_PACK;
- }
- if ((flags & SLAB_HIGH_PACK) && (flags & (SLAB_POISON|SLAB_RED_ZONE))) {
- printk("%sHigh pack requested, but with poisoning/red-zoning - %s\n",
- func_nm, name);
- flags &= ~SLAB_HIGH_PACK;
- }
-#endif
-#endif /* SLAB_DEBUG_SUPPORT */
#endif /* SLAB_MGMT_CHECKS */

/* Always checks flags, a caller might be expecting debug
@@ -951,8 +878,6 @@
cachep->c_firstp = kmem_slab_end(cachep);
cachep->c_lastp = kmem_slab_end(cachep);
cachep->c_flags = flags;
- cachep->c_ctor = ctor;
- cachep->c_dtor = dtor;
cachep->c_magic = SLAB_C_MAGIC;
cachep->c_name = name; /* Simply point to the name. */
spin_lock_init(&cachep->c_spinlock);
@@ -1072,8 +997,7 @@
}

static inline void
-kmem_cache_init_objs(kmem_cache_t * cachep, kmem_slab_t * slabp, void *objp,
- unsigned long ctor_flags)
+kmem_cache_init_objs(kmem_cache_t * cachep, kmem_slab_t * slabp, void *objp)
{
kmem_bufctl_t **bufpp = &slabp->s_freep;
unsigned long num = cachep->c_num-1;
@@ -1087,12 +1011,6 @@
}
#endif /* SLAB_DEBUG_SUPPORT */

- /* Constructors are not allowed to allocate memory from the same cache
- * which they are a constructor for. Otherwise, deadlock.
- * They must also be threaded.
- */
- if (cachep->c_ctor)
- cachep->c_ctor(objp, cachep, ctor_flags);
#if SLAB_DEBUG_SUPPORT
else if (cachep->c_flags & SLAB_POISON) {
/* need to poison the objs */
@@ -1139,7 +1057,6 @@
void *objp;
size_t offset;
unsigned int dma, local_flags;
- unsigned long ctor_flags;
unsigned long save_flags;

/* Be lazy and only check for valid flags here,
@@ -1165,14 +1082,7 @@
flags &= ~SLAB_LEVEL_MASK;
flags |= SLAB_ATOMIC;
}
- ctor_flags = SLAB_CTOR_CONSTRUCTOR;
local_flags = (flags & SLAB_LEVEL_MASK);
- if (local_flags == SLAB_ATOMIC) {
- /* Not allowed to sleep. Need to tell a constructor about
- * this - it might need to know...
- */
- ctor_flags |= SLAB_CTOR_ATOMIC;
- }

/* About to mess with non-constant members - lock. */
spin_lock_irqsave(&cachep->c_spinlock, save_flags);
@@ -1228,7 +1138,7 @@
* an obj and its related bufctl. For off-slab bufctls, c_offset is
* the distance between objs in the slab.
*/
- kmem_cache_init_objs(cachep, slabp, objp, ctor_flags);
+ kmem_cache_init_objs(cachep, slabp, objp);

spin_lock_irq(&cachep->c_spinlock);

@@ -1539,10 +1449,6 @@
return;
#if SLAB_DEBUG_SUPPORT
init_state_check:
- /* Need to call the slab's constructor so the
- * caller can perform a verify of its state (debugging).
- */
- cachep->c_ctor(objp, cachep, SLAB_CTOR_CONSTRUCTOR|SLAB_CTOR_VERIFY);
goto finished_initial;
extra_checks:
if (!kmem_extra_free_checks(cachep, slabp->s_freep, bufp, objp)) {
@@ -1842,7 +1748,7 @@
kmem_cache_t *test_cachep;

printk(KERN_INFO "kmem_test() - start\n");
- test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISON, NULL, NULL);
+ test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISON);
if (test_cachep) {
char *objp = kmem_cache_alloc(test_cachep, SLAB_KERNEL);
if (objp) {
diff -urN linux-orig/net/core/skbuff.c linux/net/core/skbuff.c
--- linux-orig/net/core/skbuff.c Tue Sep 15 07:52:10 1998
+++ linux/net/core/skbuff.c Tue Jan 12 21:03:54 1999
@@ -107,13 +107,35 @@
#ifdef CONFIG_INET
printk("IP fragment buffer size : %u\n",
atomic_read(&ip_frag_mem));
-#endif
+#endif
+}
+
+/*
+ * Slab constructor for a skb head.
+ */
+static inline void skb_headerinit(struct sk_buff *skb)
+{
+ skb->destructor = NULL;
+ skb->pkt_type = PACKET_HOST; /* Default type */
+ skb->pkt_bridged = 0; /* Not bridged */
+ skb->prev = skb->next = NULL;
+ skb->list = NULL;
+ skb->sk = NULL;
+ skb->stamp.tv_sec=0; /* No idea about time */
+ skb->ip_summed = 0;
+ skb->security = 0; /* By default packets are insecure */
+ skb->dst = NULL;
+#ifdef CONFIG_IP_FIREWALL
+ skb->fwmark = 0;
+#endif
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->priority = 0;
}

-/* Allocate a new skbuff. We do this ourselves so we can fill in a few
+/* Allocate a new skbuff. We do this ourselves so we can fill in a few
* 'private' fields and also do memory statistics to find all the
* [BEEP] leaks.
- *
+ *
*/

struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
@@ -134,6 +156,7 @@
skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
if (skb == NULL)
goto nohead;
+ skb_headerinit(skb);

/* Get the DATA. Size must match skb_add_mtu(). */
size = ((size + 15) & ~15);
@@ -174,30 +197,6 @@
}


-/*
- * Slab constructor for a skb head.
- */
-static inline void skb_headerinit(void *p, kmem_cache_t *cache,
- unsigned long flags)
-{
- struct sk_buff *skb = p;
-
- skb->destructor = NULL;
- skb->pkt_type = PACKET_HOST; /* Default type */
- skb->pkt_bridged = 0; /* Not bridged */
- skb->prev = skb->next = NULL;
- skb->list = NULL;
- skb->sk = NULL;
- skb->stamp.tv_sec=0; /* No idea about time */
- skb->ip_summed = 0;
- skb->security = 0; /* By default packets are insecure */
- skb->dst = NULL;
-#ifdef CONFIG_IP_FIREWALL
- skb->fwmark = 0;
-#endif
- memset(skb->cb, 0, sizeof(skb->cb));
- skb->priority = 0;
-}

/*
* Free an skbuff by memory without cleaning the state.
@@ -224,7 +223,7 @@
dst_release(skb->dst);
if(skb->destructor)
skb->destructor(skb);
- skb_headerinit(skb, NULL, 0); /* clean state */
+ skb_headerinit(skb); /* clean state */
kfree_skbmem(skb);
}

@@ -235,15 +234,35 @@
struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
{
struct sk_buff *n;
-
+
+ /*
+ * 12/01/1999 Marcin Dalecki <dalecki@cs.net.pl>
+ *
+ * The following code actually reveals, why nobody was using the
+ * constructor destructor mechanism previously provided by the slab
+ * allocator. Here the kmem_cache_alloc was calling the skb_headerinit
+ * function indirectly to just reset the results of it by copying over
+ * the values from the cloned skb.
+ *
+ * In Linux we are generally using thinny wrappers around the special
+ * purpose allocation functions, we do the initialization/cleaning on
+ * demand for all the different kinds of objects present across the
+ * kernel. This is providing the same level of efficiency without the
+ * penalties of additional complexity and obfuscation, provided by the
+ * previously present general constructor/destructor mechanis of the
+ * slab.
+ *
+ * It was a DESIGN ERROR in respect of the rest of the kernel.
+ */
+
n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
if (!n)
return NULL;
-
memcpy(n, skb, sizeof(*n));
+
atomic_inc(skb_datarefp(skb));
skb->cloned = 1;
-
+
atomic_inc(&net_allocs);
atomic_inc(&net_skbcount);
dst_clone(n->dst);
@@ -369,11 +388,9 @@

void __init skb_init(void)
{
- skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
+ skbuff_head_cache = kmem_cache_create("skbuff_head",
sizeof(struct sk_buff),
- 0,
- SLAB_HWCACHE_ALIGN,
- skb_headerinit, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if (!skbuff_head_cache)
panic("cannot create skbuff cache");
}
diff -urN linux-orig/net/core/sock.c linux/net/core/sock.c
--- linux-orig/net/core/sock.c Tue Dec 29 20:09:04 1998
+++ linux/net/core/sock.c Tue Jan 12 21:03:11 1999
@@ -287,8 +287,8 @@
case SO_PASSCRED:
sock->passcred = valbool;
break;
-
-
+
+
#ifdef CONFIG_NETDEVICES
case SO_BINDTODEVICE:
{
@@ -509,8 +509,8 @@

void __init sk_init(void)
{
- sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,
- SLAB_HWCACHE_ALIGN, 0, 0);
+ sk_cachep = kmem_cache_create("sock", sizeof(struct sock),
+ 0, SLAB_HWCACHE_ALIGN);

}

diff -urN linux-orig/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- linux-orig/net/ipv4/tcp.c Mon Jan 11 00:52:33 1999
+++ linux/net/ipv4/tcp.c Tue Jan 12 21:05:28 1999
@@ -1754,22 +1754,19 @@

tcp_openreq_cachep = kmem_cache_create("tcp_open_request",
sizeof(struct open_request),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!tcp_openreq_cachep)
panic("tcp_init: Cannot alloc open_request cache.");

tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
sizeof(struct tcp_bind_bucket),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!tcp_bucket_cachep)
panic("tcp_init: Cannot alloc tcp_bind_bucket cache.");

tcp_timewait_cachep = kmem_cache_create("tcp_tw_bucket",
sizeof(struct tcp_tw_bucket),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN);
if(!tcp_timewait_cachep)
panic("tcp_init: Cannot alloc tcp_tw_bucket cache.");
}
--------------E21141A3ED9088585281D8D9--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
In article <369BD8A7.AE499CB8@cs.net.pl>,
dalecki@cs.net.pl (Marcin Dalecki) writes:
> Hello Everybody!
> The following simple patch is a correction of a design error
> in the slab implementation.
> Several YEARS ago it got introduced into the general linux kernel.
> It is providing a mechanism of constructors and destructors for the
> objects allocaed and deallocated. However still after YEARS I found
> actually only one place in the kernel where it was used!
> READ TWICE: Only one.
A) It was actually used twice during 2.1, but it got later removed by other
changes.
B) Using pre initialized headers for skbuffs gives an about 20% forwarding
rate improvement for fast routing.
C) Read Bonwick's original paper before doing any changes to slab.c.
> And there only the constructor was present and even the usage of it
> was bogous at least. (Please see the corresponding comment in the
> patch.)
You did not understand the basic idea behind slab: it is an object cache
that is able to cached _initialized_ objects, because for some objects
it is more expensive to initialize them than to use them in the fast path.
Skbuffs are exactly such an example. Moving the constructor into the caller
does not work, because the caller doesn't know if the object was freshly
allocated from the page allocator, or was from an already initialized object
cache. In the later case it does not need to initialize at all!
Linus, please don't apply this bogus patch.
Thank you,
-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
On Wed, 13 Jan 1999, Marcin Dalecki wrote:
> Several YEARS ago it got introduced into the general linux kernel.
> It is providing a mechanism of constructors and destructors for the
> objects allocaed and deallocated. However still after YEARS I found
> actually only one place in the kernel where it was used!
this doesnt mean it should be removed ... later on it can make a
difference, we can call constructors in the idle thread(s). Lets better
keep the interface right, even if it's unused.
-- mingo
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
In article <369CC886.E9431AC9@cs.net.pl>,
Marcin Dalecki <dalecki@cs.net.pl> writes:
> If you had really readed through the patch you should see why the only
> usage
> of it in skbuff was bogous due to the fact that the results of the
> implyed
> constructor call (omitted due to reusal or not) gets just overwritten by
> the
> copy operation just shortly after it. Did you spot the memcpy(new_skb,
> orig_skb) ?
That is only in skb_clone, not in alloc_skb.
> This is an generic example of case where the logic behind the implyed
> constructors
> is just getting into way: CLONING OF OBJECTS.
You might not have noticed it, but most skbs are allocated, not cloned.
It is especially important for the fast routing path, which is totally
memory bound (when several 100Mbit/s busmastering ethernet cards are active
the CPU cache isn't of much use anymore because it is invalidated so often).
The improvements on forwarding performance was the main reason why the slab
skb patch was added.
Also: in the middle of 2.1 there was a nice fork time optimization (it got
unfortunately thrown out again by the half-finished changes for bigger NR_OPEN
support, but I plan to resubmit them for 2.3). With clever use of the constructor
it is possible to avoid the copying of the files array on forking for most cases.

-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
On Wed, 13 Jan 1999, Marcin Dalecki wrote:
> Or put it again into 2.3 or whatever. [...]
it breaks the interface. The SLAB allocator should not be faulted for
other code not using it's capabilities ... It's not something obsolete,
it's a future use ...
> [...] Even after my patch, there appears to be still *PLENTY* of room
> for other simplifications/optimizations in slab.c.
your patches are welcome! (Last i checked it had a near perfect jumpless
fast path.)
-- mingo
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
Andi Kleen wrote:

> C) Read Bonwick's original paper before doing any changes to slab.c.
I did. And I'm still thinking that it is lying at a lot of places about
the performance gains it is claiming.
>
> > And there only the constructor was present and even the usage of it
> > was bogous at least. (Please see the corresponding comment in the
> > patch.)
>
> You did not understand the basic idea behind slab: it is an object cache
Sure I did understand it. My passive english isn't that bad actually ;-)
However I see that due to the fact that where possible we have
already split all the reusable parts of all our major structs and the
changing
user parts into different structs, there isn't much of a need for a
mechanism
like this in linux currently. And this is the main reason nobody appears
to dare
to use it. This is what the whole free list for inode buffer headers,
the whole skb stuff and many many others, are for.
You didn't read through the patch...
Remember what you gain in skbuff is loosing on all other places.
> that is able to cached _initialized_ objects, because for some objects
> it is more expensive to initialize them than to use them in the fast path.
> Skbuffs are exactly such an example. Moving the constructor into the caller
> does not work, because the caller doesn't know if the object was freshly
> allocated from the page allocator, or was from an already initialized object
> cache. In the later case it does not need to initialize at all!
The initialization you are talking about is just only setting anything
to 0.
Just about 10 blah->boom=0. I just don't beleve that the improvement you
are
talking about. The cost of calling indirect the constructor function
pushig all the
four parameters of it and checking in all other allocation cases for the
presence
of a non present constructor IS greater by any means.
At least in the case I have spotted in skbuff there was CERTAINLY no
improvemnt at all present there.
If you had really readed through the patch you should see why the only
usage
of it in skbuff was bogous due to the fact that the results of the
implyed
constructor call (omitted due to reusal or not) gets just overwritten by
the
copy operation just shortly after it. Did you spot the memcpy(new_skb,
orig_skb) ?
This is an generic example of case where the logic behind the implyed
constructors
is just getting into way: CLONING OF OBJECTS.
So there was actually performance lost due to the implyed constructor
even in
the very single case where it was used!

> Linus, please don't apply this bogus patch.
Nah ... it just isn't bogous...
It just happens that the desing of the kernel had been already aware
about
the reusability of objects just before the Bonwick paper!
At least the proper usage of constructors/destructors would be something
that would imply MAJOR redesign of MAJOR kernel parts before it could
benefit us anything. Or to be more precise the redesign would just give
some other implementation of something we are already fully aware of.
This is certainly something that will not happen before 2.2. So
therefore
the patch is still valid. However maybe in 10.x one could resurrect it
again.
But then please concurrently with actual consequent usage!
--Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
On Wed, 13 Jan 1999, MOLNAR Ingo wrote:
>
> On Wed, 13 Jan 1999, Marcin Dalecki wrote:
>
> > Or put it again into 2.3 or whatever. [...]
>
> it breaks the interface. The SLAB allocator should not be faulted for
> other code not using it's capabilities ... It's not something obsolete,
> it's a future use ...
The slab code _should_ be faulted for being ugly as hell, and much too
complex for it's uses. I've wanted to remove it several times completely,
going back to the older kmalloc(). I appreciate people looking into
removing features that are hardly ever used and of dubious value.
I bet that 100% of the benefit of slab could be gotten with a really small
skb "cache" in front of a much simpler kmalloc() (where the skb cache
would be a few entries worth of pre-initialized skb's). Or alternatively
just keep sab, but separate the notion of allocation and caching - so that
the 99% that are _not_ interested in constructors would never have to go
through any parts that know about them.
Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
MOLNAR Ingo wrote:
>
> On Wed, 13 Jan 1999, Marcin Dalecki wrote:
>
> > Several YEARS ago it got introduced into the general linux kernel.
> > It is providing a mechanism of constructors and destructors for the
> > objects allocaed and deallocated. However still after YEARS I found
> > actually only one place in the kernel where it was used!
>
> this doesnt mean it should be removed ... later on it can make a
> difference, we can call constructors in the idle thread(s). Lets better
> keep the interface right, even if it's unused.
Or put it again into 2.3 or whatever. I still don't like to have dead
code,
however wonderfull, around. And in esp. I don't like it in something as
vital
as the allocator. Even after my patch, there appears to be still
*PLENTY*
of room for other simplifications/optimizations in slab.c.
And just please put it in, only if it get's real usage, wich would
actually
proove that this is something desirable. Academic exercises aren't
very usefull for the sake fo theyr own. However the past two years show
that
this isn't soemthing going to happen any time soon.
BTW. Please take a look at the many free_list buffer_header mechanisms
in the kernel which are giving a hint on how the kernel already quite
perfectly
avoids unnecessary reinitializations on object reusal.
--Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
On Wed, 13 Jan 1999, Linus Torvalds wrote:
> The slab code _should_ be faulted for being ugly as hell, and much too
> complex for it's uses. I've wanted to remove it several times completely,
> going back to the older kmalloc(). I appreciate people looking into
> removing features that are hardly ever used and of dubious value.
i have only looked at the patch of Marcin. It removed a i think useful
interface component from kmem_cache_create/destroy. Those two functions
are called a few times per boot. Unless i'm missing something in the slab
code, the existance of ctor/dtor does not affect typical
allocation/deallocation at all, they are only invoked when the cache grows
or shrinks.
i agree that slab.c is not readable. But i think the main reason is the
debugging, sanity-check and statistics code, which should be removed
before 2.2, it should be maintained in IKD-patch. (there is a generic
trend of moving debugging patches [kernel debugger, tracing, deadlock
detection, allocation leak detection, etc.] into IKD, this way we do not
hinder the main kernel with unnecessary complexity)
but removing ctor/dtor is i think a mistake, although i agree that it's
inactive code currently.
> I bet that 100% of the benefit of slab could be gotten with a really small
> skb "cache" in front of a much simpler kmalloc() (where the skb cache
> would be a few entries worth of pre-initialized skb's). Or alternatively
> just keep sab, but separate the notion of allocation and caching - so that
> the 99% that are _not_ interested in constructors would never have to go
> through any parts that know about them.
the SLAB also keeps caches separated, which (to me) feels better than what
kmalloc could give us anytime. I was always worried about the multipage
allocations done by the SLAB, but this fragmentation issue seems to be a
red herring after all.
the ctor code could be used for some things all around the place. Things
like bh's could be preinitialized:
if((bh = kmem_cache_alloc(bh_cachep, SLAB_ATOMIC)) != NULL) {
memset(bh, 0, sizeof(*bh));
we'd preinitialize bh's to eg. bh->state = B_FREE, most other fields
zero.
another example of constructable slab objects is the dcache, we could
construct them this way:
dentry->d_count = 1;
dentry->d_flags = 0;
dentry->d_inode = NULL;
dentry->d_parent = NULL;
dentry->d_sb = NULL;
dentry->d_mounts = dentry;
dentry->d_covers = dentry;
INIT_LIST_HEAD(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs);
INIT_LIST_HEAD(&dentry->d_alias);
(not all uses of slab are perinitializable, eg. vmas are usually 'cloned'
from already existing vmas, but even in this case there are fields that
are almost never used, eg. we could initialize vma->vm_pte to 0 when the
vma is deallocated)
to not populate the cache and generate memory traffic unnecessary, we
could construct the slab object when it's deallocated. (at that point it's
almost 100% likely to still be in cache in a dirty state). We could also
do some (careful!) background construction if some CPU goes idle. (but we
have to be very sure not to pollute the cache prematurely with not yet
used objects.)
(also it might be useful to inline the constructor into the allocation
point somehow, this way we could still get nicely compiled code in the
'not constructed' case, at the cost of more code)
-- mingo
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
Andi Kleen wrote:
> You might not have noticed it, but most skbs are allocated, not cloned.
> It is especially important for the fast routing path, which is totally
> memory bound (when several 100Mbit/s busmastering ethernet cards are active
> the CPU cache isn't of much use anymore because it is invalidated so often).
> The improvements on forwarding performance was the main reason why the slab
> skb patch was added.
Then why not just maintain a free list inside skbuff.c? Very same like
all the other parts of the kernel are doing.
> Also: in the middle of 2.1 there was a nice fork time optimization (it got
> unfortunately thrown out again by the half-finished changes for bigger NR_OPEN
> support, but I plan to resubmit them for 2.3). With clever use of the constructor
Then please reintroduce the fluffy featurefull slab.c in 2.3. The stuff
I had
removed will certianly be not used in 2.2.
> it is possible to avoid the copying of the files array on forking for most cases.
Same again... use a free list.
--Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
MOLNAR Ingo wrote:
>
> On Wed, 13 Jan 1999, Marcin Dalecki wrote:
>
> > Or put it again into 2.3 or whatever. [...]
>
> it breaks the interface. The SLAB allocator should not be faulted for
> other code not using it's capabilities ... It's not something obsolete,
> it's a future use ...
>
> > [...] Even after my patch, there appears to be still *PLENTY* of room
> > for other simplifications/optimizations in slab.c.
>
> your patches are welcome! (Last i checked it had a near perfect jumpless
> fast path.)
You can well make the code denser to improve general cache/branch
prediction
behaviour for example, by removig a lot of featurism. My expierence
shows that
this is already quite a good optimization method in general.
Shorter code runs faster!
--Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
Hello!
Linus Torvalds wrote:
>
> On Wed, 13 Jan 1999, MOLNAR Ingo wrote:
> >
> > On Wed, 13 Jan 1999, Marcin Dalecki wrote:
> >
> > > Or put it again into 2.3 or whatever. [...]
> >
> > it breaks the interface. The SLAB allocator should not be faulted for
> > other code not using it's capabilities ... It's not something obsolete,
> > it's a future use ...
>
> The slab code _should_ be faulted for being ugly as hell, and much too
> complex for it's uses. I've wanted to remove it several times completely,
> going back to the older kmalloc(). I appreciate people looking into
> removing features that are hardly ever used and of dubious value.
No need to say that if only my english where better I couldn't express
it
better by myself.
> I bet that 100% of the benefit of slab could be gotten with a really small
> skb "cache" in front of a much simpler kmalloc() (where the skb cache
> would be a few entries worth of pre-initialized skb's). Or alternatively
> just keep sab, but separate the notion of allocation and caching - so that
> the 99% that are _not_ interested in constructors would never have to go
> through any parts that know about them.
OK Linus if you give the blessing I will spend much more
ime on making this somehow more smooth. The separation idea
is something certainly worth a second tought. Maybe one could
provide a real clean abstraction for the free list mechanism used
all around the kernel thus helping reducing code duplication.
I hope I have already shown by practice that optimizing is
something I appreciate doing
(remember the complete CD-ROM driver in just about two pages :-).
I have already some ideas about how to first gather real allocator
behaviour from the kernel, and how to move the developement of the slab
code into user space with easy proper bechmarking, based on this *real*
data, using all the usual user space tools to tweak it to no end...
However since I'm already proffesional at coding, I wouldn't like
to spend serious time on this without knowing first, that the results
will have some real chances to be actually used.
Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
> > The improvements on forwarding performance was the main reason why the slab
> > skb patch was added.
>
> Then why not just maintain a free list inside skbuff.c? Very same like
> all the other parts of the kernel are doing.
No. Thats not what slab is all about. Read the papers.
> > it is possible to avoid the copying of the files array on forking for most cases.
>
> Same again... use a free list.
A free list doesnt do cache optimisations. I think you should read the
papers on SLAB before you do anything more than remove dead constructor
code. Also do you want 300 free lists in the kernel. Then you can write
a vm layer to balance them. Linus just blew away a ton of this kind of mess
in the VM with user pages. Don't reinvent the problems some older BSDs had
with 400 different ways to reclaim mbufs on a bad day.
I'd agree the slab code is messy, I can see the argument for removing the
un-needed constructors and that seems fine, someone can put it back nicely
when they use it. That bit makes sense.
However anyone who blithely throws slab out without doing serious benchmarks
on high end network performance is a fool. Furthermore 2.2 is not the time
to be trying to throw out slab. 2.3 is the time to try and throw it out
by proving you can consistently beat it.
Alan
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
On Wed, Jan 13, 1999 at 08:27:59PM +0100, Alan Cox wrote:
> > With one exception nobody stepped in and used this feature!
> > Look at the patch the constructor usage there was just preventing
> > a hand full of zero initializations, just about 8 or 10 (frankly I don't
> > remember exactly), which looked the following way around:
>
> Im not arguing about removing the constructors. We don't use them, why keep
> them. They can be put back if/when used. Slab itself is a different matter
I hope to reintroduce the lazy copying fork optimization for big file tables
once the big NROPEN mess is sorted out. For that constructors are needed.
[.To be honest I'm still pissed that that nice optimization was thrown out,
without finishing the work - supporting sparse fd arrays fully. It would be
best to either revert fork.c:copy_files to 2.1.5x state or finish the sparse
array implementation]
>
> >>From thje other paragraph I think I just got the wrong end of the stick. Its
> removing slab I don't want to see, not removing pointless constructors.
I don't think it is a good idea to throw out useful infrastructure.
-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
Alan Cox wrote:
> > Then why not just maintain a free list inside skbuff.c? Very same like
> > all the other parts of the kernel are doing.
>
> No. Thats not what slab is all about. Read the papers.
I did read it! I did read it! I did... and I still don't buy much of
the claims made there without looking at the context of usage.
> > > it is possible to avoid the copying of the files array on forking for most cases.
> >
> > Same again... use a free list.
>
> A free list doesnt do cache optimisations. I think you should read the
> papers on SLAB before you do anything more than remove dead constructor
> code. Also do you want 300 free lists in the kernel. Then you can write
No certainly I don't want. The places where those are used are rare in
linux.
And this is actully how linux is dealing with the problem already.
It just turns out there there isn't that much of place to do reusal at
all.
My notes about the free lists should be primary seen as a hint on about
which *fundamental* changes to the design of the kernel would be needed
to make actuall use of something like the slab constructor/destructor
mechanism. Quite the opposite way around also.
In case of skbuff I didn't mean it serious. It's not worth it.
> a vm layer to balance them. Linus just blew away a ton of this kind of mess
> in the VM with user pages. Don't reinvent the problems some older BSDs had
Ehm I didn't notice the VM layer used slab constructors/destructors in
any way.
> with 400 different ways to reclaim mbufs on a bad day.
>
> I'd agree the slab code is messy, I can see the argument for removing the
> un-needed constructors and that seems fine, someone can put it back nicely
> when they use it. That bit makes sense.
>
> However anyone who blithely throws slab out without doing serious benchmarks
> on high end network performance is a fool. Furthermore 2.2 is not the time
Please tell me what was there to benchmark it? Are you going to
impress me with the network statement? That's not that easy :-).
With one exception nobody stepped in and used this feature!
Look at the patch the constructor usage there was just preventing
a hand full of zero initializations, just about 8 or 10 (frankly I don't
remember exactly), which looked the following way around:
boo->blah = NULL;
boo->bang = NULL;
boo->bar = 0;
boo->geek = 0;
...
This translated into code wasn't justifying any serious trouble to
trying to avoid it: Compare this please to the cost to check
*everywhere* for the presence of a constructor or destructor and then
actually calling it in case of need. Oh of course it's harder to count
this penaly in cycles together.
(I certainly know you can imagine the very very sparse code the compiler
is making out of the stuff shown above.
MV &BOO --> X
XOR AX, AX
MV AX *X, ++X
MV AX *X, ++X
...
) And at the other place it invented some "write only"
operations. However I'm fully aware about the fact that the other
place was less common.
> to be trying to throw out slab. 2.3 is the time to try and throw it out
> by proving you can consistently beat it.
I didn't mean to throw it out *entierly*. What I'm primarly
after is removing carfully all the unneded stuff for the
*STABLE* release. I don't like to
see a *STABLE* productivity release containing unused
(and therefore not seriously tested code). And on the way of
doing this I would certainly like to reorder, squezze,
tweak some stuff in it. I'm certainly aware about the
fact that there is need for stability in first place now.
BTW> I don't see the need for a TBit betwork in my home to do some
serious benchmarking. And I have some real worlds MBits at
hand in work :-).
Second please have a look at the places where I have added some
comments about the usage of the other remaining parameters to
kmem_cache_create(). They show quite clear, that there seems
to be at least a little confusion about what they are
actually usefull for. And as long as long the confusion remains
there are no chances they will be used properly.
--Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
MOLNAR Ingo wrote:
> but removing ctor/dtor is i think a mistake, although i agree that it's
> inactive code currently.
>
> > I bet that 100% of the benefit of slab could be gotten with a really small
> > skb "cache" in front of a much simpler kmalloc() (where the skb cache
> > would be a few entries worth of pre-initialized skb's). Or alternatively
> > just keep sab, but separate the notion of allocation and caching - so that
> > the 99% that are _not_ interested in constructors would never have to go
> > through any parts that know about them.
>
> the SLAB also keeps caches separated, which (to me) feels better than what
> kmalloc could give us anytime. I was always worried about the multipage
> allocations done by the SLAB, but this fragmentation issue seems to be a
> red herring after all.
This isn't true. Do you remember the discussion after it got
introduced? There where *plenty* of people crying about exactly this
problem.
> another example of constructable slab objects is the dcache, we could
> construct them this way:
>
> (not all uses of slab are perinitializable, eg. vmas are usually 'cloned'
> from already existing vmas, but even in this case there are fields that
> are almost never used, eg. we could initialize vma->vm_pte to 0 when the
> vma is deallocated)
Ah there you repeat my main argument why the whole idea behind it
doesn't
buy you much in linux.
You had TWO YEARS of time to proove it in PRACTICE that it
would be usefull and how wonderfull it would perform.
However for whichever reasons -- nobody did! Maybe this isn't
just accident?
--Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
> My notes about the free lists should be primary seen as a hint on about
> which *fundamental* changes to the design of the kernel would be needed
> to make actuall use of something like the slab constructor/destructor
> mechanism. Quite the opposite way around also.
Ok. Sorry
> > a vm layer to balance them. Linus just blew away a ton of this kind of mess
> > in the VM with user pages. Don't reinvent the problems some older BSDs had
>
> Ehm I didn't notice the VM layer used slab constructors/destructors in
> any way.
If you have a big pile of lists of free objects just in case you eventually
have to have scavenging routines to get them back on tight memory. BSD for
example recovers mbufs (sk_buff equivalents) when there is a memory shortage,
this means it asks each protocol to ask each of its sockets if it can get
stuff back (ick...). Then there is the "who shall I ask first" question.
(Current BSD this isnt paticularly bad btw)
> > However anyone who blithely throws slab out without doing serious benchmarks
> > on high end network performance is a fool. Furthermore 2.2 is not the time
>
> Please tell me what was there to benchmark it? Are you going to
> impress me with the network statement? That's not that easy :-).
Packets per second with slab versus without.
> With one exception nobody stepped in and used this feature!
> Look at the patch the constructor usage there was just preventing
> a hand full of zero initializations, just about 8 or 10 (frankly I don't
> remember exactly), which looked the following way around:
Im not arguing about removing the constructors. We don't use them, why keep
them. They can be put back if/when used. Slab itself is a different matter
From thje other paragraph I think I just got the wrong end of the stick. Its
removing slab I don't want to see, not removing pointless constructors.
Alan
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
"David S. Miller" wrote:
>
> > the SLAB also keeps caches separated, which (to me) feels better
> > than what kmalloc could give us anytime. I was always worried
> > about the multipage allocations done by the SLAB, but this
> > fragmentation issue seems to be a red herring after all.
>
> This isn't true. Do you remember the discussion after it got
> introduced? There where *plenty* of people crying about exactly
> this problem.
>
> As soon as we forced unconditional reaping at every try_to_free_page()
> attempt, the majority, if not all, of these problems went away.
Oh OK I didn't follow it that close.
> You had TWO YEARS of time to proove it in PRACTICE that it would be
> usefull and how wonderfull it would perform. However for whichever
> reasons -- nobody did! Maybe this isn't just accident?
>
> It costs one instruction to test a single bit, and this instruction
> will be there even if you removed ctor/dtor support entirely from SLAB
> because other feature bits are being checked at the same time in that
> instruction. So the total cost of this facility is two pointers in an
> internal structure used by the SLAB subsystem, not more.
The only second other "feature" bit tested there I see which can't be
avoided is the distinguishment between slabs for slabs and slabs for
other things. Many many of the other features are dead as well :-).
> Andi Kleen, among others, did make good usage of the ctor/dtor
> facility, but due to other happenings in the areas where he had made
> his changes at the time, the patches did not go in.
>
> I myself have several ideas for using this, but I also am deferring
> this work to 2.3.x where it belongs.
So put the whole back into 2.3.x.
> As for evidence that SLAB in and of itself is faster, look at the
> change which made SKB's structure part get allocated allocated via a
> SLAB cache and the data part thru kmalloc(). This increased TCP
> bandwidth very measurably. At the time, as a test, I turned off
> SLAB's cache alignment heuristics so that no cache coloring was done
> at all, the result was that Andi's change made TCP bandwidth worse.
> (both cases were relatively worse with cache coloring turned off in
> SLAB, so: 1) Andi's change was relatively worse with SLAB coloring
> turned off and 2) both cases (with and without Andi's SKB change) were
> equally relatively worse with coloring off than on... the whole point
> here is that the coloring scheme of SLAB helped regardless of SKB
> allocation scheme used, and helps even more so with Andi's change).
This is mainly prooving that the slab is a faster kmalloc in some places
:-).
It doesn't exclude the possibility to make it even faster and cleaner
in implementation :-).
However I have evidently my oppinnions about the usefulness of the
constructor/destructor concept in respect of the current *fundamental*
kernel design. The colouring benchmarks I don't beleve until I
reproduce them myself in a NON ISOLATED environment.
> If you have the worlds greatest memory allocator for the kernel, then
> "jak fajnie"! I can't wait to see it. But now is the time for
> stabilizing what we have, unless you have a drop in replacement which
> Linus can put in without thinking.
Eh... David just a hint: I'm not that "durny i naiwny" to claim that I
would
like to start from scratch and provide something entiertly new and
"wonderfull".
Really no need to get ironic... (however please feel free at ironizing
at
my english as much as is deservs :-)
I already quite like for example the idea of saving passing the structs
size
all the way along it's allocation for example!. This way the unavoidable
second parameter is servig a dual purspose instead of a single one. It
hints
us at where to get our allocation chunk candidates from as well.
I would just like do some deeper cleanup in the existing slab.c
Please take note of the comments about the additional flags usage for
kmem_create_cache I have put in the patch too. OK?
--Marcin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
If you look at the code path which actually checks for whether
constructor/destructor stuff needs to happen, SLAB is checking
multiple flag bits in a single word at once and branches to a slow
path if any of these features are being used (ctors, dtors, SLAB
debugging, etc.)
The overhead is therefore one instruction and two pointers in an
internal structure which is always hot in the cache anyways. Worth
removing the facility completely? I don't think so.
Later,
David S. Miller
davem@dm.cobaltmicro.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Re: PATCH killing dead code and design errors in pre6 [ In reply to ]
Date: Wed, 13 Jan 1999 20:27:17 +0100
From: Marcin Dalecki <dalecki@cs.net.pl>
> the SLAB also keeps caches separated, which (to me) feels better
> than what kmalloc could give us anytime. I was always worried
> about the multipage allocations done by the SLAB, but this
> fragmentation issue seems to be a red herring after all.
This isn't true. Do you remember the discussion after it got
introduced? There where *plenty* of people crying about exactly
this problem.
As soon as we forced unconditional reaping at every try_to_free_page()
attempt, the majority, if not all, of these problems went away.
You had TWO YEARS of time to proove it in PRACTICE that it would be
usefull and how wonderfull it would perform. However for whichever
reasons -- nobody did! Maybe this isn't just accident?
It costs one instruction to test a single bit, and this instruction
will be there even if you removed ctor/dtor support entirely from SLAB
because other feature bits are being checked at the same time in that
instruction. So the total cost of this facility is two pointers in an
internal structure used by the SLAB subsystem, not more.
Andi Kleen, among others, did make good usage of the ctor/dtor
facility, but due to other happenings in the areas where he had made
his changes at the time, the patches did not go in.
I myself have several ideas for using this, but I also am deferring
this work to 2.3.x where it belongs.
As for evidence that SLAB in and of itself is faster, look at the
change which made SKB's structure part get allocated allocated via a
SLAB cache and the data part thru kmalloc(). This increased TCP
bandwidth very measurably. At the time, as a test, I turned off
SLAB's cache alignment heuristics so that no cache coloring was done
at all, the result was that Andi's change made TCP bandwidth worse.
(both cases were relatively worse with cache coloring turned off in
SLAB, so: 1) Andi's change was relatively worse with SLAB coloring
turned off and 2) both cases (with and without Andi's SKB change) were
equally relatively worse with coloring off than on... the whole point
here is that the coloring scheme of SLAB helped regardless of SKB
allocation scheme used, and helps even more so with Andi's change).
If you have the worlds greatest memory allocator for the kernel, then
"jak fajnie"! I can't wait to see it. But now is the time for
stabilizing what we have, unless you have a drop in replacement which
Linus can put in without thinking.
Later,
David S. Miller
davem@dm.cobaltmicro.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/