[patch] Statistics revisited

Aaron Tiensivu (tiensivu@pilot.msu.edu)
Wed, 23 Oct 1996 20:36:44 -0400 (EDT)


[2nd posting - FAT cache statistics added]

Does anyone remember the old DOS disk cache program 'Lightning'? I still run
it on my '286 back home. One cool feature was that it had a lot of stats
about the hit and miss ratios of the cache. I was often curious about that
little tidbit of information inside Linux, and now I present a patch to give
you a look under the hood. :)

So that it won't break many programs, I added the information to the end
of '/proc/stat'. The first number presented is the hit number and the
second number is the miss number. The directory cache and the generic buffer
cache is profiled.

This patch is against Linux 2.1.5

Have fun! And please e-mail me if you like it. ;-)

Enjoy,
Aaron Tiensivu (tiensivu@pilot.msu.edu)

--- linux/fs/dcache.c.orig Wed Oct 23 16:03:00 1996
+++ linux/fs/dcache.c Wed Oct 23 20:33:25 1996
@@ -20,6 +20,7 @@

#include <linux/fs.h>
#include <linux/string.h>
+#include <linux/kernel_stat.h>

/*
* Don't bother caching long names.. They just take up space in the cache, and
@@ -185,14 +186,20 @@
struct hash_list * hash;
struct dir_cache_entry *de;

- if (len > DCACHE_NAME_LEN)
+ if (len > DCACHE_NAME_LEN) {
+ kstat.dirc_miss++;
return 0;
+ }
+
hash = hash_table + hash_fn(dir->i_dev, dir->i_ino, namehash(name,len));
de = find_entry(dir, name, len, hash);
- if (!de)
+ if (!de) {
+ kstat.dirc_miss++;
return 0;
+ }
*ino = de->ino;
move_to_level2(de, hash);
+ kstat.dirc_hit++;
return 1;
}

--- linux/fs/buffer.c.orig Wed Oct 23 19:04:49 1996
+++ linux/fs/buffer.c Wed Oct 23 19:13:07 1996
@@ -31,6 +31,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
+#include <linux/kernel_stat.h>

#include <asm/system.h>
#include <asm/segment.h>
@@ -481,13 +482,15 @@

for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
if (tmp->b_blocknr == block && tmp->b_dev == dev)
- if (tmp->b_size == size)
+ if (tmp->b_size == size) {
+ kstat.dskc_hit++;
return tmp;
- else {
+ } else {
printk("VFS: Wrong blocksize on device %s\n",
kdevname(dev));
return NULL;
}
+ kstat.dskc_miss++;
return NULL;
}

--- linux/include/linux/kernel_stat.h.orig Wed Oct 23 16:01:12 1996
+++ linux/include/linux/kernel_stat.h Wed Oct 23 20:17:43 1996
@@ -25,6 +25,13 @@
unsigned int ierrors, oerrors;
unsigned int collisions;
unsigned int context_swtch;
+#ifdef CONFIG_PROC_FS
+ unsigned int dirc_hit, dirc_miss;
+ unsigned int dskc_hit, dskc_miss;
+#ifdef CONFIG_MSDOS_FS
+ unsigned int fatc_hit, fatc_miss;
+#endif
+#endif /* CONFIG_PROC_FS */
};

extern struct kernel_stat kstat;
--- linux/fs/proc/array.c.orig Wed Oct 23 16:10:26 1996
+++ linux/fs/proc/array.c Wed Oct 23 20:14:52 1996
@@ -28,6 +28,9 @@
*
* Yves Arrouye : remove removal of trailing spaces in get_array.
* <Yves.Arrouye@marin.fdn.fr>
+ *
+ * Aaron Tiensivu : added directory/generic/FAT buffer cache hits and misse
s
+ * <tiensivu@pilot.msu.edu>
*/

#include <linux/types.h>
@@ -197,6 +200,7 @@

for (i = 0 ; i < NR_IRQS ; i++)
sum += kstat.interrupts[i];
+
len = sprintf(buffer,
"cpu %u %u %u %lu\n"
"disk %u %u %u %u\n"
@@ -226,15 +230,32 @@
kstat.pswpin,
kstat.pswpout,
sum);
+
for (i = 0 ; i < NR_IRQS ; i++)
len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
+
len += sprintf(buffer + len,
"\nctxt %u\n"
"btime %lu\n"
- "processes %lu\n",
- kstat.context_swtch,
+ "processes %lu\n"
+ "dircache %u %u\n"
+ "dskcache %u %u\n"
+#ifdef CONFIG_MSDOS_FS
+ "fatcache %u %u\n"
+#endif
+ ,kstat.context_swtch,
xtime.tv_sec - jiffies / HZ,
- total_forks);
+ total_forks,
+ kstat.dirc_hit,
+ kstat.dirc_miss,
+ kstat.dskc_hit,
+ kstat.dskc_miss
+#ifdef CONFIG_MSDOS_FS
+ ,kstat.fatc_hit,
+ kstat.fatc_miss
+#endif
+ );
+
return len;
}

--- linux/fs/fat/cache.c.orig Wed Oct 23 19:54:53 1996
+++ linux/fs/fat/cache.c Wed Oct 23 20:05:38 1996
@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
+#include <linux/kernel_stat.h>

#include "msbuffer.h"

@@ -134,8 +135,12 @@
#ifdef DEBUG
printk("cache hit: %d (%d)\n",walk->file_cluster,*d_clu);
#endif
- if ((*f_clu = walk->file_cluster) == cluster) return;
+ if ((*f_clu = walk->file_cluster) == cluster) {
+ kstat.fatc_hit++;
+ return;
+ }
}
+ kstat.fatc_miss++;
#ifdef DEBUG
printk("cache miss\n");
#endif