aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-08-09 14:30:40 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-08-10 15:11:42 -0400
commit92221162875ec48913d3f9710046e48d599c9cf2 (patch)
tree891aeb2c50777478aaf0cd5a2537db65f6b7d2ae
parent1e6dd077a880ba5570beb690523b7a78a91a7615 (diff)
perf annotate: Sort by hottest lines in the TUI
Right now it will just sort and position at the hottest line, i.e. the one where more samples were taken. It will be at the center of the screen and later TAB/shift-TAB will cycle thru the hottest lines. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/util/hist.c13
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/ui/browsers/annotate.c153
4 files changed, 125 insertions, 46 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index fd20670ce98..1478dc64bf1 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -285,7 +285,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he)
285 LIST_HEAD(head); 285 LIST_HEAD(head);
286 struct objdump_line *pos, *n; 286 struct objdump_line *pos, *n;
287 287
288 if (hist_entry__annotate(he, &head) < 0) 288 if (hist_entry__annotate(he, &head, 0) < 0)
289 return -1; 289 return -1;
290 290
291 if (full_paths) 291 if (full_paths)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 62ec9b0e4b9..be22ae6ef05 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -983,9 +983,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
983 return 0; 983 return 0;
984} 984}
985 985
986static struct objdump_line *objdump_line__new(s64 offset, char *line) 986static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
987{ 987{
988 struct objdump_line *self = malloc(sizeof(*self)); 988 struct objdump_line *self = malloc(sizeof(*self) + privsize);
989 989
990 if (self != NULL) { 990 if (self != NULL) {
991 self->offset = offset; 991 self->offset = offset;
@@ -1017,7 +1017,7 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
1017} 1017}
1018 1018
1019static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file, 1019static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
1020 struct list_head *head) 1020 struct list_head *head, size_t privsize)
1021{ 1021{
1022 struct symbol *sym = self->ms.sym; 1022 struct symbol *sym = self->ms.sym;
1023 struct objdump_line *objdump_line; 1023 struct objdump_line *objdump_line;
@@ -1068,7 +1068,7 @@ static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
1068 offset = -1; 1068 offset = -1;
1069 } 1069 }
1070 1070
1071 objdump_line = objdump_line__new(offset, line); 1071 objdump_line = objdump_line__new(offset, line, privsize);
1072 if (objdump_line == NULL) { 1072 if (objdump_line == NULL) {
1073 free(line); 1073 free(line);
1074 return -1; 1074 return -1;
@@ -1078,7 +1078,8 @@ static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
1078 return 0; 1078 return 0;
1079} 1079}
1080 1080
1081int hist_entry__annotate(struct hist_entry *self, struct list_head *head) 1081int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1082 size_t privsize)
1082{ 1083{
1083 struct symbol *sym = self->ms.sym; 1084 struct symbol *sym = self->ms.sym;
1084 struct map *map = self->ms.map; 1085 struct map *map = self->ms.map;
@@ -1143,7 +1144,7 @@ fallback:
1143 goto out_free_filename; 1144 goto out_free_filename;
1144 1145
1145 while (!feof(file)) 1146 while (!feof(file))
1146 if (hist_entry__parse_objdump_line(self, file, head) < 0) 1147 if (hist_entry__parse_objdump_line(self, file, head, privsize) < 0)
1147 break; 1148 break;
1148 1149
1149 pclose(file); 1150 pclose(file);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 65a48db46a2..587d375d343 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -101,7 +101,8 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
101 bool show_displacement, FILE *fp); 101 bool show_displacement, FILE *fp);
102 102
103int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip); 103int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip);
104int hist_entry__annotate(struct hist_entry *self, struct list_head *head); 104int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
105 size_t privsize);
105 106
106void hists__filter_by_dso(struct hists *self, const struct dso *dso); 107void hists__filter_by_dso(struct hists *self, const struct dso *dso);
107void hists__filter_by_thread(struct hists *self, const struct thread *thread); 108void hists__filter_by_thread(struct hists *self, const struct thread *thread);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 5b01df633f9..763592b09d7 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -14,6 +14,23 @@ static void ui__error_window(const char *fmt, ...)
14 va_end(ap); 14 va_end(ap);
15} 15}
16 16
17struct annotate_browser {
18 struct ui_browser b;
19 struct rb_root entries;
20};
21
22struct objdump_line_rb_node {
23 struct rb_node rb_node;
24 double percent;
25 u32 idx;
26};
27
28static inline
29struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)
30{
31 return (struct objdump_line_rb_node *)(self + 1);
32}
33
17static void annotate_browser__write(struct ui_browser *self, void *entry, int row) 34static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
18{ 35{
19 struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); 36 struct objdump_line *ol = rb_entry(entry, struct objdump_line, node);
@@ -21,17 +38,41 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
21 int width = self->width; 38 int width = self->width;
22 39
23 if (ol->offset != -1) { 40 if (ol->offset != -1) {
24 struct hist_entry *he = self->priv; 41 struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
25 struct symbol *sym = he->ms.sym; 42 int color = ui_browser__percent_color(olrb->percent, current_entry);
26 int len = he->ms.sym->end - he->ms.sym->start; 43 SLsmg_set_color(color);
44 slsmg_printf(" %7.2f ", olrb->percent);
45 if (!current_entry)
46 SLsmg_set_color(HE_COLORSET_CODE);
47 } else {
48 int color = ui_browser__percent_color(0, current_entry);
49 SLsmg_set_color(color);
50 slsmg_write_nstring(" ", 9);
51 }
52
53 SLsmg_write_char(':');
54 slsmg_write_nstring(" ", 8);
55 if (!*ol->line)
56 slsmg_write_nstring(" ", width - 18);
57 else
58 slsmg_write_nstring(ol->line, width - 18);
59}
60
61static double objdump_line__calc_percent(struct objdump_line *self,
62 struct list_head *head,
63 struct symbol *sym)
64{
65 double percent = 0.0;
66
67 if (self->offset != -1) {
68 int len = sym->end - sym->start;
27 unsigned int hits = 0; 69 unsigned int hits = 0;
28 double percent = 0.0;
29 int color;
30 struct sym_priv *priv = symbol__priv(sym); 70 struct sym_priv *priv = symbol__priv(sym);
31 struct sym_ext *sym_ext = priv->ext; 71 struct sym_ext *sym_ext = priv->ext;
32 struct sym_hist *h = priv->hist; 72 struct sym_hist *h = priv->hist;
33 s64 offset = ol->offset; 73 s64 offset = self->offset;
34 struct objdump_line *next = objdump__get_next_ip_line(self->entries, ol); 74 struct objdump_line *next = objdump__get_next_ip_line(head, self);
75
35 76
36 while (offset < (s64)len && 77 while (offset < (s64)len &&
37 (next == NULL || offset < next->offset)) { 78 (next == NULL || offset < next->offset)) {
@@ -45,37 +86,45 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
45 86
46 if (sym_ext == NULL && h->sum) 87 if (sym_ext == NULL && h->sum)
47 percent = 100.0 * hits / h->sum; 88 percent = 100.0 * hits / h->sum;
48
49 color = ui_browser__percent_color(percent, current_entry);
50 SLsmg_set_color(color);
51 slsmg_printf(" %7.2f ", percent);
52 if (!current_entry)
53 SLsmg_set_color(HE_COLORSET_CODE);
54 } else {
55 int color = ui_browser__percent_color(0, current_entry);
56 SLsmg_set_color(color);
57 slsmg_write_nstring(" ", 9);
58 } 89 }
59 90
60 SLsmg_write_char(':'); 91 return percent;
61 slsmg_write_nstring(" ", 8); 92}
62 if (!*ol->line) 93
63 slsmg_write_nstring(" ", width - 18); 94static void objdump__insert_line(struct rb_root *self,
64 else 95 struct objdump_line_rb_node *line)
65 slsmg_write_nstring(ol->line, width - 18); 96{
97 struct rb_node **p = &self->rb_node;
98 struct rb_node *parent = NULL;
99 struct objdump_line_rb_node *l;
100
101 while (*p != NULL) {
102 parent = *p;
103 l = rb_entry(parent, struct objdump_line_rb_node, rb_node);
104 if (line->percent < l->percent)
105 p = &(*p)->rb_left;
106 else
107 p = &(*p)->rb_right;
108 }
109 rb_link_node(&line->rb_node, parent, p);
110 rb_insert_color(&line->rb_node, self);
66} 111}
67 112
68int hist_entry__tui_annotate(struct hist_entry *self) 113int hist_entry__tui_annotate(struct hist_entry *self)
69{ 114{
70 struct newtExitStruct es; 115 struct newtExitStruct es;
71 struct objdump_line *pos, *n; 116 struct objdump_line *pos, *n;
117 struct objdump_line_rb_node *rbpos;
118 struct rb_node *nd;
72 LIST_HEAD(head); 119 LIST_HEAD(head);
73 struct ui_browser browser = { 120 struct annotate_browser browser = {
74 .entries = &head, 121 .b = {
75 .refresh = ui_browser__list_head_refresh, 122 .entries = &head,
76 .seek = ui_browser__list_head_seek, 123 .refresh = ui_browser__list_head_refresh,
77 .write = annotate_browser__write, 124 .seek = ui_browser__list_head_seek,
78 .priv = self, 125 .write = annotate_browser__write,
126 .priv = self,
127 },
79 }; 128 };
80 int ret; 129 int ret;
81 130
@@ -85,7 +134,7 @@ int hist_entry__tui_annotate(struct hist_entry *self)
85 if (self->ms.map->dso->annotate_warned) 134 if (self->ms.map->dso->annotate_warned)
86 return -1; 135 return -1;
87 136
88 if (hist_entry__annotate(self, &head) < 0) { 137 if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) {
89 ui__error_window(ui_helpline__last_msg); 138 ui__error_window(ui_helpline__last_msg);
90 return -1; 139 return -1;
91 } 140 }
@@ -94,16 +143,44 @@ int hist_entry__tui_annotate(struct hist_entry *self)
94 143
95 list_for_each_entry(pos, &head, node) { 144 list_for_each_entry(pos, &head, node) {
96 size_t line_len = strlen(pos->line); 145 size_t line_len = strlen(pos->line);
97 if (browser.width < line_len) 146 if (browser.b.width < line_len)
98 browser.width = line_len; 147 browser.b.width = line_len;
99 ++browser.nr_entries; 148 rbpos = objdump_line__rb(pos);
149 rbpos->idx = browser.b.nr_entries++;
150 rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym);
151 if (rbpos->percent < 0.01)
152 continue;
153 objdump__insert_line(&browser.entries, rbpos);
154 }
155
156 /*
157 * Position the browser at the hottest line.
158 */
159 nd = rb_last(&browser.entries);
160 if (nd != NULL) {
161 unsigned back;
162
163 ui_browser__refresh_dimensions(&browser.b);
164 back = browser.b.height / 2;
165 rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node);
166 pos = ((struct objdump_line *)rbpos) - 1;
167 browser.b.top_idx = browser.b.index = rbpos->idx;
168
169 while (browser.b.top_idx != 0 && back != 0) {
170 pos = list_entry(pos->node.prev, struct objdump_line, node);
171
172 --browser.b.top_idx;
173 --back;
174 }
175
176 browser.b.top = pos;
100 } 177 }
101 178
102 browser.width += 18; /* Percentage */ 179 browser.b.width += 18; /* Percentage */
103 ui_browser__show(&browser, self->ms.sym->name); 180 ui_browser__show(&browser.b, self->ms.sym->name);
104 newtFormAddHotKey(browser.form, ' '); 181 newtFormAddHotKey(browser.b.form, ' ');
105 ret = ui_browser__run(&browser, &es); 182 ret = ui_browser__run(&browser.b, &es);
106 newtFormDestroy(browser.form); 183 newtFormDestroy(browser.b.form);
107 newtPopWindow(); 184 newtPopWindow();
108 list_for_each_entry_safe(pos, n, &head, node) { 185 list_for_each_entry_safe(pos, n, &head, node) {
109 list_del(&pos->node); 186 list_del(&pos->node);