Re: 2.1.115 is not slower than 2.0.34

Andi Kleen (ak@muc.de)
15 Aug 1998 13:28:52 +0200


In article <UTC199808150825.KAA08521.aeb@texel.cwi.nl>,
Andries.Brouwer@cwi.nl writes:
> After I sent a patch improving the speed of ext2, I hoped
> for people telling me about the effects it had. However,
> it seems all activity on the list is about killing X.

> So, I just did some timings myself.
> This is on a 166MHz Pentium with 64MB - rather quiet at the time.
> 2.1.116a is a kernel with my ext2 patch.

Could you do the same test again with this patch applied? It should
tune the dcache even more, with minimal changes and also helps against
memory fragmentation.

It adds:
- Use inline buffer for names <16 bytes. This has a hit rate over 99%
and helps against fragmentation.
- Use the slab allocator directly to allocate dentries. That helps further
against fragmentation and also does L1 cache colouring to optimize cache
usage.

-Andi

Index: linux/fs/dcache.c
===================================================================
RCS file: /vger/u4/cvs/linux/fs/dcache.c,v
retrieving revision 1.58
diff -u -r1.58 dcache.c
--- dcache.c 1998/07/26 03:04:06 1.58
+++ dcache.c 1998/08/15 02:10:44
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/init.h>

#include <asm/uaccess.h>
@@ -29,6 +30,8 @@
extern int inodes_stat[];
#define nr_inodes (inodes_stat[0])

+kmem_cache_t *dentry_cache;
+
/*
* This is the single most critical data structure when it comes
* to the dcache: the hashtable for lookups. Somebody should try
@@ -56,8 +59,9 @@
{
if (dentry->d_op && dentry->d_op->d_release)
dentry->d_op->d_release(dentry);
- kfree(dentry->d_name.name);
- kfree(dentry);
+ if (dname_external(dentry))
+ kfree(dentry->d_name.name);
+ kmem_cache_free(dentry_cache, dentry);
}

/*
@@ -498,15 +502,18 @@
free_inode_memory(8);
}

- dentry = kmalloc(sizeof(struct dentry), GFP_KERNEL);
+ dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
if (!dentry)
return NULL;

- str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);
- if (!str) {
- kfree(dentry);
- return NULL;
- }
+ if (name->len > DNAME_INLINE_LEN-1) {
+ str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);
+ if (!str) {
+ kmem_cache_free(dentry_cache, dentry);
+ return NULL;
+ }
+ } else
+ str = dentry->d_iname;

memcpy(str, name->name, name->len);
str[name->len] = 0;
@@ -723,8 +730,14 @@
list_del(&target->d_child);

/* Switch the parents and the names.. */
- do_switch(dentry->d_parent, target->d_parent);
+ memcpy(target->d_iname, dentry->d_iname, DNAME_INLINE_LEN);
do_switch(dentry->d_name.name, target->d_name.name);
+ if (target->d_name.name == dentry->d_iname)
+ target->d_name.name = target->d_iname;
+ if (dentry->d_name.name == target->d_iname)
+ dentry->d_name.name = dentry->d_iname;
+
+ do_switch(dentry->d_parent, target->d_parent);
do_switch(dentry->d_name.len, target->d_name.len);
do_switch(dentry->d_name.hash, target->d_name.hash);
list_add(&target->d_child, &target->d_parent->d_subdirs);
@@ -884,6 +897,22 @@
{
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.
+ */
+ dentry_cache = kmem_cache_create("dentry_cache",
+ sizeof(struct dentry),
+ 0,
+ SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (!dentry_cache)
+ panic("Cannot create dentry cache");

i = D_HASHSIZE;
do {
Index: linux/include/linux/dcache.h
===================================================================
RCS file: /vger/u4/cvs/linux/include/linux/dcache.h,v
retrieving revision 1.18
diff -u -r1.18 dcache.h
--- dcache.h 1998/07/26 03:00:17 1.18
+++ dcache.h 1998/08/15 02:11:00
@@ -50,6 +50,8 @@
return end_name_hash(hash);
}

+#define DNAME_INLINE_LEN 16
+
struct dentry {
int d_count;
unsigned int d_flags;
@@ -68,6 +70,7 @@
struct super_block * d_sb; /* The root of the dentry tree */
unsigned long d_reftime; /* last time referenced */
void * d_fsdata; /* fs-specific data */
+ unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
};

struct dentry_operations {
@@ -112,6 +115,11 @@
{
list_del(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_hash);
+}
+
+static __inline__ int dname_external(struct dentry *d)
+{
+ return d->d_name.name != d->d_iname;
}

/*

-
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.altern.org/andrebalsa/doc/lkml-faq.html