diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-03-26 20:16:22 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-04-02 15:27:55 -0400 |
commit | 5f4d3f8816461300ce54505c9117bf85b3044aa0 (patch) | |
tree | b69a6f22792480ab1ee02c67e5f8a650d66f208d /tools | |
parent | 7e5e1b1404c30db5f6bc3f5203b6c21c1d244f99 (diff) |
perf report: Add progress bars
For when we are processing the events and inserting the entries in the
browser.
Experimentation here: naming "ui_something" we may be treading into
creating a TUI/GUI set of routines that can then be implemented in terms
of multiple backends.
Also the time it takes for adding things to the "browser" takes, visually
(I guess I should do some profiling here ;-) ), more time than for
processing the events...
That means we probably need to create a custom hist_entry browser, so
that we reuse the structures we have in place instead of duplicating
them in newt.
But progress was made and at least we can see something while long files
are being loaded, that must be one of UI 101 bullet points :-)
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-report.c | 7 | ||||
-rw-r--r-- | tools/perf/util/debug.h | 16 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 5 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 2 | ||||
-rw-r--r-- | tools/perf/util/newt.c | 103 | ||||
-rw-r--r-- | tools/perf/util/session.c | 6 | ||||
-rw-r--r-- | tools/perf/util/session.h | 12 |
7 files changed, 119 insertions, 32 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6ab16980dd66..381918515a5c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -303,13 +303,14 @@ static int __cmd_report(void) | |||
303 | next = rb_first(&session->stats_by_id); | 303 | next = rb_first(&session->stats_by_id); |
304 | while (next) { | 304 | while (next) { |
305 | struct event_stat_id *stats; | 305 | struct event_stat_id *stats; |
306 | u64 nr_hists; | ||
306 | 307 | ||
307 | stats = rb_entry(next, struct event_stat_id, rb_node); | 308 | stats = rb_entry(next, struct event_stat_id, rb_node); |
308 | perf_session__collapse_resort(&stats->hists); | 309 | perf_session__collapse_resort(&stats->hists); |
309 | perf_session__output_resort(&stats->hists, stats->stats.total); | 310 | nr_hists = perf_session__output_resort(&stats->hists, |
310 | 311 | stats->stats.total); | |
311 | if (use_browser) | 312 | if (use_browser) |
312 | perf_session__browse_hists(&stats->hists, | 313 | perf_session__browse_hists(&stats->hists, nr_hists, |
313 | stats->stats.total, help); | 314 | stats->stats.total, help); |
314 | else { | 315 | else { |
315 | if (rb_first(&session->stats_by_id) == | 316 | if (rb_first(&session->stats_by_id) == |
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 0172edf3f153..5cb0a1b1401a 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
@@ -10,13 +10,29 @@ extern int dump_trace; | |||
10 | int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); | 10 | int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); |
11 | void trace_event(event_t *event); | 11 | void trace_event(event_t *event); |
12 | 12 | ||
13 | struct ui_progress; | ||
14 | |||
13 | #ifdef NO_NEWT_SUPPORT | 15 | #ifdef NO_NEWT_SUPPORT |
14 | static inline int browser__show_help(const char *format __used, va_list ap __used) | 16 | static inline int browser__show_help(const char *format __used, va_list ap __used) |
15 | { | 17 | { |
16 | return 0; | 18 | return 0; |
17 | } | 19 | } |
20 | |||
21 | static inline struct ui_progress *ui_progress__new(const char *title __used, | ||
22 | u64 total __used) | ||
23 | { | ||
24 | return (struct ui_progress *)1; | ||
25 | } | ||
26 | |||
27 | static inline void ui_progress__update(struct ui_progress *self __used, | ||
28 | u64 curr __used) {} | ||
29 | |||
30 | static inline void ui_progress__delete(struct ui_progress *self __used) {} | ||
18 | #else | 31 | #else |
19 | int browser__show_help(const char *format, va_list ap); | 32 | int browser__show_help(const char *format, va_list ap); |
33 | struct ui_progress *ui_progress__new(const char *title, u64 total); | ||
34 | void ui_progress__update(struct ui_progress *self, u64 curr); | ||
35 | void ui_progress__delete(struct ui_progress *self); | ||
20 | #endif | 36 | #endif |
21 | 37 | ||
22 | #endif /* __PERF_DEBUG_H */ | 38 | #endif /* __PERF_DEBUG_H */ |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index de3190102cc8..a46d09332462 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -185,12 +185,13 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root, | |||
185 | rb_insert_color(&he->rb_node, root); | 185 | rb_insert_color(&he->rb_node, root); |
186 | } | 186 | } |
187 | 187 | ||
188 | void perf_session__output_resort(struct rb_root *hists, u64 total_samples) | 188 | u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) |
189 | { | 189 | { |
190 | struct rb_root tmp; | 190 | struct rb_root tmp; |
191 | struct rb_node *next; | 191 | struct rb_node *next; |
192 | struct hist_entry *n; | 192 | struct hist_entry *n; |
193 | u64 min_callchain_hits; | 193 | u64 min_callchain_hits; |
194 | u64 nr_hists = 0; | ||
194 | 195 | ||
195 | min_callchain_hits = | 196 | min_callchain_hits = |
196 | total_samples * (callchain_param.min_percent / 100); | 197 | total_samples * (callchain_param.min_percent / 100); |
@@ -205,9 +206,11 @@ void perf_session__output_resort(struct rb_root *hists, u64 total_samples) | |||
205 | rb_erase(&n->rb_node, hists); | 206 | rb_erase(&n->rb_node, hists); |
206 | perf_session__insert_output_hist_entry(&tmp, n, | 207 | perf_session__insert_output_hist_entry(&tmp, n, |
207 | min_callchain_hits); | 208 | min_callchain_hits); |
209 | ++nr_hists; | ||
208 | } | 210 | } |
209 | 211 | ||
210 | *hists = tmp; | 212 | *hists = tmp; |
213 | return nr_hists; | ||
211 | } | 214 | } |
212 | 215 | ||
213 | static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) | 216 | static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index fe366ce5db45..da6a8c1320fa 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -25,7 +25,7 @@ size_t hist_entry__fprintf(struct hist_entry *self, | |||
25 | u64 session_total); | 25 | u64 session_total); |
26 | void hist_entry__free(struct hist_entry *); | 26 | void hist_entry__free(struct hist_entry *); |
27 | 27 | ||
28 | void perf_session__output_resort(struct rb_root *hists, u64 total_samples); | 28 | u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples); |
29 | void perf_session__collapse_resort(struct rb_root *hists); | 29 | void perf_session__collapse_resort(struct rb_root *hists); |
30 | size_t perf_session__fprintf_hists(struct rb_root *hists, | 30 | size_t perf_session__fprintf_hists(struct rb_root *hists, |
31 | struct perf_session *pair, | 31 | struct perf_session *pair, |
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index e99bcc8d1939..b0210ae5b93c 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c | |||
@@ -12,6 +12,72 @@ | |||
12 | #include "sort.h" | 12 | #include "sort.h" |
13 | #include "symbol.h" | 13 | #include "symbol.h" |
14 | 14 | ||
15 | struct ui_progress { | ||
16 | newtComponent form, scale; | ||
17 | }; | ||
18 | |||
19 | struct ui_progress *ui_progress__new(const char *title, u64 total) | ||
20 | { | ||
21 | struct ui_progress *self = malloc(sizeof(*self)); | ||
22 | |||
23 | if (self != NULL) { | ||
24 | int cols; | ||
25 | newtGetScreenSize(&cols, NULL); | ||
26 | cols -= 4; | ||
27 | newtCenteredWindow(cols, 1, title); | ||
28 | self->form = newtForm(NULL, NULL, 0); | ||
29 | if (self->form == NULL) | ||
30 | goto out_free_self; | ||
31 | self->scale = newtScale(0, 0, cols, total); | ||
32 | if (self->scale == NULL) | ||
33 | goto out_free_form; | ||
34 | newtFormAddComponents(self->form, self->scale, NULL); | ||
35 | newtRefresh(); | ||
36 | } | ||
37 | |||
38 | return self; | ||
39 | |||
40 | out_free_form: | ||
41 | newtFormDestroy(self->form); | ||
42 | out_free_self: | ||
43 | free(self); | ||
44 | return NULL; | ||
45 | } | ||
46 | |||
47 | void ui_progress__update(struct ui_progress *self, u64 curr) | ||
48 | { | ||
49 | newtScaleSet(self->scale, curr); | ||
50 | newtRefresh(); | ||
51 | } | ||
52 | |||
53 | void ui_progress__delete(struct ui_progress *self) | ||
54 | { | ||
55 | newtFormDestroy(self->form); | ||
56 | newtPopWindow(); | ||
57 | free(self); | ||
58 | } | ||
59 | |||
60 | static char browser__last_msg[1024]; | ||
61 | |||
62 | int browser__show_help(const char *format, va_list ap) | ||
63 | { | ||
64 | int ret; | ||
65 | static int backlog; | ||
66 | |||
67 | ret = vsnprintf(browser__last_msg + backlog, | ||
68 | sizeof(browser__last_msg) - backlog, format, ap); | ||
69 | backlog += ret; | ||
70 | |||
71 | if (browser__last_msg[backlog - 1] == '\n') { | ||
72 | newtPopHelpLine(); | ||
73 | newtPushHelpLine(browser__last_msg); | ||
74 | newtRefresh(); | ||
75 | backlog = 0; | ||
76 | } | ||
77 | |||
78 | return ret; | ||
79 | } | ||
80 | |||
15 | static void newt_form__set_exit_keys(newtComponent self) | 81 | static void newt_form__set_exit_keys(newtComponent self) |
16 | { | 82 | { |
17 | newtFormAddHotKey(self, NEWT_KEY_ESCAPE); | 83 | newtFormAddHotKey(self, NEWT_KEY_ESCAPE); |
@@ -364,8 +430,8 @@ static void perf_session__selection(newtComponent self, void *data) | |||
364 | *symbol_ptr = newt__symbol_tree_get_current(self); | 430 | *symbol_ptr = newt__symbol_tree_get_current(self); |
365 | } | 431 | } |
366 | 432 | ||
367 | void perf_session__browse_hists(struct rb_root *hists, u64 session_total, | 433 | int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, |
368 | const char *helpline) | 434 | u64 session_total, const char *helpline) |
369 | { | 435 | { |
370 | struct sort_entry *se; | 436 | struct sort_entry *se; |
371 | struct rb_node *nd; | 437 | struct rb_node *nd; |
@@ -378,6 +444,12 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, | |||
378 | newtComponent form, tree; | 444 | newtComponent form, tree; |
379 | struct newtExitStruct es; | 445 | struct newtExitStruct es; |
380 | const struct map_symbol *selection; | 446 | const struct map_symbol *selection; |
447 | u64 curr_hist = 0; | ||
448 | struct ui_progress *progress; | ||
449 | |||
450 | progress = ui_progress__new("Adding entries to the browser...", nr_hists); | ||
451 | if (progress == NULL) | ||
452 | return -1; | ||
381 | 453 | ||
382 | snprintf(str, sizeof(str), "Samples: %Ld", session_total); | 454 | snprintf(str, sizeof(str), "Samples: %Ld", session_total); |
383 | newtDrawRootText(0, 0, str); | 455 | newtDrawRootText(0, 0, str); |
@@ -419,8 +491,13 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, | |||
419 | max_len = len; | 491 | max_len = len; |
420 | if (symbol_conf.use_callchain) | 492 | if (symbol_conf.use_callchain) |
421 | hist_entry__append_callchain_browser(h, tree, session_total, idx++); | 493 | hist_entry__append_callchain_browser(h, tree, session_total, idx++); |
494 | ++curr_hist; | ||
495 | if (curr_hist % 5) | ||
496 | ui_progress__update(progress, curr_hist); | ||
422 | } | 497 | } |
423 | 498 | ||
499 | ui_progress__delete(progress); | ||
500 | |||
424 | if (max_len > cols) | 501 | if (max_len > cols) |
425 | max_len = cols - 3; | 502 | max_len = cols - 3; |
426 | 503 | ||
@@ -480,27 +557,7 @@ do_annotate: | |||
480 | 557 | ||
481 | newtFormDestroy(form); | 558 | newtFormDestroy(form); |
482 | newtPopWindow(); | 559 | newtPopWindow(); |
483 | } | 560 | return 0; |
484 | |||
485 | static char browser__last_msg[1024]; | ||
486 | |||
487 | int browser__show_help(const char *format, va_list ap) | ||
488 | { | ||
489 | int ret; | ||
490 | static int backlog; | ||
491 | |||
492 | ret = vsnprintf(browser__last_msg + backlog, | ||
493 | sizeof(browser__last_msg) - backlog, format, ap); | ||
494 | backlog += ret; | ||
495 | |||
496 | if (browser__last_msg[backlog - 1] == '\n') { | ||
497 | newtPopHelpLine(); | ||
498 | newtPushHelpLine(browser__last_msg); | ||
499 | newtRefresh(); | ||
500 | backlog = 0; | ||
501 | } | ||
502 | |||
503 | return ret; | ||
504 | } | 561 | } |
505 | 562 | ||
506 | void setup_browser(void) | 563 | void setup_browser(void) |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 76b4ac689df9..32765cdca058 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -397,6 +397,10 @@ int __perf_session__process_events(struct perf_session *self, | |||
397 | event_t *event; | 397 | event_t *event; |
398 | uint32_t size; | 398 | uint32_t size; |
399 | char *buf; | 399 | char *buf; |
400 | struct ui_progress *progress = ui_progress__new("Processing events...", | ||
401 | self->size); | ||
402 | if (progress == NULL) | ||
403 | return -1; | ||
400 | 404 | ||
401 | perf_event_ops__fill_defaults(ops); | 405 | perf_event_ops__fill_defaults(ops); |
402 | 406 | ||
@@ -425,6 +429,7 @@ remap: | |||
425 | 429 | ||
426 | more: | 430 | more: |
427 | event = (event_t *)(buf + head); | 431 | event = (event_t *)(buf + head); |
432 | ui_progress__update(progress, offset); | ||
428 | 433 | ||
429 | if (self->header.needs_swap) | 434 | if (self->header.needs_swap) |
430 | perf_event_header__bswap(&event->header); | 435 | perf_event_header__bswap(&event->header); |
@@ -475,6 +480,7 @@ more: | |||
475 | done: | 480 | done: |
476 | err = 0; | 481 | err = 0; |
477 | out_err: | 482 | out_err: |
483 | ui_progress__delete(progress); | ||
478 | return err; | 484 | return err; |
479 | } | 485 | } |
480 | 486 | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 631f8157fc17..6a15daeda577 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -88,11 +88,15 @@ static inline struct map * | |||
88 | } | 88 | } |
89 | 89 | ||
90 | #ifdef NO_NEWT_SUPPORT | 90 | #ifdef NO_NEWT_SUPPORT |
91 | static inline void perf_session__browse_hists(struct rb_root *hists __used, | 91 | static inline int perf_session__browse_hists(struct rb_root *hists __used, |
92 | u64 nr_hists __used, | ||
92 | u64 session_total __used, | 93 | u64 session_total __used, |
93 | const char *helpline __used) {} | 94 | const char *helpline __used) |
95 | { | ||
96 | return 0; | ||
97 | } | ||
94 | #else | 98 | #else |
95 | void perf_session__browse_hists(struct rb_root *hists, u64 session_total, | 99 | int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, |
96 | const char *helpline); | 100 | u64 session_total, const char *helpline); |
97 | #endif | 101 | #endif |
98 | #endif /* __PERF_SESSION_H */ | 102 | #endif /* __PERF_SESSION_H */ |