aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2013-03-05 00:53:28 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-03-15 12:06:06 -0400
commit1491c22a5f8563951d3a798758f82b471ecbf501 (patch)
treea0593f15e7598c429afb20fad007664387c4e24c /tools
parentc5a8368ca667d22a6e45396f23a5392d90396f39 (diff)
perf annotate: Support event group view for --print-line
Dynamically allocate source_line_percent according to a number of group members and save nr_pcnt to the struct source_line. This way we can handle multiple events in a general manner. However since the size of struct source_line is not fixed anymore, iterating whole source_line should care about its size. $ perf annotate --group --stdio --print-line Sorted summary for file /lib/ld-2.11.1.so ---------------------------------------------- 33.33 0.00 /build/buildd/eglibc-2.11.1/elf/rtld.c:381 33.33 0.00 /build/buildd/eglibc-2.11.1/elf/dynamic-link.h:128 33.33 0.00 /build/buildd/eglibc-2.11.1/elf/do-rel.h:105 0.00 75.00 /build/buildd/eglibc-2.11.1/elf/dynamic-link.h:137 0.00 25.00 /build/buildd/eglibc-2.11.1/elf/dynamic-link.h:187 ... Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Pekka Enberg <penberg@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1362462812-30885-9-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/annotate.c130
-rw-r--r--tools/perf/util/annotate.h1
2 files changed, 98 insertions, 33 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index ebf2596d7e2e..05e34df5d041 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -607,18 +607,26 @@ static double disasm__calc_percent(struct annotation *notes, int evidx,
607 s64 offset, s64 end, const char **path) 607 s64 offset, s64 end, const char **path)
608{ 608{
609 struct source_line *src_line = notes->src->lines; 609 struct source_line *src_line = notes->src->lines;
610 struct sym_hist *h = annotation__histogram(notes, evidx);
611 unsigned int hits = 0;
612 double percent = 0.0; 610 double percent = 0.0;
613 611
614 if (src_line) { 612 if (src_line) {
613 size_t sizeof_src_line = sizeof(*src_line) +
614 sizeof(src_line->p) * (src_line->nr_pcnt - 1);
615
615 while (offset < end) { 616 while (offset < end) {
617 src_line = (void *)notes->src->lines +
618 (sizeof_src_line * offset);
619
616 if (*path == NULL) 620 if (*path == NULL)
617 *path = src_line[offset].path; 621 *path = src_line->path;
618 622
619 percent += src_line[offset++].p[0].percent; 623 percent += src_line->p[evidx].percent;
624 offset++;
620 } 625 }
621 } else { 626 } else {
627 struct sym_hist *h = annotation__histogram(notes, evidx);
628 unsigned int hits = 0;
629
622 while (offset < end) 630 while (offset < end)
623 hits += h->addr[offset++]; 631 hits += h->addr[offset++];
624 632
@@ -658,9 +666,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
658 666
659 for (i = 0; i < nr_percent; i++) { 667 for (i = 0; i < nr_percent; i++) {
660 percent = disasm__calc_percent(notes, 668 percent = disasm__calc_percent(notes,
661 evsel->idx + i, offset, 669 notes->src->lines ? i : evsel->idx + i,
662 next ? next->offset : (s64) len, 670 offset,
663 &path); 671 next ? next->offset : (s64) len,
672 &path);
664 673
665 ppercents[i] = percent; 674 ppercents[i] = percent;
666 if (percent > max_percent) 675 if (percent > max_percent)
@@ -921,7 +930,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
921 struct source_line *iter; 930 struct source_line *iter;
922 struct rb_node **p = &root->rb_node; 931 struct rb_node **p = &root->rb_node;
923 struct rb_node *parent = NULL; 932 struct rb_node *parent = NULL;
924 int ret; 933 int i, ret;
925 934
926 while (*p != NULL) { 935 while (*p != NULL) {
927 parent = *p; 936 parent = *p;
@@ -929,7 +938,8 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
929 938
930 ret = strcmp(iter->path, src_line->path); 939 ret = strcmp(iter->path, src_line->path);
931 if (ret == 0) { 940 if (ret == 0) {
932 iter->p[0].percent_sum += src_line->p[0].percent; 941 for (i = 0; i < src_line->nr_pcnt; i++)
942 iter->p[i].percent_sum += src_line->p[i].percent;
933 return; 943 return;
934 } 944 }
935 945
@@ -939,12 +949,26 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
939 p = &(*p)->rb_right; 949 p = &(*p)->rb_right;
940 } 950 }
941 951
942 src_line->p[0].percent_sum = src_line->p[0].percent; 952 for (i = 0; i < src_line->nr_pcnt; i++)
953 src_line->p[i].percent_sum = src_line->p[i].percent;
943 954
944 rb_link_node(&src_line->node, parent, p); 955 rb_link_node(&src_line->node, parent, p);
945 rb_insert_color(&src_line->node, root); 956 rb_insert_color(&src_line->node, root);
946} 957}
947 958
959static int cmp_source_line(struct source_line *a, struct source_line *b)
960{
961 int i;
962
963 for (i = 0; i < a->nr_pcnt; i++) {
964 if (a->p[i].percent_sum == b->p[i].percent_sum)
965 continue;
966 return a->p[i].percent_sum > b->p[i].percent_sum;
967 }
968
969 return 0;
970}
971
948static void __resort_source_line(struct rb_root *root, struct source_line *src_line) 972static void __resort_source_line(struct rb_root *root, struct source_line *src_line)
949{ 973{
950 struct source_line *iter; 974 struct source_line *iter;
@@ -955,7 +979,7 @@ static void __resort_source_line(struct rb_root *root, struct source_line *src_l
955 parent = *p; 979 parent = *p;
956 iter = rb_entry(parent, struct source_line, node); 980 iter = rb_entry(parent, struct source_line, node);
957 981
958 if (src_line->p[0].percent_sum > iter->p[0].percent_sum) 982 if (cmp_source_line(src_line, iter))
959 p = &(*p)->rb_left; 983 p = &(*p)->rb_left;
960 else 984 else
961 p = &(*p)->rb_right; 985 p = &(*p)->rb_right;
@@ -987,12 +1011,18 @@ static void symbol__free_source_line(struct symbol *sym, int len)
987{ 1011{
988 struct annotation *notes = symbol__annotation(sym); 1012 struct annotation *notes = symbol__annotation(sym);
989 struct source_line *src_line = notes->src->lines; 1013 struct source_line *src_line = notes->src->lines;
1014 size_t sizeof_src_line;
990 int i; 1015 int i;
991 1016
992 for (i = 0; i < len; i++) 1017 sizeof_src_line = sizeof(*src_line) +
993 free(src_line[i].path); 1018 (sizeof(src_line->p) * (src_line->nr_pcnt - 1));
994 1019
995 free(src_line); 1020 for (i = 0; i < len; i++) {
1021 free(src_line->path);
1022 src_line = (void *)src_line + sizeof_src_line;
1023 }
1024
1025 free(notes->src->lines);
996 notes->src->lines = NULL; 1026 notes->src->lines = NULL;
997} 1027}
998 1028
@@ -1003,17 +1033,30 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1003 const char *filename) 1033 const char *filename)
1004{ 1034{
1005 u64 start; 1035 u64 start;
1006 int i; 1036 int i, k;
1037 int evidx = evsel->idx;
1007 char cmd[PATH_MAX * 2]; 1038 char cmd[PATH_MAX * 2];
1008 struct source_line *src_line; 1039 struct source_line *src_line;
1009 struct annotation *notes = symbol__annotation(sym); 1040 struct annotation *notes = symbol__annotation(sym);
1010 struct sym_hist *h = annotation__histogram(notes, evsel->idx); 1041 struct sym_hist *h = annotation__histogram(notes, evidx);
1011 struct rb_root tmp_root = RB_ROOT; 1042 struct rb_root tmp_root = RB_ROOT;
1043 int nr_pcnt = 1;
1044 u64 h_sum = h->sum;
1045 size_t sizeof_src_line = sizeof(struct source_line);
1046
1047 if (perf_evsel__is_group_event(evsel)) {
1048 for (i = 1; i < evsel->nr_members; i++) {
1049 h = annotation__histogram(notes, evidx + i);
1050 h_sum += h->sum;
1051 }
1052 nr_pcnt = evsel->nr_members;
1053 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->p);
1054 }
1012 1055
1013 if (!h->sum) 1056 if (!h_sum)
1014 return 0; 1057 return 0;
1015 1058
1016 src_line = notes->src->lines = calloc(len, sizeof(struct source_line)); 1059 src_line = notes->src->lines = calloc(len, sizeof_src_line);
1017 if (!notes->src->lines) 1060 if (!notes->src->lines)
1018 return -1; 1061 return -1;
1019 1062
@@ -1024,29 +1067,41 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1024 size_t line_len; 1067 size_t line_len;
1025 u64 offset; 1068 u64 offset;
1026 FILE *fp; 1069 FILE *fp;
1070 double percent_max = 0.0;
1027 1071
1028 src_line[i].p[0].percent = 100.0 * h->addr[i] / h->sum; 1072 src_line->nr_pcnt = nr_pcnt;
1029 if (src_line[i].p[0].percent <= 0.5) 1073
1030 continue; 1074 for (k = 0; k < nr_pcnt; k++) {
1075 h = annotation__histogram(notes, evidx + k);
1076 src_line->p[k].percent = 100.0 * h->addr[i] / h->sum;
1077
1078 if (src_line->p[k].percent > percent_max)
1079 percent_max = src_line->p[k].percent;
1080 }
1081
1082 if (percent_max <= 0.5)
1083 goto next;
1031 1084
1032 offset = start + i; 1085 offset = start + i;
1033 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); 1086 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
1034 fp = popen(cmd, "r"); 1087 fp = popen(cmd, "r");
1035 if (!fp) 1088 if (!fp)
1036 continue; 1089 goto next;
1037 1090
1038 if (getline(&path, &line_len, fp) < 0 || !line_len) 1091 if (getline(&path, &line_len, fp) < 0 || !line_len)
1039 goto next; 1092 goto next_close;
1040 1093
1041 src_line[i].path = malloc(sizeof(char) * line_len + 1); 1094 src_line->path = malloc(sizeof(char) * line_len + 1);
1042 if (!src_line[i].path) 1095 if (!src_line->path)
1043 goto next; 1096 goto next_close;
1044 1097
1045 strcpy(src_line[i].path, path); 1098 strcpy(src_line->path, path);
1046 insert_source_line(&tmp_root, &src_line[i]); 1099 insert_source_line(&tmp_root, src_line);
1047 1100
1048 next: 1101 next_close:
1049 pclose(fp); 1102 pclose(fp);
1103 next:
1104 src_line = (void *)src_line + sizeof_src_line;
1050 } 1105 }
1051 1106
1052 resort_source_line(root, &tmp_root); 1107 resort_source_line(root, &tmp_root);
@@ -1068,16 +1123,25 @@ static void print_summary(struct rb_root *root, const char *filename)
1068 1123
1069 node = rb_first(root); 1124 node = rb_first(root);
1070 while (node) { 1125 while (node) {
1071 double percent; 1126 double percent, percent_max = 0.0;
1072 const char *color; 1127 const char *color;
1073 char *path; 1128 char *path;
1129 int i;
1074 1130
1075 src_line = rb_entry(node, struct source_line, node); 1131 src_line = rb_entry(node, struct source_line, node);
1076 percent = src_line->p[0].percent_sum; 1132 for (i = 0; i < src_line->nr_pcnt; i++) {
1077 color = get_percent_color(percent); 1133 percent = src_line->p[i].percent_sum;
1134 color = get_percent_color(percent);
1135 color_fprintf(stdout, color, " %7.2f", percent);
1136
1137 if (percent > percent_max)
1138 percent_max = percent;
1139 }
1140
1078 path = src_line->path; 1141 path = src_line->path;
1142 color = get_percent_color(percent_max);
1143 color_fprintf(stdout, color, " %s", path);
1079 1144
1080 color_fprintf(stdout, color, " %7.2f %s", percent, path);
1081 node = rb_next(node); 1145 node = rb_next(node);
1082 } 1146 }
1083} 1147}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index bb2e3f998983..68f851e6c685 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -82,6 +82,7 @@ struct source_line_percent {
82struct source_line { 82struct source_line {
83 struct rb_node node; 83 struct rb_node node;
84 char *path; 84 char *path;
85 int nr_pcnt;
85 struct source_line_percent p[1]; 86 struct source_line_percent p[1];
86}; 87};
87 88