diff options
author | Rom Lemarchand <romlem@google.com> | 2013-07-08 21:50:24 -0700 |
---|---|---|
committer | Rom Lemarchand <romlem@google.com> | 2013-07-09 13:45:38 -0700 |
commit | 2bed1558d45f10384a0293e7d27a59315e355c9f (patch) | |
tree | 5d7b60f3df65f5e09edf61b8597b6900d3eb8bc6 | |
parent | 266dde27811b78f466702295ba0173b8d8be5ada (diff) | |
download | extras-2bed1558d45f10384a0293e7d27a59315e355c9f.tar.gz |
ksmutils: Add sort option to ksminfo
Add an option to sort pages by usage count in ksminfo.
Change-Id: I115ed7d8f8e99b8eed636e88605421c1b20b8d77
Signed-off-by: Rom Lemarchand <romlem@google.com>
-rw-r--r-- | ksmutils/ksminfo.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/ksmutils/ksminfo.c b/ksmutils/ksminfo.c index 9423f4ff..7c682f97 100644 --- a/ksmutils/ksminfo.c +++ b/ksmutils/ksminfo.c @@ -32,10 +32,14 @@ #define NO_PATTERN 0x100 +#define PR_SORTED 1 +#define PR_VERBOSE 2 + static void usage(char *myname); static int getprocname(pid_t pid, char *buf, int len); -static void print_ksm_pages(pm_map_t **maps, size_t num_maps, bool verbose); +static void print_ksm_pages(pm_map_t **maps, size_t num_maps, uint8_t pr_flags); static bool is_pattern(uint8_t *data, size_t len); +static int cmp_pages(const void *a, const void *b); extern uint32_t hashword(const uint32_t *, size_t, int32_t); struct ksm_page { @@ -54,17 +58,20 @@ int main(int argc, char *argv[]) { char cmdline[256]; // this must be within the range of int int error; int rc = EXIT_SUCCESS; - bool verbose = false; + uint8_t pr_flags = 0; opterr = 0; do { - int c = getopt(argc, argv, "hv"); + int c = getopt(argc, argv, "hvs"); if (c == -1) break; switch (c) { + case 's': + pr_flags |= PR_SORTED; + break; case 'v': - verbose = true; + pr_flags |= PR_VERBOSE; break; case 'h': usage(argv[0]); @@ -113,7 +120,7 @@ int main(int argc, char *argv[]) { printf("%s (%u):\n", cmdline, pid); printf("Warning: this tool only compares the KSM CRCs of pages, there is a chance of " "collisions\n"); - print_ksm_pages(maps, num_maps, verbose); + print_ksm_pages(maps, num_maps, pr_flags); free(maps); destroy_proc: @@ -121,7 +128,7 @@ destroy_proc: return rc; } -static void print_ksm_pages(pm_map_t **maps, size_t num_maps, bool verbose) { +static void print_ksm_pages(pm_map_t **maps, size_t num_maps, uint8_t pr_flags) { size_t i, j, k; size_t len; uint64_t *pagemap; @@ -216,7 +223,7 @@ static void print_ksm_pages(pm_map_t **maps, size_t num_maps, bool verbose) { pages_len++; } - if (verbose) { + if (pr_flags & PR_VERBOSE) { if (pages[k].vaddr_len == pages[k].vaddr_size) { unsigned long *tmp = realloc(pages[k].vaddr, (pages[k].vaddr_size + GROWTH_FACTOR) * sizeof(*(pages[k].vaddr))); @@ -236,6 +243,10 @@ static void print_ksm_pages(pm_map_t **maps, size_t num_maps, bool verbose) { free(pagemap); } + if (pr_flags & PR_SORTED) { + qsort(pages, pages_len, sizeof(*pages), cmp_pages); + } + for (i = 0; i < pages_len; i++) { if (pages[i].pattern != NO_PATTERN) { printf("0x%02x byte pattern: ", pages[i].pattern); @@ -248,7 +259,7 @@ static void print_ksm_pages(pm_map_t **maps, size_t num_maps, bool verbose) { } printf("\n"); - if (verbose) { + if (pr_flags & PR_VERBOSE) { j = 0; while (j < pages[i].vaddr_len) { printf(" "); @@ -261,7 +272,7 @@ static void print_ksm_pages(pm_map_t **maps, size_t num_maps, bool verbose) { } err_realloc: - if (verbose) { + if (pr_flags & PR_VERBOSE) { for (i = 0; i < pages_len; i++) { free(pages[i].vaddr); } @@ -274,12 +285,20 @@ err_open: } static void usage(char *myname) { - fprintf(stderr, "Usage: %s [ -v | -h ] <pid>\n" + fprintf(stderr, "Usage: %s [-s | -v | -h ] <pid>\n" + " -s Sort pages by usage count.\n" " -v Verbose: print virtual addresses.\n" " -h Display this help screen.\n", myname); } +static int cmp_pages(const void *a, const void *b) { + const struct ksm_page *pg_a = a; + const struct ksm_page *pg_b = b; + + return pg_b->vaddr_len - pg_a->vaddr_len; +} + static bool is_pattern(uint8_t *data, size_t len) { size_t i; uint8_t first_byte = data[0]; |