From mboxrd@z Thu Jan 1 00:00:00 1970 From: Peter Zijlstra Date: Tue, 11 Jul 2006 20:29:50 +0200 Message-Id: <20060711182950.31293.14820.sendpatchset@lappy> In-Reply-To: <20060711182936.31293.58306.sendpatchset@lappy> References: <20060711182936.31293.58306.sendpatchset@lappy> Subject: [PATCH 2/2] mm: refault histogram Sender: owner-linux-mm@kvack.org Return-Path: To: linux-mm@kvack.org, linux-kernel@vger.kernel.org Cc: Peter Zijlstra , Rik van Riel List-ID: From: Peter Zijlstra Adds a refault histogram on top of the nonresident code. Based on ideas and code from Rik van Riel. Signed-off-by: Peter Zijlstra page[i] = 0; /* Return the distance between entry and clock hand. */ distance = atomic_read(&nr_bucket->hand) + NUM_NR - i; - distance %= NUM_NR; - return (distance << nonres_shift) + (nr_bucket - nonres_table); + distance = (distance % NUM_NR) << nonres_shift; + distance += (nr_bucket - nonres_table); + goto out; } } - return ~0UL; + distance = ~0UL; +out: +#ifdef CONFIG_MM_REFAULT + { + extern void nonresident_refault(unsigned long); + nonresident_refault(distance); + } +#endif /* CONFIG_MM_REFAULT */ + return distance; } u32 nonresident_put(struct address_space * mapping, unsigned long index) Index: linux-2.6/mm/refault.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/mm/refault.c 2006-07-11 18:07:03.000000000 +0200 @@ -0,0 +1,114 @@ +#include +#include +#include +#include + +#define BUCKETS 64 + +DEFINE_PER_CPU(unsigned long[BUCKETS+1], refault_histogram); + +extern unsigned long nonresident_total(void); + +void nonresident_refault(unsigned long distance) +{ + unsigned long nonres_bucket = nonresident_total() / BUCKETS; + unsigned long bucket_id = distance / nonres_bucket; + + if (bucket_id > BUCKETS) + bucket_id = BUCKETS; + + __get_cpu_var(refault_histogram)[bucket_id]++; +} + +#ifdef CONFIG_PROC_FS + +#include + +static void *frag_start(struct seq_file *m, loff_t *pos) +{ + if (*pos < 0 || *pos > BUCKETS) + return NULL; + + m->private = (void *)(unsigned long)*pos; + + return pos; +} + +static void *frag_next(struct seq_file *m, void *arg, loff_t *pos) +{ + if (*pos < BUCKETS) { + (*pos)++; + (unsigned long)m->private++; + return pos; + } + return NULL; +} + +static void frag_stop(struct seq_file *m, void *arg) +{ +} + +unsigned long get_refault_stat(unsigned long index) +{ + unsigned long total = 0; + int cpu; + + for_each_possible_cpu(cpu) { + total += per_cpu(refault_histogram, cpu)[index]; + } + return total; +} + +static int frag_show(struct seq_file *m, void *arg) +{ + unsigned long index = (unsigned long)m->private; + unsigned long nonres_bucket = nonresident_total() / BUCKETS; + unsigned long upper = ((unsigned long)index + 1) * nonres_bucket; + unsigned long lower = (unsigned long)index * nonres_bucket; + unsigned long hits = get_refault_stat(index); + + if (index == 0) + seq_printf(m, " Refault distance Hits\n"); + + if (index < BUCKETS) + seq_printf(m, "%9lu - %9lu %9lu\n", lower, upper, hits); + else + seq_printf(m, " New/Beyond %9lu %9lu\n", lower, hits); + + return 0; +} + +struct seq_operations refault_op = { + .start = frag_start, + .next = frag_next, + .stop = frag_stop, + .show = frag_show, +}; + +static void refault_reset(void) +{ + int cpu; + int bucket_id; + + for_each_possible_cpu(cpu) { + for (bucket_id = 0; bucket_id <= BUCKETS; ++bucket_id) + per_cpu(refault_histogram, cpu)[bucket_id] = 0; + } +} + +ssize_t refault_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + char c; + + if (get_user(c, buf)) + return -EFAULT; + if (c == '0') + refault_reset(); + } + return count; +} + +#endif /* CONFIG_PROCFS */ + Index: linux-2.6/mm/Makefile =================================================================== --- linux-2.6.orig/mm/Makefile 2006-07-11 18:07:03.000000000 +0200 +++ linux-2.6/mm/Makefile 2006-07-11 18:07:03.000000000 +0200 @@ -14,6 +14,7 @@ obj-y := bootmem.o filemap.o mempool.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o obj-$(CONFIG_MM_NONRESIDENT) += nonresident.o +obj-$(CONFIG_MM_REFAULT) += refault.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o obj-$(CONFIG_SPARSEMEM) += sparse.o -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org