aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-08-10 17:40:50 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2009-08-10 17:40:50 -0400
commitdcbf77cac640af0ab944d5cbb07934bf6708b4d9 (patch)
treee2f4d1b3a1089ee10436cb19740a9cb99f2dc527 /tools/perf/builtin-report.c
parentc00aafcd4977769e8728292302ddbbb8b1082fab (diff)
parent85dfd81dc57e8183a277ddd7a56aa65c96f3f487 (diff)
Merge branch 'master' into for-linus
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c103
1 files changed, 91 insertions, 12 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ce4f28645e64..99274cec0adb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -31,7 +31,7 @@
31static char const *input_name = "perf.data"; 31static char const *input_name = "perf.data";
32static char *vmlinux = NULL; 32static char *vmlinux = NULL;
33 33
34static char default_sort_order[] = "comm,dso"; 34static char default_sort_order[] = "comm,dso,symbol";
35static char *sort_order = default_sort_order; 35static char *sort_order = default_sort_order;
36static char *dso_list_str, *comm_list_str, *sym_list_str, 36static char *dso_list_str, *comm_list_str, *sym_list_str,
37 *col_width_list_str; 37 *col_width_list_str;
@@ -68,7 +68,7 @@ static int callchain;
68 68
69static 69static
70struct callchain_param callchain_param = { 70struct callchain_param callchain_param = {
71 .mode = CHAIN_GRAPH_ABS, 71 .mode = CHAIN_GRAPH_REL,
72 .min_percent = 0.5 72 .min_percent = 0.5
73}; 73};
74 74
@@ -112,7 +112,9 @@ struct read_event {
112 struct perf_event_header header; 112 struct perf_event_header header;
113 u32 pid,tid; 113 u32 pid,tid;
114 u64 value; 114 u64 value;
115 u64 format[3]; 115 u64 time_enabled;
116 u64 time_running;
117 u64 id;
116}; 118};
117 119
118typedef union event_union { 120typedef union event_union {
@@ -698,7 +700,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
698 size_t ret = 0; 700 size_t ret = 0;
699 701
700 if (verbose) 702 if (verbose)
701 ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip); 703 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
704 dso__symtab_origin(self->dso));
702 705
703 ret += repsep_fprintf(fp, "[%c] ", self->level); 706 ret += repsep_fprintf(fp, "[%c] ", self->level);
704 if (self->sym) { 707 if (self->sym) {
@@ -888,6 +891,21 @@ ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
888 return ret; 891 return ret;
889} 892}
890 893
894static struct symbol *rem_sq_bracket;
895static struct callchain_list rem_hits;
896
897static void init_rem_hits(void)
898{
899 rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
900 if (!rem_sq_bracket) {
901 fprintf(stderr, "Not enough memory to display remaining hits\n");
902 return;
903 }
904
905 strcpy(rem_sq_bracket->name, "[...]");
906 rem_hits.sym = rem_sq_bracket;
907}
908
891static size_t 909static size_t
892callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 910callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
893 u64 total_samples, int depth, int depth_mask) 911 u64 total_samples, int depth, int depth_mask)
@@ -897,25 +915,34 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
897 struct callchain_list *chain; 915 struct callchain_list *chain;
898 int new_depth_mask = depth_mask; 916 int new_depth_mask = depth_mask;
899 u64 new_total; 917 u64 new_total;
918 u64 remaining;
900 size_t ret = 0; 919 size_t ret = 0;
901 int i; 920 int i;
902 921
903 if (callchain_param.mode == CHAIN_GRAPH_REL) 922 if (callchain_param.mode == CHAIN_GRAPH_REL)
904 new_total = self->cumul_hit; 923 new_total = self->children_hit;
905 else 924 else
906 new_total = total_samples; 925 new_total = total_samples;
907 926
927 remaining = new_total;
928
908 node = rb_first(&self->rb_root); 929 node = rb_first(&self->rb_root);
909 while (node) { 930 while (node) {
931 u64 cumul;
932
910 child = rb_entry(node, struct callchain_node, rb_node); 933 child = rb_entry(node, struct callchain_node, rb_node);
934 cumul = cumul_hits(child);
935 remaining -= cumul;
911 936
912 /* 937 /*
913 * The depth mask manages the output of pipes that show 938 * The depth mask manages the output of pipes that show
914 * the depth. We don't want to keep the pipes of the current 939 * the depth. We don't want to keep the pipes of the current
915 * level for the last child of this depth 940 * level for the last child of this depth.
941 * Except if we have remaining filtered hits. They will
942 * supersede the last child
916 */ 943 */
917 next = rb_next(node); 944 next = rb_next(node);
918 if (!next) 945 if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
919 new_depth_mask &= ~(1 << (depth - 1)); 946 new_depth_mask &= ~(1 << (depth - 1));
920 947
921 /* 948 /*
@@ -930,7 +957,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
930 ret += ipchain__fprintf_graph(fp, chain, depth, 957 ret += ipchain__fprintf_graph(fp, chain, depth,
931 new_depth_mask, i++, 958 new_depth_mask, i++,
932 new_total, 959 new_total,
933 child->cumul_hit); 960 cumul);
934 } 961 }
935 ret += callchain__fprintf_graph(fp, child, new_total, 962 ret += callchain__fprintf_graph(fp, child, new_total,
936 depth + 1, 963 depth + 1,
@@ -938,6 +965,19 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
938 node = next; 965 node = next;
939 } 966 }
940 967
968 if (callchain_param.mode == CHAIN_GRAPH_REL &&
969 remaining && remaining != new_total) {
970
971 if (!rem_sq_bracket)
972 return ret;
973
974 new_depth_mask &= ~(1 << (depth - 1));
975
976 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
977 new_depth_mask, 0, new_total,
978 remaining);
979 }
980
941 return ret; 981 return ret;
942} 982}
943 983
@@ -1358,6 +1398,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1358 unsigned int width; 1398 unsigned int width;
1359 char *col_width = col_width_list_str; 1399 char *col_width = col_width_list_str;
1360 1400
1401 init_rem_hits();
1402
1361 fprintf(fp, "# Samples: %Ld\n", (u64)total_samples); 1403 fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
1362 fprintf(fp, "#\n"); 1404 fprintf(fp, "#\n");
1363 1405
@@ -1424,11 +1466,13 @@ print_entries:
1424 if (sort_order == default_sort_order && 1466 if (sort_order == default_sort_order &&
1425 parent_pattern == default_parent_pattern) { 1467 parent_pattern == default_parent_pattern) {
1426 fprintf(fp, "#\n"); 1468 fprintf(fp, "#\n");
1427 fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n"); 1469 fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
1428 fprintf(fp, "#\n"); 1470 fprintf(fp, "#\n");
1429 } 1471 }
1430 fprintf(fp, "\n"); 1472 fprintf(fp, "\n");
1431 1473
1474 free(rem_sq_bracket);
1475
1432 return ret; 1476 return ret;
1433} 1477}
1434 1478
@@ -1690,14 +1734,37 @@ static void trace_event(event_t *event)
1690 dprintf(".\n"); 1734 dprintf(".\n");
1691} 1735}
1692 1736
1737static struct perf_header *header;
1738
1739static struct perf_counter_attr *perf_header__find_attr(u64 id)
1740{
1741 int i;
1742
1743 for (i = 0; i < header->attrs; i++) {
1744 struct perf_header_attr *attr = header->attr[i];
1745 int j;
1746
1747 for (j = 0; j < attr->ids; j++) {
1748 if (attr->id[j] == id)
1749 return &attr->attr;
1750 }
1751 }
1752
1753 return NULL;
1754}
1755
1693static int 1756static int
1694process_read_event(event_t *event, unsigned long offset, unsigned long head) 1757process_read_event(event_t *event, unsigned long offset, unsigned long head)
1695{ 1758{
1696 dprintf("%p [%p]: PERF_EVENT_READ: %d %d %Lu\n", 1759 struct perf_counter_attr *attr = perf_header__find_attr(event->read.id);
1760
1761 dprintf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n",
1697 (void *)(offset + head), 1762 (void *)(offset + head),
1698 (void *)(long)(event->header.size), 1763 (void *)(long)(event->header.size),
1699 event->read.pid, 1764 event->read.pid,
1700 event->read.tid, 1765 event->read.tid,
1766 attr ? __event_name(attr->type, attr->config)
1767 : "FAIL",
1701 event->read.value); 1768 event->read.value);
1702 1769
1703 return 0; 1770 return 0;
@@ -1743,8 +1810,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1743 return 0; 1810 return 0;
1744} 1811}
1745 1812
1746static struct perf_header *header;
1747
1748static u64 perf_header__sample_type(void) 1813static u64 perf_header__sample_type(void)
1749{ 1814{
1750 u64 sample_type = 0; 1815 u64 sample_type = 0;
@@ -1812,6 +1877,13 @@ static int __cmd_report(void)
1812 " -g?\n"); 1877 " -g?\n");
1813 exit(-1); 1878 exit(-1);
1814 } 1879 }
1880 } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
1881 callchain = 1;
1882 if (register_callchain_param(&callchain_param) < 0) {
1883 fprintf(stderr, "Can't register callchain"
1884 " params\n");
1885 exit(-1);
1886 }
1815 } 1887 }
1816 1888
1817 if (load_kernel() < 0) { 1889 if (load_kernel() < 0) {
@@ -1950,6 +2022,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
1950 else if (!strncmp(tok, "fractal", strlen(arg))) 2022 else if (!strncmp(tok, "fractal", strlen(arg)))
1951 callchain_param.mode = CHAIN_GRAPH_REL; 2023 callchain_param.mode = CHAIN_GRAPH_REL;
1952 2024
2025 else if (!strncmp(tok, "none", strlen(arg))) {
2026 callchain_param.mode = CHAIN_NONE;
2027 callchain = 0;
2028
2029 return 0;
2030 }
2031
1953 else 2032 else
1954 return -1; 2033 return -1;
1955 2034