aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-10-22 17:23:23 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-23 01:55:18 -0400
commita4fb581b15949cfd10b64c8af37bc106e95307f3 (patch)
tree6c7606626388485266ef527700524e5ad7ea5a9d /tools/perf/builtin-report.c
parentaf0a6fa46388e1e0c2d1a672aad84f8f6ef0b20b (diff)
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left margin. So depending on the current sort dimension configuration, callchains may appear to be well attached to the first sort dimension column field which is mostly the case, except when the first dimension of sorting is done by comm, because these are right aligned. This patch binds the callchain to the first letter in the first column, whatever type of column it is (dso, comm, symbol). Before: 0.80% perf [k] __lock_acquire __lock_acquire lock_acquire | |--58.33%-- _spin_lock | | | |--28.57%-- inotify_should_send_event | | fsnotify | | __fsnotify_parent After: 0.80% perf [k] __lock_acquire __lock_acquire lock_acquire | |--58.33%-- _spin_lock | | | |--28.57%-- inotify_should_send_event | | fsnotify | | __fsnotify_parent Also, for clarity, we don't put anymore the callchain as is but: - If we have a top level ancestor in the callchain, start it with a first ascii hook. Before: 0.80% perf [kernel] [k] __lock_acquire __lock_acquire lock_acquire | |--58.33%-- _spin_lock | | | |--28.57%-- inotify_should_send_event | | fsnotify [..] [..] After: 0.80% perf [kernel] [k] __lock_acquire | --- __lock_acquire lock_acquire | |--58.33%-- _spin_lock | | | |--28.57%-- inotify_should_send_event | | fsnotify [..] [..] - Otherwise, if we have several top level ancestors, then display these like we did before: 1.69% Xorg | |--21.21%-- vread_hpet | 0x7fffd85b46fc | 0x7fffd85b494d | 0x7f4fafb4e54d | |--15.15%-- exaOffscreenAlloc | |--9.09%-- I830WaitLpRing Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 3d8c52220f1f..72d58421223d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -59,12 +59,28 @@ static struct perf_header *header;
59 59
60static u64 sample_type; 60static u64 sample_type;
61 61
62static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask) 62
63static size_t
64callchain__fprintf_left_margin(FILE *fp, int left_margin)
65{
66 int i;
67 int ret;
68
69 ret = fprintf(fp, " ");
70
71 for (i = 0; i < left_margin; i++)
72 ret += fprintf(fp, " ");
73
74 return ret;
75}
76
77static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
78 int left_margin)
63{ 79{
64 int i; 80 int i;
65 size_t ret = 0; 81 size_t ret = 0;
66 82
67 ret += fprintf(fp, "%s", " "); 83 ret += callchain__fprintf_left_margin(fp, left_margin);
68 84
69 for (i = 0; i < depth; i++) 85 for (i = 0; i < depth; i++)
70 if (depth_mask & (1 << i)) 86 if (depth_mask & (1 << i))
@@ -79,12 +95,12 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
79static size_t 95static size_t
80ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, 96ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
81 int depth_mask, int count, u64 total_samples, 97 int depth_mask, int count, u64 total_samples,
82 int hits) 98 int hits, int left_margin)
83{ 99{
84 int i; 100 int i;
85 size_t ret = 0; 101 size_t ret = 0;
86 102
87 ret += fprintf(fp, "%s", " "); 103 ret += callchain__fprintf_left_margin(fp, left_margin);
88 for (i = 0; i < depth; i++) { 104 for (i = 0; i < depth; i++) {
89 if (depth_mask & (1 << i)) 105 if (depth_mask & (1 << i))
90 ret += fprintf(fp, "|"); 106 ret += fprintf(fp, "|");
@@ -123,7 +139,8 @@ static void init_rem_hits(void)
123 139
124static size_t 140static size_t
125__callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 141__callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
126 u64 total_samples, int depth, int depth_mask) 142 u64 total_samples, int depth, int depth_mask,
143 int left_margin)
127{ 144{
128 struct rb_node *node, *next; 145 struct rb_node *node, *next;
129 struct callchain_node *child; 146 struct callchain_node *child;
@@ -164,7 +181,8 @@ __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
164 * But we keep the older depth mask for the line seperator 181 * But we keep the older depth mask for the line seperator
165 * to keep the level link until we reach the last child 182 * to keep the level link until we reach the last child
166 */ 183 */
167 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask); 184 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
185 left_margin);
168 i = 0; 186 i = 0;
169 list_for_each_entry(chain, &child->val, list) { 187 list_for_each_entry(chain, &child->val, list) {
170 if (chain->ip >= PERF_CONTEXT_MAX) 188 if (chain->ip >= PERF_CONTEXT_MAX)
@@ -172,11 +190,13 @@ __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
172 ret += ipchain__fprintf_graph(fp, chain, depth, 190 ret += ipchain__fprintf_graph(fp, chain, depth,
173 new_depth_mask, i++, 191 new_depth_mask, i++,
174 new_total, 192 new_total,
175 cumul); 193 cumul,
194 left_margin);
176 } 195 }
177 ret += __callchain__fprintf_graph(fp, child, new_total, 196 ret += __callchain__fprintf_graph(fp, child, new_total,
178 depth + 1, 197 depth + 1,
179 new_depth_mask | (1 << depth)); 198 new_depth_mask | (1 << depth),
199 left_margin);
180 node = next; 200 node = next;
181 } 201 }
182 202
@@ -190,17 +210,19 @@ __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
190 210
191 ret += ipchain__fprintf_graph(fp, &rem_hits, depth, 211 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
192 new_depth_mask, 0, new_total, 212 new_depth_mask, 0, new_total,
193 remaining); 213 remaining, left_margin);
194 } 214 }
195 215
196 return ret; 216 return ret;
197} 217}
198 218
219
199static size_t 220static size_t
200callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 221callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
201 u64 total_samples) 222 u64 total_samples, int left_margin)
202{ 223{
203 struct callchain_list *chain; 224 struct callchain_list *chain;
225 bool printed = false;
204 int i = 0; 226 int i = 0;
205 int ret = 0; 227 int ret = 0;
206 228
@@ -208,17 +230,27 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
208 if (chain->ip >= PERF_CONTEXT_MAX) 230 if (chain->ip >= PERF_CONTEXT_MAX)
209 continue; 231 continue;
210 232
211 if (!i++ && sort_by_sym_first) 233 if (!i++ && sort__first_dimension == SORT_SYM)
212 continue; 234 continue;
213 235
236 if (!printed) {
237 ret += callchain__fprintf_left_margin(fp, left_margin);
238 ret += fprintf(fp, "|\n");
239 ret += callchain__fprintf_left_margin(fp, left_margin);
240 ret += fprintf(fp, "---");
241
242 left_margin += 3;
243 printed = true;
244 } else
245 ret += callchain__fprintf_left_margin(fp, left_margin);
246
214 if (chain->sym) 247 if (chain->sym)
215 ret += fprintf(fp, " %s\n", chain->sym->name); 248 ret += fprintf(fp, " %s\n", chain->sym->name);
216 else 249 else
217 ret += fprintf(fp, " %p\n", 250 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
218 (void *)(long)chain->ip);
219 } 251 }
220 252
221 ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1); 253 ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
222 254
223 return ret; 255 return ret;
224} 256}
@@ -251,7 +283,7 @@ callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
251 283
252static size_t 284static size_t
253hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, 285hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
254 u64 total_samples) 286 u64 total_samples, int left_margin)
255{ 287{
256 struct rb_node *rb_node; 288 struct rb_node *rb_node;
257 struct callchain_node *chain; 289 struct callchain_node *chain;
@@ -271,7 +303,8 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
271 break; 303 break;
272 case CHAIN_GRAPH_ABS: /* Falldown */ 304 case CHAIN_GRAPH_ABS: /* Falldown */
273 case CHAIN_GRAPH_REL: 305 case CHAIN_GRAPH_REL:
274 ret += callchain__fprintf_graph(fp, chain, total_samples); 306 ret += callchain__fprintf_graph(fp, chain, total_samples,
307 left_margin);
275 case CHAIN_NONE: 308 case CHAIN_NONE:
276 default: 309 default:
277 break; 310 break;
@@ -316,8 +349,19 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
316 349
317 ret += fprintf(fp, "\n"); 350 ret += fprintf(fp, "\n");
318 351
319 if (callchain) 352 if (callchain) {
320 hist_entry_callchain__fprintf(fp, self, total_samples); 353 int left_margin = 0;
354
355 if (sort__first_dimension == SORT_COMM) {
356 se = list_first_entry(&hist_entry__sort_list, typeof(*se),
357 list);
358 left_margin = se->width ? *se->width : 0;
359 left_margin -= thread__comm_len(self->thread);
360 }
361
362 hist_entry_callchain__fprintf(fp, self, total_samples,
363 left_margin);
364 }
321 365
322 return ret; 366 return ret;
323} 367}