OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 2 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
3 * Distributed under the terms of the GNU General Public License v2 | 3 * Distributed under the terms of the GNU General Public License v2 |
4 */ | 4 */ |
5 | 5 |
6 #include <ncurses.h> | 6 #include <ncurses.h> |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <time.h> | |
11 #include <unistd.h> | 10 #include <unistd.h> |
12 | 11 |
| 12 #include <debug.h> |
| 13 #include <eprintf.h> |
13 #include <style.h> | 14 #include <style.h> |
14 | 15 |
15 #include "ktop.h" | 16 #include "ktop.h" |
16 #include "plot.h" | 17 #include "plot.h" |
| 18 #include "reduce.h" |
17 #include "syscall.h" | 19 #include "syscall.h" |
18 #include "tickcounter.h" | 20 #include "tickcounter.h" |
19 | 21 |
20 enum { HELP_ROW = 0, | 22 enum { HELP_ROW = 0, |
21 HELP_COL = 0, | 23 HELP_COL = 0, |
| 24 TOP_ROW = HELP_ROW + 1, |
| 25 TOP_COL = 0, |
22 RW_ROW = HELP_ROW + 1, | 26 RW_ROW = HELP_ROW + 1, |
23 RW_COL = 0, | 27 RW_COL = 0, |
24 » PID_ROW = RW_ROW + 6, | 28 » PID_ROW = TOP_ROW + 12, |
25 PID_COL = 0, | 29 PID_COL = 0, |
26 TOP_ROW = RW_ROW + 6, | |
27 TOP_COL = 70, | |
28 SELF_ROW = HELP_ROW + 1, | 30 SELF_ROW = HELP_ROW + 1, |
29 » SELF_COL = 40 }; | 31 » SELF_COL = 0, |
| 32 » MAX_ROW = SELF_ROW, |
| 33 » MAX_COL = SELF_COL + 40, |
| 34 }; |
30 | 35 |
31 typedef struct Top_ten_s { | 36 typedef struct Top_ten_s { |
32 int syscall; | 37 int syscall; |
33 int value; | 38 int value; |
34 } Top_ten_s; | 39 } Top_ten_s; |
35 | 40 |
| 41 typedef struct Display_call_s { |
| 42 char *name; |
| 43 int index; |
| 44 } Display_call_s; |
| 45 |
36 bool Plot = FALSE; | 46 bool Plot = FALSE; |
37 | 47 |
38 static u64 A[NUM_SYS_CALLS]; | |
39 static u64 B[NUM_SYS_CALLS]; | |
40 static u64 *Old = A; | |
41 static u64 *New = B; | |
42 static int Delta[NUM_SYS_CALLS]; | |
43 static Top_ten_s Top_ten[10]; | 48 static Top_ten_s Top_ten[10]; |
44 | 49 |
45 static TickCounter_s TotalDelta; | |
46 static graph_s TotalGraph = {{0, 0}, {{0, 10}, {60, 20}}}; | 50 static graph_s TotalGraph = {{0, 0}, {{0, 10}, {60, 20}}}; |
47 | 51 |
| 52 Display_call_s Display_call[] = { |
| 53 { "read: ", sys_read }, |
| 54 { "write: ", sys_write }, |
| 55 { "pread: ", sys_pread64 }, |
| 56 { "pwrite:", sys_pwrite64 }, |
| 57 { "sync: ", sys_sync }, |
| 58 { "fsync: ", sys_fsync }, |
| 59 { "open: ", sys_open }, |
| 60 { "close: ", sys_close }, |
| 61 { "creat: ", sys_creat }, |
| 62 { "unlink:", sys_unlink }, |
| 63 { "stat: ", sys_stat64 }, |
| 64 { "fstat: ", sys_fstat64 }, |
| 65 { "fork: ", ptregs_fork }, |
| 66 { "vfork: ", ptregs_vfork }, |
| 67 { NULL, 0 }}; |
| 68 |
48 static void help(void) | 69 static void help(void) |
49 { | 70 { |
50 mvprintw(HELP_ROW, HELP_COL, | 71 mvprintw(HELP_ROW, HELP_COL, |
51 » » "q - quit c - clear"); | 72 » » "q quit c clear k kernel ops i internal ops f file ops " |
| 73 » » " < shorter > longer %d.%.3d", |
| 74 » » Sleep.tv_sec, Sleep.tv_nsec / A_MILLION); |
52 } | 75 } |
53 | 76 |
54 char *getpidname(int pid) | 77 static void file_system(void) |
55 { | 78 { |
56 » char path[100]; | 79 » Display_call_s *d; |
57 » static char name[4096]; | 80 » int row = RW_ROW; |
58 » int rc; | |
59 | 81 |
60 » snprintf(path, sizeof(path), "/proc/%d/exe", pid); | 82 » mvprintw(row, RW_COL, " total hits/sec"); |
61 » rc = readlink(path, name, sizeof(name)); | |
62 » if (rc == -1) return NULL; | |
63 » name[rc] = '\0'; | |
64 » | |
65 » return name; //strdup(name); | |
66 } | |
67 | 83 |
68 static void read_write(void) | 84 » for (d = Display_call; d->name; d++) { |
69 { | 85 » » mvprintw(++row, RW_COL, "%s %10lld %10d", |
70 » mvprintw(RW_ROW, RW_COL, " total hits/sec"); | 86 » » » d->name, New[d->index], Delta[d->index]); |
71 » mvprintw(RW_ROW+1, RW_COL, "read: %10lld %10d", | 87 » } |
72 » » New[sys_read], Delta[sys_read]); | |
73 » mvprintw(RW_ROW+2, RW_COL, "write: %10lld %10d", | |
74 » » New[sys_write], Delta[sys_write]); | |
75 » mvprintw(RW_ROW+3, RW_COL, "pread: %10lld %10d", | |
76 » » New[sys_pread64], Delta[sys_pread64]); | |
77 » mvprintw(RW_ROW+4, RW_COL, "pwrite:%10lld %10d", | |
78 » » New[sys_pwrite64], Delta[sys_pwrite64]); | |
79 } | 88 } |
80 | 89 |
81 static void self(void) | 90 static void self(void) |
82 { | 91 { |
83 » mvprintw(SELF_ROW, SELF_COL, "Skipped: %8lld", MyPidCount); | 92 » static double max = 0; |
84 » mvprintw(SELF_ROW+1, SELF_COL, "Slept: %8lld", Slept); | 93 » double avg; |
| 94 |
| 95 » mvprintw(SELF_ROW, SELF_COL, "Skipped: %12lld", MyPidCount); |
| 96 » mvprintw(SELF_ROW+1, SELF_COL, "Slept: %12lld", Slept); |
| 97 » mvprintw(SELF_ROW+2, SELF_COL, "Tick: %12zd", sizeof(TickCounter_
s)); |
| 98 » mvprintw(SELF_ROW+3, SELF_COL, "No_enter: %12lld", No_enter); |
| 99 » mvprintw(SELF_ROW+4, SELF_COL, "Found: %12lld", Found); |
| 100 » mvprintw(SELF_ROW+5, SELF_COL, "Out_of_order:%12lld", Out_of_order); |
| 101 » mvprintw(SELF_ROW+6, SELF_COL, "No_start: %12lld", No_start); |
| 102 » if (1) { |
| 103 » » mvprintw(SELF_ROW+7, SELF_COL, "Ticks: %12lld", Pidcall_ti
ck); |
| 104 » » if (PidcallRecord == 0) return; |
| 105 » » avg = (double)PidcallIterations / (double)PidcallRecord; |
| 106 » » PidcallIterations = PidcallRecord = 0; |
| 107 » » if (avg > max) max =avg; |
| 108 » » mvprintw(SELF_ROW+8, SELF_COL, "Avg: %g", avg); |
| 109 » » mvprintw(SELF_ROW+9, SELF_COL, "Max: %g", max); |
| 110 » } |
85 } | 111 } |
86 | 112 |
87 static void top_pid(void) | 113 static void top_pid(void) |
88 { | 114 { |
89 int max = 0; | 115 int max = 0; |
90 int pid = 0; | 116 int pid = 0; |
91 int i; | 117 int i; |
92 | 118 |
93 for (i = 0; i < MAX_PID; i++) { | 119 for (i = 0; i < MAX_PID; i++) { |
94 if (Pid[i] > max) { | 120 if (Pid[i] > max) { |
95 max = Pid[i]; | 121 max = Pid[i]; |
96 pid = i; | 122 pid = i; |
97 } | 123 } |
98 } | 124 } |
99 » mvprintw(TOP_ROW, TOP_COL, "max: %d %d", pid, max); | 125 » mvprintw(MAX_ROW, MAX_COL, "max: %d %d", pid, max); |
| 126 } |
| 127 |
| 128 static char *getpidname(int pid) |
| 129 { |
| 130 » char path[100]; |
| 131 » static char name[4096]; |
| 132 » int rc; |
| 133 |
| 134 » snprintf(path, sizeof(path), "/proc/%d/exe", pid); |
| 135 » rc = readlink(path, name, sizeof(name)); |
| 136 » if (rc == -1) { |
| 137 » » return NULL; |
| 138 » } |
| 139 » if (rc == sizeof(name)) { |
| 140 » » fatal("pid name too long"); |
| 141 » } |
| 142 » name[rc] = '\0'; |
| 143 |
| 144 » return strdup(name); |
100 } | 145 } |
101 | 146 |
102 static void display_pidcall(void) | 147 static void display_pidcall(void) |
103 { | 148 { |
104 » Pidcall_s *p = Pidcall; | 149 » Pidcall_s *pc; |
105 int row = PID_ROW; | 150 int row = PID_ROW; |
106 int col = PID_COL; | 151 int col = PID_COL; |
107 int pid; | 152 int pid; |
108 int i; | 153 int i; |
109 | 154 |
110 » mvprintw(row++, col, " pid total"); | 155 » mvprintw(row++, col, "%3d pid count duration", Num_rank); |
111 » for (i = 0; i < 25; i++, p++, row++) { | 156 » for (i = 0; i < 25 && i < Num_rank; i++, row++) { |
112 » » if (p == Pidnext) return; | 157 » » pc = Rank_pidcall[i]; |
113 » » pid = get_pid(p->pidcall); | 158 » » pid = get_pid(pc->pidcall); |
114 » » mvprintw(row, col, "%3d. %5d %6d %-22.22s %-28.28s", | 159 » » if (!pc->name) { |
115 » » » i+1, pid, p->count, | 160 » » » pc->name = getpidname(pid); |
116 » » » Syscall[get_call(p->pidcall)], | 161 » » » if (!pc->name) { |
117 » » » getpidname(pid)); | 162 » » » » pc->name = strdup("(unknown)"); |
| 163 » » » } |
| 164 » » } |
| 165 » » mvprintw(row, col, "%3d. %5d %6d %10lld %-22.22s %-28.28s", |
| 166 » » » i + 1, pid, pc->save.count, |
| 167 » » » pc->save.count ? pc->save.time / pc->save.count : 0LL, |
| 168 » » » Syscall[get_call(pc->pidcall)], |
| 169 » » » pc->name); |
| 170 » » mvprintw(row, col+80, "%8lx %8lx %8lx", |
| 171 » » » pc->arg[0], pc->arg[1], pc->arg[2]); |
118 } | 172 } |
119 } | 173 } |
120 | 174 |
121 static void display_top_ten(void) | 175 static void display_top_ten(void) |
122 { | 176 { |
123 » int row = TOP_ROW + 1; | 177 » int row = TOP_ROW; |
124 int i; | 178 int i; |
125 | 179 |
126 mvprintw(row++, TOP_COL, " hits sys_call"); | 180 mvprintw(row++, TOP_COL, " hits sys_call"); |
127 for (i = 0; i < 10; i++, row++) { | 181 for (i = 0; i < 10; i++, row++) { |
128 if (Top_ten[i].value == 0) return; | 182 if (Top_ten[i].value == 0) return; |
129 mvprintw(row, TOP_COL, "%8d %-22.22s", | 183 mvprintw(row, TOP_COL, "%8d %-22.22s", |
130 Top_ten[i].value, Syscall[Top_ten[i].syscall]); | 184 Top_ten[i].value, Syscall[Top_ten[i].syscall]); |
131 } | 185 } |
132 } | 186 } |
133 | 187 |
(...skipping 19 matching lines...) Expand all Loading... |
153 | 207 |
154 zero(Top_ten); | 208 zero(Top_ten); |
155 for (i = 0; i < NUM_SYS_CALLS; i++) { | 209 for (i = 0; i < NUM_SYS_CALLS; i++) { |
156 x = Delta[i]; | 210 x = Delta[i]; |
157 if (x > Top_ten[9].value) { | 211 if (x > Top_ten[9].value) { |
158 top_ten_insert(x, i); | 212 top_ten_insert(x, i); |
159 } | 213 } |
160 } | 214 } |
161 } | 215 } |
162 | 216 |
163 static void delta(void) | |
164 { | |
165 u64 *tmp; | |
166 int sum; | |
167 int i; | |
168 | |
169 tmp = Old; | |
170 Old = New; | |
171 New = tmp; | |
172 | |
173 memmove(New, Syscall_count, sizeof(Syscall_count)); | |
174 | |
175 sum = 0; | |
176 for (i = 0; i < NUM_SYS_CALLS; i++) { | |
177 Delta[i] = New[i] - Old[i]; | |
178 sum += Delta[i]; | |
179 } | |
180 tick(&TotalDelta, sum); | |
181 top_ten(); | |
182 } | |
183 | |
184 static void graph_total(void) | 217 static void graph_total(void) |
185 { | 218 { |
186 vector_s v = new_vector(WHEEL_SIZE); | 219 vector_s v = new_vector(WHEEL_SIZE); |
187 int i; | 220 int i; |
188 int j; | 221 int j; |
189 | 222 |
190 j = TotalDelta.itick; | 223 j = TotalDelta.itick; |
191 for (i = 0; i < WHEEL_SIZE; i++) { | 224 for (i = 0; i < WHEEL_SIZE; i++) { |
192 v.p[i].x = j; | 225 v.p[i].x = j; |
193 v.p[i].y = TotalDelta.tick[j]; | 226 v.p[i].y = TotalDelta.tick[j]; |
194 if (++j == WHEEL_SIZE) { | 227 if (++j == WHEEL_SIZE) { |
195 j = 0; | 228 j = 0; |
196 } | 229 } |
197 } | 230 } |
198 vplot(&TotalGraph, v, '*'); | 231 vplot(&TotalGraph, v, '*'); |
199 } | 232 } |
200 | 233 |
201 static void init(void) | 234 void init_display(void) |
202 { | 235 { |
203 initscr(); | 236 initscr(); |
204 cbreak(); | 237 cbreak(); |
205 noecho(); | 238 noecho(); |
206 nonl(); | 239 nonl(); |
207 idlok(stdscr, TRUE); | 240 idlok(stdscr, TRUE); |
208 keypad(stdscr, TRUE); | 241 keypad(stdscr, TRUE); |
209 | 242 |
210 init_counter(&TotalDelta, 1); | 243 init_counter(&TotalDelta, 1); |
211 } | 244 } |
212 | 245 |
213 void *display(void *arg) | 246 void kernel_display(void) |
214 { | 247 { |
215 » struct timespec sleep = { 1, 0 }; | 248 » clear(); |
216 | 249 » top_ten(); |
217 » ignore_pid(gettid()); | 250 » if (Plot) { |
218 » init(); | 251 » » clear(); |
219 » for (;;) { | 252 » » graph_total(); |
220 » » if (Command) { | 253 » } else { |
221 » » » return NULL; | 254 » » display_pidcall(); |
222 » » } | 255 » » display_top_ten(); |
223 » » delta(); | |
224 » » if (Plot) { | |
225 » » » clear(); | |
226 » » » graph_total(); | |
227 » » } else { | |
228 » » » top_pid(); | |
229 » » » display_pidcall(); | |
230 » » » display_top_ten(); | |
231 » » } | |
232 » » help(); | |
233 » » read_write(); | |
234 » » self(); | |
235 » » refresh(); | |
236 » » nanosleep(&sleep, NULL); | |
237 } | 256 } |
| 257 help(); |
| 258 refresh(); |
238 } | 259 } |
239 | 260 |
240 void clear_display(void) | 261 void internal_display(void) |
241 { | 262 { |
242 » zero(A); | 263 » clear(); |
243 » zero(B); | 264 » help(); |
244 » zero(Pid); | 265 » self(); |
245 » zero(Syscall_count); | 266 » top_pid(); |
246 » MyPidCount = 0; | 267 » refresh(); |
247 » Slept = 0; | 268 } |
| 269 |
| 270 void file_system_display(void) |
| 271 { |
| 272 » clear(); |
| 273 » help(); |
| 274 » file_system(); |
| 275 » refresh(); |
248 } | 276 } |
249 | 277 |
250 void cleanup_display(void) | 278 void cleanup_display(void) |
251 { | 279 { |
252 endwin(); | 280 endwin(); |
253 } | 281 } |
OLD | NEW |