]> git.itanic.dy.fi Git - scan-pagemap/blob - analyze.c
Analyzer: Add per pid analyzer
[scan-pagemap] / analyze.c
1 #include <string.h>
2 #include <stdio.h>
3
4 #include "analyze.h"
5 #include "utils.h"
6 #include "bintree.h"
7
8 #define SI_k    1024ll
9 #define SI_M    (SI_k * SI_k)
10 #define SI_G    (SI_M * SI_k)
11
12 #define PRETTY_THRESH   100
13 #define NICE_DIV(a)                                                     \
14         ((a) < SI_k * PRETTY_THRESH ? (a) :                             \
15                 (a < SI_M * PRETTY_THRESH ? ((a) / SI_k) :              \
16                         (a < SI_G * PRETTY_THRESH ? ((a) / SI_M) :      \
17                                 ((a) / SI_G))))
18
19 #define NICE_UNIT(a)                                                    \
20         ((a) < (SI_k * PRETTY_THRESH) ? " " :                           \
21                 ((a) < (SI_G * PRETTY_THRESH) ? "k" :                   \
22                         ((a) < (SI_G * PRETTY_THRESH) ? "M" : "G")))
23
24 #define PAGE_TO_NICE(a)         NICE_DIV((long long)a * PAGE_SIZE)
25 #define PAGE_TO_NICE_UNIT(a)    NICE_UNIT((long long)a * PAGE_SIZE)
26
27 struct analyze_frames {
28         struct bintree_ops ops;
29         long int present_pages;
30         long int swapped_pages;
31         long int unused_pages;
32 };
33
34 #define bintree_ops_to_af(bintree_ops)                          \
35         container_of((bintree_ops), struct analyze_frames, ops)
36
37 static void count_pages(struct bintree *b, struct bintree_ops *ops)
38 {
39         struct pageframe *pf = tree_to_pageframe(b);
40         struct analyze_frames *af = bintree_ops_to_af(ops);
41
42         if (pf->page_present) {
43                 af->present_pages += pf->refcount;
44         } else if (pf->page_swapped) {
45                 af->swapped_pages += pf->refcount;
46         } else {
47                 af->unused_pages += pf->refcount;
48         }
49 }
50
51 /*
52  * print_page_stats - Prints system wide page stats
53  */
54 void print_page_stats(struct pageframe *pf)
55 {
56         struct analyze_frames af;
57         long count;
58         memset(&af, 0, sizeof(af));
59
60         af.ops.callback = count_pages;
61
62         count = bintree_walk(&pf->tree, &af.ops);
63         printf("present pages: %ld, %lld %sB\n"
64                 "Swapped pages: %ld, %lld %sB\n"
65                 "Unused pages: %ld, %lld %sB\n"
66                 "Total %ld physical pages, %lld %sB\n",
67                 af.present_pages,
68                 PAGE_TO_NICE(af.present_pages),
69                 PAGE_TO_NICE_UNIT(af.present_pages),
70                 af.swapped_pages,
71                 PAGE_TO_NICE(af.swapped_pages),
72                 PAGE_TO_NICE_UNIT(af.swapped_pages),
73                 af.unused_pages,
74                 PAGE_TO_NICE(af.unused_pages),
75                 PAGE_TO_NICE_UNIT(af.unused_pages),
76                 count,
77                 PAGE_TO_NICE(count),
78                 PAGE_TO_NICE_UNIT(count));
79 }
80
81 void print_pid_stats(struct pageframe *pf, struct process *process_list)
82 {
83         struct process *ps;
84         struct maps *map;
85         long int swapped, present;
86
87         printf("   in ram   swapped    pid name\n");
88
89         list_for_each_entry(ps, &process_list->list, list) {
90                 swapped = present = 0;
91
92                 if (ps->maps)
93                         list_for_each_entry(map, &ps->maps->list, list) {
94                                 present += map->pages_present;
95                                 swapped += map->pages_swapped;
96                         }
97
98                 if ((swapped + present) == 0)
99                         continue;
100
101                 printf("% 6lld %sB % 6lld %sB % 5d %s",
102                         PAGE_TO_NICE(present), PAGE_TO_NICE_UNIT(present),
103                         PAGE_TO_NICE(swapped), PAGE_TO_NICE_UNIT(swapped),
104                         ps->pid, ps->name);
105         }
106 }