aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/perf_counter/builtin-report.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-06-03 06:37:36 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-03 08:14:31 -0400
commit8229289b607682f90b946ad2c319526303c17700 (patch)
tree0fafa2c4e66052e4b94fb3b3e23507d6962800a4 /Documentation/perf_counter/builtin-report.c
parente61078a0c88773d3465b0b9d665c5ed6b952b1cf (diff)
perf report: Fix comm sorting
Since we can (and do) change comm strings during the collection phase, we cannot actually sort on them to build the histogram. Therefore add an (optional) third sorting phase to collapse the histrogram. Comm sorting now builds the histrogram on threads and then in the collapse phase collects all threads with the same comm. This collapsed histogram is then reversed and sorted on events. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: John Kacur <jkacur@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter/builtin-report.c')
-rw-r--r--Documentation/perf_counter/builtin-report.c118
1 files changed, 112 insertions, 6 deletions
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 0f88d9ebb34a..6d359c9f75dd 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -211,9 +211,9 @@ static struct thread *thread__new(pid_t pid)
211 211
212 if (self != NULL) { 212 if (self != NULL) {
213 self->pid = pid; 213 self->pid = pid;
214 self->comm = malloc(30); 214 self->comm = malloc(32);
215 if (self->comm) 215 if (self->comm)
216 sprintf(self->comm, ":%d", pid); 216 snprintf(self->comm, 32, ":%d", self->pid);
217 INIT_LIST_HEAD(&self->maps); 217 INIT_LIST_HEAD(&self->maps);
218 } 218 }
219 219
@@ -222,6 +222,8 @@ static struct thread *thread__new(pid_t pid)
222 222
223static int thread__set_comm(struct thread *self, const char *comm) 223static int thread__set_comm(struct thread *self, const char *comm)
224{ 224{
225 if (self->comm)
226 free(self->comm);
225 self->comm = strdup(comm); 227 self->comm = strdup(comm);
226 return self->comm ? 0 : -ENOMEM; 228 return self->comm ? 0 : -ENOMEM;
227} 229}
@@ -303,9 +305,12 @@ struct sort_entry {
303 char *header; 305 char *header;
304 306
305 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 307 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
308 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
306 size_t (*print)(FILE *fp, struct hist_entry *); 309 size_t (*print)(FILE *fp, struct hist_entry *);
307}; 310};
308 311
312/* --sort pid */
313
309static int64_t 314static int64_t
310sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) 315sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
311{ 316{
@@ -324,9 +329,17 @@ static struct sort_entry sort_thread = {
324 .print = sort__thread_print, 329 .print = sort__thread_print,
325}; 330};
326 331
332/* --sort comm */
333
327static int64_t 334static int64_t
328sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 335sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
329{ 336{
337 return right->thread->pid - left->thread->pid;
338}
339
340static int64_t
341sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
342{
330 char *comm_l = left->thread->comm; 343 char *comm_l = left->thread->comm;
331 char *comm_r = right->thread->comm; 344 char *comm_r = right->thread->comm;
332 345
@@ -349,11 +362,14 @@ sort__comm_print(FILE *fp, struct hist_entry *self)
349} 362}
350 363
351static struct sort_entry sort_comm = { 364static struct sort_entry sort_comm = {
352 .header = " Command", 365 .header = " Command",
353 .cmp = sort__comm_cmp, 366 .cmp = sort__comm_cmp,
354 .print = sort__comm_print, 367 .collapse = sort__comm_collapse,
368 .print = sort__comm_print,
355}; 369};
356 370
371/* --sort dso */
372
357static int64_t 373static int64_t
358sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 374sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
359{ 375{
@@ -387,6 +403,8 @@ static struct sort_entry sort_dso = {
387 .print = sort__dso_print, 403 .print = sort__dso_print,
388}; 404};
389 405
406/* --sort symbol */
407
390static int64_t 408static int64_t
391sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 409sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
392{ 410{
@@ -428,6 +446,8 @@ static struct sort_entry sort_sym = {
428 .print = sort__sym_print, 446 .print = sort__sym_print,
429}; 447};
430 448
449static int sort__need_collapse = 0;
450
431struct sort_dimension { 451struct sort_dimension {
432 char *name; 452 char *name;
433 struct sort_entry *entry; 453 struct sort_entry *entry;
@@ -456,6 +476,9 @@ static int sort_dimension__add(char *tok)
456 if (strncasecmp(tok, sd->name, strlen(tok))) 476 if (strncasecmp(tok, sd->name, strlen(tok)))
457 continue; 477 continue;
458 478
479 if (sd->entry->collapse)
480 sort__need_collapse = 1;
481
459 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 482 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
460 sd->taken = 1; 483 sd->taken = 1;
461 484
@@ -480,6 +503,25 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
480 return cmp; 503 return cmp;
481} 504}
482 505
506static int64_t
507hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
508{
509 struct sort_entry *se;
510 int64_t cmp = 0;
511
512 list_for_each_entry(se, &hist_entry__sort_list, list) {
513 int64_t (*f)(struct hist_entry *, struct hist_entry *);
514
515 f = se->collapse ?: se->cmp;
516
517 cmp = f(left, right);
518 if (cmp)
519 break;
520 }
521
522 return cmp;
523}
524
483static size_t 525static size_t
484hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples) 526hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
485{ 527{
@@ -549,6 +591,64 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
549 return 0; 591 return 0;
550} 592}
551 593
594static void hist_entry__free(struct hist_entry *he)
595{
596 free(he);
597}
598
599/*
600 * collapse the histogram
601 */
602
603static struct rb_root collapse_hists;
604
605static void collapse__insert_entry(struct hist_entry *he)
606{
607 struct rb_node **p = &collapse_hists.rb_node;
608 struct rb_node *parent = NULL;
609 struct hist_entry *iter;
610 int64_t cmp;
611
612 while (*p != NULL) {
613 parent = *p;
614 iter = rb_entry(parent, struct hist_entry, rb_node);
615
616 cmp = hist_entry__collapse(iter, he);
617
618 if (!cmp) {
619 iter->count += he->count;
620 hist_entry__free(he);
621 return;
622 }
623
624 if (cmp < 0)
625 p = &(*p)->rb_left;
626 else
627 p = &(*p)->rb_right;
628 }
629
630 rb_link_node(&he->rb_node, parent, p);
631 rb_insert_color(&he->rb_node, &collapse_hists);
632}
633
634static void collapse__resort(void)
635{
636 struct rb_node *next;
637 struct hist_entry *n;
638
639 if (!sort__need_collapse)
640 return;
641
642 next = rb_first(&hist);
643 while (next) {
644 n = rb_entry(next, struct hist_entry, rb_node);
645 next = rb_next(&n->rb_node);
646
647 rb_erase(&n->rb_node, &hist);
648 collapse__insert_entry(n);
649 }
650}
651
552/* 652/*
553 * reverse the map, sort on count. 653 * reverse the map, sort on count.
554 */ 654 */
@@ -577,9 +677,14 @@ static void output__insert_entry(struct hist_entry *he)
577 677
578static void output__resort(void) 678static void output__resort(void)
579{ 679{
580 struct rb_node *next = rb_first(&hist); 680 struct rb_node *next;
581 struct hist_entry *n; 681 struct hist_entry *n;
582 682
683 if (sort__need_collapse)
684 next = rb_first(&collapse_hists);
685 else
686 next = rb_first(&hist);
687
583 while (next) { 688 while (next) {
584 n = rb_entry(next, struct hist_entry, rb_node); 689 n = rb_entry(next, struct hist_entry, rb_node);
585 next = rb_next(&n->rb_node); 690 next = rb_next(&n->rb_node);
@@ -859,6 +964,7 @@ broken_event:
859 if (verbose >= 2) 964 if (verbose >= 2)
860 dsos__fprintf(stdout); 965 dsos__fprintf(stdout);
861 966
967 collapse__resort();
862 output__resort(); 968 output__resort();
863 output__fprintf(stdout, total); 969 output__fprintf(stdout, total);
864 970