diff options
Diffstat (limited to 'Documentation/perf_counter/builtin-report.c')
-rw-r--r-- | Documentation/perf_counter/builtin-report.c | 129 |
1 files changed, 99 insertions, 30 deletions
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c index a58be7fee425..a4c6ffa96505 100644 --- a/Documentation/perf_counter/builtin-report.c +++ b/Documentation/perf_counter/builtin-report.c | |||
@@ -447,26 +447,33 @@ static size_t map__fprintf(struct map *self, FILE *fp) | |||
447 | self->start, self->end, self->pgoff, self->dso->name); | 447 | self->start, self->end, self->pgoff, self->dso->name); |
448 | } | 448 | } |
449 | 449 | ||
450 | struct thread; | ||
451 | |||
452 | static const char *thread__name(struct thread *self, char *bf, size_t size); | ||
453 | |||
450 | struct symhist { | 454 | struct symhist { |
451 | struct rb_node rb_node; | 455 | struct rb_node rb_node; |
452 | struct dso *dso; | 456 | struct dso *dso; |
453 | struct symbol *sym; | 457 | struct symbol *sym; |
458 | struct thread *thread; | ||
454 | uint64_t ip; | 459 | uint64_t ip; |
455 | uint32_t count; | 460 | uint32_t count; |
456 | char level; | 461 | char level; |
457 | }; | 462 | }; |
458 | 463 | ||
459 | static struct symhist *symhist__new(struct symbol *sym, uint64_t ip, | 464 | static struct symhist *symhist__new(struct symbol *sym, uint64_t ip, |
460 | struct dso *dso, char level) | 465 | struct thread *thread, struct dso *dso, |
466 | char level) | ||
461 | { | 467 | { |
462 | struct symhist *self = malloc(sizeof(*self)); | 468 | struct symhist *self = malloc(sizeof(*self)); |
463 | 469 | ||
464 | if (self != NULL) { | 470 | if (self != NULL) { |
465 | self->sym = sym; | 471 | self->sym = sym; |
466 | self->ip = ip; | 472 | self->thread = thread; |
467 | self->dso = dso; | 473 | self->ip = ip; |
468 | self->level = level; | 474 | self->dso = dso; |
469 | self->count = 1; | 475 | self->level = level; |
476 | self->count = 1; | ||
470 | } | 477 | } |
471 | 478 | ||
472 | return self; | 479 | return self; |
@@ -482,17 +489,29 @@ static void symhist__inc(struct symhist *self) | |||
482 | ++self->count; | 489 | ++self->count; |
483 | } | 490 | } |
484 | 491 | ||
485 | static size_t symhist__fprintf(struct symhist *self, FILE *fp) | 492 | static size_t |
493 | symhist__fprintf(struct symhist *self, uint64_t total_samples, FILE *fp) | ||
486 | { | 494 | { |
487 | size_t ret = fprintf(fp, "%#llx [%c] ", (unsigned long long)self->ip, self->level); | 495 | char bf[32]; |
496 | size_t ret; | ||
497 | |||
498 | if (total_samples) | ||
499 | ret = fprintf(fp, "%5.2f", (self->count * 100.0) / total_samples); | ||
500 | else | ||
501 | ret = fprintf(fp, "%12d", self->count); | ||
502 | |||
503 | ret += fprintf(fp, "%14s [%c] %#018llx ", | ||
504 | thread__name(self->thread, bf, sizeof(bf)), | ||
505 | self->level, (unsigned long long)self->ip); | ||
488 | 506 | ||
489 | if (self->level != '.') | 507 | if (self->level != '.') |
490 | ret += fprintf(fp, "%s", self->sym ? self->sym->name: "<unknown>"); | 508 | ret += fprintf(fp, "%s\n", |
509 | self->sym ? self->sym->name : "<unknown>"); | ||
491 | else | 510 | else |
492 | ret += fprintf(fp, "%s: %s", | 511 | ret += fprintf(fp, "%s: %s\n", |
493 | self->dso ? self->dso->name : "<unknown>", | 512 | self->dso ? self->dso->name : "<unknown>", |
494 | self->sym ? self->sym->name : "<unknown>"); | 513 | self->sym ? self->sym->name : "<unknown>"); |
495 | return ret + fprintf(fp, ": %u\n", self->count); | 514 | return ret; |
496 | } | 515 | } |
497 | 516 | ||
498 | struct thread { | 517 | struct thread { |
@@ -503,6 +522,15 @@ struct thread { | |||
503 | char *comm; | 522 | char *comm; |
504 | }; | 523 | }; |
505 | 524 | ||
525 | static const char *thread__name(struct thread *self, char *bf, size_t size) | ||
526 | { | ||
527 | if (self->comm) | ||
528 | return self->comm; | ||
529 | |||
530 | snprintf(bf, sizeof(bf), ":%u", self->pid); | ||
531 | return bf; | ||
532 | } | ||
533 | |||
506 | static struct thread *thread__new(pid_t pid) | 534 | static struct thread *thread__new(pid_t pid) |
507 | { | 535 | { |
508 | struct thread *self = malloc(sizeof(*self)); | 536 | struct thread *self = malloc(sizeof(*self)); |
@@ -542,7 +570,7 @@ static int thread__symbol_incnew(struct thread *self, struct symbol *sym, | |||
542 | p = &(*p)->rb_right; | 570 | p = &(*p)->rb_right; |
543 | } | 571 | } |
544 | 572 | ||
545 | sh = symhist__new(sym, ip, dso, level); | 573 | sh = symhist__new(sym, ip, self, dso, level); |
546 | if (sh == NULL) | 574 | if (sh == NULL) |
547 | return -ENOMEM; | 575 | return -ENOMEM; |
548 | rb_link_node(&sh->rb_node, parent, p); | 576 | rb_link_node(&sh->rb_node, parent, p); |
@@ -574,7 +602,7 @@ static size_t thread__fprintf(struct thread *self, FILE *fp) | |||
574 | 602 | ||
575 | for (nd = rb_first(&self->symhists); nd; nd = rb_next(nd)) { | 603 | for (nd = rb_first(&self->symhists); nd; nd = rb_next(nd)) { |
576 | struct symhist *pos = rb_entry(nd, struct symhist, rb_node); | 604 | struct symhist *pos = rb_entry(nd, struct symhist, rb_node); |
577 | ret += symhist__fprintf(pos, fp); | 605 | ret += symhist__fprintf(pos, 0, fp); |
578 | } | 606 | } |
579 | 607 | ||
580 | return ret; | 608 | return ret; |
@@ -628,7 +656,7 @@ static struct map *thread__find_map(struct thread *self, uint64_t ip) | |||
628 | return NULL; | 656 | return NULL; |
629 | } | 657 | } |
630 | 658 | ||
631 | static void threads__fprintf(FILE *fp) | 659 | void threads__fprintf(FILE *fp) |
632 | { | 660 | { |
633 | struct rb_node *nd; | 661 | struct rb_node *nd; |
634 | for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { | 662 | for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { |
@@ -637,6 +665,61 @@ static void threads__fprintf(FILE *fp) | |||
637 | } | 665 | } |
638 | } | 666 | } |
639 | 667 | ||
668 | static struct rb_root global_symhists = RB_ROOT; | ||
669 | |||
670 | static void threads__insert_symhist(struct symhist *sh) | ||
671 | { | ||
672 | struct rb_node **p = &global_symhists.rb_node; | ||
673 | struct rb_node *parent = NULL; | ||
674 | struct symhist *iter; | ||
675 | |||
676 | while (*p != NULL) { | ||
677 | parent = *p; | ||
678 | iter = rb_entry(parent, struct symhist, rb_node); | ||
679 | |||
680 | /* Reverse order */ | ||
681 | if (sh->count > iter->count) | ||
682 | p = &(*p)->rb_left; | ||
683 | else | ||
684 | p = &(*p)->rb_right; | ||
685 | } | ||
686 | |||
687 | rb_link_node(&sh->rb_node, parent, p); | ||
688 | rb_insert_color(&sh->rb_node, &global_symhists); | ||
689 | } | ||
690 | |||
691 | static void threads__sort_symhists(void) | ||
692 | { | ||
693 | struct rb_node *nd; | ||
694 | |||
695 | for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { | ||
696 | struct thread *thread = rb_entry(nd, struct thread, rb_node); | ||
697 | struct rb_node *next = rb_first(&thread->symhists); | ||
698 | |||
699 | while (next) { | ||
700 | struct symhist *n = rb_entry(next, struct symhist, | ||
701 | rb_node); | ||
702 | next = rb_next(&n->rb_node); | ||
703 | rb_erase(&n->rb_node, &thread->symhists); | ||
704 | threads__insert_symhist(n); | ||
705 | } | ||
706 | |||
707 | } | ||
708 | } | ||
709 | |||
710 | static size_t threads__symhists_fprintf(uint64_t total_samples, FILE *fp) | ||
711 | { | ||
712 | struct rb_node *nd; | ||
713 | size_t ret = 0; | ||
714 | |||
715 | for (nd = rb_first(&global_symhists); nd; nd = rb_next(nd)) { | ||
716 | struct symhist *pos = rb_entry(nd, struct symhist, rb_node); | ||
717 | ret += symhist__fprintf(pos, total_samples, fp); | ||
718 | } | ||
719 | |||
720 | return ret; | ||
721 | } | ||
722 | |||
640 | static int __cmd_report(void) | 723 | static int __cmd_report(void) |
641 | { | 724 | { |
642 | unsigned long offset = 0; | 725 | unsigned long offset = 0; |
@@ -826,23 +909,9 @@ done: | |||
826 | return 0; | 909 | return 0; |
827 | } | 910 | } |
828 | 911 | ||
829 | //dsos__fprintf(stdout); | 912 | threads__sort_symhists(); |
830 | threads__fprintf(stdout); | 913 | threads__symhists_fprintf(total, stdout); |
831 | #if 0 | ||
832 | std::map<std::string, int>::iterator hi = hist.begin(); | ||
833 | |||
834 | while (hi != hist.end()) { | ||
835 | rev_hist.insert(std::pair<int, std::string>(hi->second, hi->first)); | ||
836 | hist.erase(hi++); | ||
837 | } | ||
838 | |||
839 | std::multimap<int, std::string>::const_iterator ri = rev_hist.begin(); | ||
840 | 914 | ||
841 | while (ri != rev_hist.end()) { | ||
842 | printf(" %5.2f %s\n", (100.0 * ri->first)/total, ri->second.c_str()); | ||
843 | ri++; | ||
844 | } | ||
845 | #endif | ||
846 | return rc; | 915 | return rc; |
847 | } | 916 | } |
848 | 917 | ||