This is a little handy dandy program that reads in the /proc/slabinfo
data and computes some information about it. I sent it before but I think
it was when vger was down.. so, if you are getting this twice, sorry. :)
The output looks like this.. note that the # of slab catagories is overall.
The program defaults to not showing you the empty ones.
'slabinfo -a' shows you everything.
Slab Active Total Active Total Memory
Name Objs Objs Slabs Slabs (in K)
--------------------------------------------------------
kmem_cache 17 42 1 1 4
sock 20 30 5 6 24
filp 144 168 4 4 16
inode 1616 1620 108 108 432
buffer_head 3438 4368 92 104 416
mm_struct 30 62 1 2 8
vm_area_struct 361 441 6 7 28
uid_cache 1 127 1 1 4
slab_cache 6 63 1 1 4
hash_cache 5 7 1 1 4
--------------------------------------------------------
21 slab catagories 5638 6928 220 235 940k
-- Which is worse: ignorance or apathy? Who knows? Who cares? Most of your faults are not your fault. If you think bus-mastering is what Sandra Bullock did in "Speed", you might be a redneck. Hiroshima '45 - Chernobyl '86 - Windows '95
--bp/iNruPH9dso1Pn Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="slabinfo.c"
/* Slabinfo - peek into the slab allocator - By Aaron Tiensivu * * Version 0.1 - [05/08/97] - Under GPL, standard disclaimers apply * * * * Usage: slabinfo [-a] * * -a will also show empty slab catagories * * * * Could this be a perl script? Sure. * * Why did I write it? Hack value and curiosity * * Limited amount of error checking since this is a QuickHack(tm) * * * * Compile * * For pgcc: * * gcc -o slabinfo -s -O6 -frisc -mpentium slabinfo.c * * * * For GCC 2.7.2: * * gcc -o slabinfo -s -O2 -m486 -fomit-frame-pointer slabinfo.c */ #ifdef __alpha__ #define PROC_SUPER_MAGIC ((short)0x9fa0) #else #define PROC_SUPER_MAGIC 0x9fa0 #endif
#define PROC "/proc"
/* Arbitrary number picked, 256 should suffice for now */ #define MAX_SLABS 256
#include <sys/types.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <math.h> #include <ctype.h> #include <sys/time.h> #include <sys/stat.h> #include <sys/vfs.h> #include <linux/version.h> #include <asm/page.h>
#define pagetok(x) ((x) << (PAGE_SHIFT - 10))
/* Taken from linux/drivers/scsi/advansys.h */
/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2, 1, 22) #error You need kernel version 2.1.22+ for this to work. #endif
/* Taken from linux/mm/slab.c */
/* /proc/slabinfo * cache-name num-active-objs total-objs num-active-slabs total-slabs num-pages-per-slab */
struct slabinfo_stat { char cache_name[20]; unsigned long active_objs; unsigned long total_objs; unsigned long active_slabs; unsigned long total_slabs; unsigned long pages_per_slab; };
static inline char * skip_token(const char *p) { while (isspace(*p)) p++; while (*p && !isspace(*p)) p++; return (char *)p; }
static inline char * skip_ws(const char *p) { while (isspace(*p)) p++; return (char *)p; }
int main(argc, argv) int argc; char **argv; {
struct statfs sb; struct slabinfo_stat sbstat[MAX_SLABS]; struct slabinfo_stat overall; char buffer[4096+1]; char ch;
register int count = -1; int fd, len, i, show_all = 0; char *p; /* overall.cache_name is never used */ overall.active_objs = 0; overall.total_objs = 0; overall.active_slabs= 0; overall.total_slabs = 0; overall.pages_per_slab = 0; while ((ch = getopt(argc, argv, "a")) != EOF) switch(ch) { case 'a': show_all = 1; break; default: printf("\n\nslabinfo version 0.1 [05/08/97] - By Aaron Tiensivu \n"); printf("usage: slabinfo [-a]\n"); printf(" -a includes empty slabs in output \n\n"); exit(0); }
/* Check to see that /proc is really there */
if (statfs(PROC, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC) { fprintf(stderr, "slabinfo: proc not mounted on " PROC "\n"); exit(-1); }
/* Relative filename lookups are faster than absolute. */ /* I realize that we're only reading one file, but it is */ /* the thought that counts. ;-) */ chdir(PROC);
if ( (fd = open("slabinfo", O_RDONLY)) < 0) { fprintf(stderr,"slabinfo: slabinfo not found\n"); exit(-1); }
len = read(fd, buffer, sizeof(buffer)-1); close(fd); buffer[len] = '\0'; p = buffer; do { count++;
/* FIXME: Should check 'slabinfo' version number */
p = strchr(p, '\n') + 1; memcpy(sbstat[count].cache_name, p, 19);
sbstat[count].active_objs = strtoul(skip_token(p), &p, 10); sbstat[count].total_objs = strtoul(skip_ws(p) , &p, 10); sbstat[count].active_slabs = strtoul(skip_ws(p) , &p, 10); sbstat[count].total_slabs = strtoul(skip_ws(p) , &p, 10); sbstat[count].pages_per_slab = strtoul(skip_ws(p) , &p, 10);
overall.active_objs += sbstat[count].active_objs; overall.active_slabs += sbstat[count].active_slabs; overall.pages_per_slab += (sbstat[count].pages_per_slab * sbstat[count].total_slabs);
overall.total_objs += sbstat[count].total_objs; overall.total_slabs += sbstat[count].total_slabs; } while (*p);
/* This still counts empty slab catagories as real catagories */ /* The number of catagories printed may not equal actual amount */
printf("\n\nSlab Active Total Active Total Memory\n"); printf("Name Objs Objs Slabs Slabs (in K)\n"); printf("--------------------------------------------------------\n"); for (i = 0; i < count; i++) { if (show_all || (sbstat[i].total_slabs > 0) ) { printf("%-20s %6lu %6lu %6lu %6lu %6lu\n", sbstat[i].cache_name, sbstat[i].active_objs, sbstat[i].total_objs, sbstat[i].active_slabs, sbstat[i].total_slabs, pagetok((sbstat[i].pages_per_slab * sbstat[i].total_slabs))); } } printf("--------------------------------------------------------\n"); printf("%-3i slab catagories %6lu %6lu %6lu %6lu %6luk\n\n", count, overall.active_objs, overall.total_objs, overall.active_slabs, overall.total_slabs, pagetok(overall.pages_per_slab));
return 0; }
--bp/iNruPH9dso1Pn--