From: Manfred Spraul attached is my proposal for a new layout of /proc/slabinfo: - It's important to identify if allocation/freeing is cpu bound, thus alloc/free data must be reported per-cpu. - The current format is not pretty: with statistics enabled, the line quite long. Adding per-cpu data to the single-line layout would make it completely unreadable, thus I've switch to a multi line layout. I've added a header that lists all fields. mm/slab.c | 68 +++++++++++++++++++++++++++++++++++++------------------------- 1 files changed, 41 insertions(+), 27 deletions(-) diff -puN mm/slab.c~slabinfo-rework mm/slab.c --- 25/mm/slab.c~slabinfo-rework 2003-05-23 18:44:18.000000000 -0700 +++ 25-akpm/mm/slab.c 2003-05-23 18:44:18.000000000 -0700 @@ -276,10 +276,10 @@ struct kmem_cache_s { unsigned long reaped; unsigned long errors; unsigned long max_freeable; - atomic_t allochit; - atomic_t allocmiss; - atomic_t freehit; - atomic_t freemiss; + unsigned long allochit[NR_CPUS]; + unsigned long allocmiss[NR_CPUS]; + unsigned long freehit[NR_CPUS]; + unsigned long freemiss[NR_CPUS]; #endif }; @@ -311,10 +311,10 @@ struct kmem_cache_s { (x)->max_freeable = i; \ } while (0) -#define STATS_INC_ALLOCHIT(x) atomic_inc(&(x)->allochit) -#define STATS_INC_ALLOCMISS(x) atomic_inc(&(x)->allocmiss) -#define STATS_INC_FREEHIT(x) atomic_inc(&(x)->freehit) -#define STATS_INC_FREEMISS(x) atomic_inc(&(x)->freemiss) +#define STATS_INC_ALLOCHIT(x) ((x)->allochit[smp_processor_id()]++) +#define STATS_INC_ALLOCMISS(x) ((x)->allocmiss[smp_processor_id()]++) +#define STATS_INC_FREEHIT(x) ((x)->freehit[smp_processor_id()]++) +#define STATS_INC_FREEMISS(x) ((x)->freemiss[smp_processor_id()]++) #else #define STATS_INC_ACTIVE(x) do { } while (0) #define STATS_DEC_ACTIVE(x) do { } while (0) @@ -2387,11 +2387,18 @@ static void *s_start(struct seq_file *m, * Output format version, so at least we can change it * without _too_ many complaints. */ - seq_puts(m, "slabinfo - version: 1.2" #if STATS - " (statistics)" + seq_puts(m, "slabinfo - version: 2.0 (statistics)\n"); +#else + seq_puts(m, "slabinfo - version: 2.0\n"); +#endif + seq_puts(m, "# name active_objs num_objs objsize objperslab pagesperslab\n"); + seq_puts(m, "#! tunables batchcount limit sharedfactor\n"); + seq_puts(m, "#! slabdata active_slabs num_slabs sharedavail\n"); +#if STATS + seq_puts(m, "#! globalstat listallocs maxobjs grown reaped error maxfreeable freelimit\n"); + seq_puts(m, "#! cpustat N allochit allocmiss freehit freemiss\n"); #endif - "\n"); } p = cache_chain.next; while (n--) { @@ -2475,13 +2482,16 @@ static int s_show(struct seq_file *m, vo if (error) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); - seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u", + seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d\n", name, active_objs, num_objs, cachep->objsize, - active_slabs, num_slabs, (1<gfporder)); - - seq_printf(m, " : %4u %4u", cachep->limit, cachep->batchcount); + cachep->num, (1<gfporder)); + seq_printf(m, "! tunables %4u %4u %4u\n", + cachep->limit, cachep->batchcount, + cachep->lists.shared->limit/cachep->batchcount); + seq_printf(m, "! slabdata %6lu %6lu %6u\n", + active_slabs, num_slabs, cachep->lists.shared->avail); #if STATS - { // list3 stats + { /* list3 stats */ unsigned long high = cachep->high_mark; unsigned long allocs = cachep->num_allocations; unsigned long grown = cachep->grown; @@ -2490,22 +2500,26 @@ static int s_show(struct seq_file *m, vo unsigned long max_freeable = cachep->max_freeable; unsigned long free_limit = cachep->free_limit; - seq_printf(m, " : %6lu %7lu %5lu %4lu %4lu %4lu %4lu", - high, allocs, grown, reaped, errors, + seq_printf(m, "! globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu\n", + allocs, high, grown, reaped, errors, max_freeable, free_limit); } - { // cpucache stats - unsigned long allochit = atomic_read(&cachep->allochit); - unsigned long allocmiss = atomic_read(&cachep->allocmiss); - unsigned long freehit = atomic_read(&cachep->freehit); - unsigned long freemiss = atomic_read(&cachep->freemiss); - - seq_printf(m, " : %6lu %6lu %6lu %6lu", - allochit, allocmiss, freehit, freemiss); + /* cpu stats */ + { + int i; + for (i=0;iallochit[i]; + unsigned long allocmiss = cachep->allocmiss[i]; + unsigned long freehit = cachep->freehit[i]; + unsigned long freemiss = cachep->freemiss[i]; + + if (allochit | allocmiss | freehit | freemiss) + seq_printf(m, "! cpustat %3d %6lu %6lu %6lu %6lu\n", + i, allochit, allocmiss, freehit, freemiss); + } } #endif spin_unlock_irq(&cachep->spinlock); - seq_putc(m, '\n'); return 0; } _