aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r--tools/perf/util/annotate.c305
1 files changed, 183 insertions, 122 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index f91775b4bc3c..20061cf42288 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -49,6 +49,7 @@ struct annotation_options annotation__default_options = {
49 .jump_arrows = true, 49 .jump_arrows = true,
50 .annotate_src = true, 50 .annotate_src = true,
51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS, 51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS,
52 .percent_type = PERCENT_PERIOD_LOCAL,
52}; 53};
53 54
54static regex_t file_lineno; 55static regex_t file_lineno;
@@ -1108,7 +1109,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
1108 if (perf_evsel__is_group_event(evsel)) 1109 if (perf_evsel__is_group_event(evsel))
1109 nr = evsel->nr_members; 1110 nr = evsel->nr_members;
1110 1111
1111 size += sizeof(al->samples[0]) * nr; 1112 size += sizeof(al->data[0]) * nr;
1112 1113
1113 al = zalloc(size); 1114 al = zalloc(size);
1114 if (al) { 1115 if (al) {
@@ -1117,7 +1118,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
1117 al->offset = args->offset; 1118 al->offset = args->offset;
1118 al->line = strdup(args->line); 1119 al->line = strdup(args->line);
1119 al->line_nr = args->line_nr; 1120 al->line_nr = args->line_nr;
1120 al->samples_nr = nr; 1121 al->data_nr = nr;
1121 } 1122 }
1122 1123
1123 return al; 1124 return al;
@@ -1297,7 +1298,8 @@ static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_wi
1297static int 1298static int
1298annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start, 1299annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
1299 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed, 1300 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
1300 int max_lines, struct annotation_line *queue, int addr_fmt_width) 1301 int max_lines, struct annotation_line *queue, int addr_fmt_width,
1302 int percent_type)
1301{ 1303{
1302 struct disasm_line *dl = container_of(al, struct disasm_line, al); 1304 struct disasm_line *dl = container_of(al, struct disasm_line, al);
1303 static const char *prev_line; 1305 static const char *prev_line;
@@ -1309,15 +1311,18 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1309 const char *color; 1311 const char *color;
1310 struct annotation *notes = symbol__annotation(sym); 1312 struct annotation *notes = symbol__annotation(sym);
1311 1313
1312 for (i = 0; i < al->samples_nr; i++) { 1314 for (i = 0; i < al->data_nr; i++) {
1313 struct annotation_data *sample = &al->samples[i]; 1315 double percent;
1314 1316
1315 if (sample->percent > max_percent) 1317 percent = annotation_data__percent(&al->data[i],
1316 max_percent = sample->percent; 1318 percent_type);
1319
1320 if (percent > max_percent)
1321 max_percent = percent;
1317 } 1322 }
1318 1323
1319 if (al->samples_nr > nr_percent) 1324 if (al->data_nr > nr_percent)
1320 nr_percent = al->samples_nr; 1325 nr_percent = al->data_nr;
1321 1326
1322 if (max_percent < min_pcnt) 1327 if (max_percent < min_pcnt)
1323 return -1; 1328 return -1;
@@ -1330,7 +1335,8 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1330 if (queue == al) 1335 if (queue == al)
1331 break; 1336 break;
1332 annotation_line__print(queue, sym, start, evsel, len, 1337 annotation_line__print(queue, sym, start, evsel, len,
1333 0, 0, 1, NULL, addr_fmt_width); 1338 0, 0, 1, NULL, addr_fmt_width,
1339 percent_type);
1334 } 1340 }
1335 } 1341 }
1336 1342
@@ -1351,18 +1357,20 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1351 } 1357 }
1352 1358
1353 for (i = 0; i < nr_percent; i++) { 1359 for (i = 0; i < nr_percent; i++) {
1354 struct annotation_data *sample = &al->samples[i]; 1360 struct annotation_data *data = &al->data[i];
1361 double percent;
1355 1362
1356 color = get_percent_color(sample->percent); 1363 percent = annotation_data__percent(data, percent_type);
1364 color = get_percent_color(percent);
1357 1365
1358 if (symbol_conf.show_total_period) 1366 if (symbol_conf.show_total_period)
1359 color_fprintf(stdout, color, " %11" PRIu64, 1367 color_fprintf(stdout, color, " %11" PRIu64,
1360 sample->he.period); 1368 data->he.period);
1361 else if (symbol_conf.show_nr_samples) 1369 else if (symbol_conf.show_nr_samples)
1362 color_fprintf(stdout, color, " %7" PRIu64, 1370 color_fprintf(stdout, color, " %7" PRIu64,
1363 sample->he.nr_samples); 1371 data->he.nr_samples);
1364 else 1372 else
1365 color_fprintf(stdout, color, " %7.2f", sample->percent); 1373 color_fprintf(stdout, color, " %7.2f", percent);
1366 } 1374 }
1367 1375
1368 printf(" : "); 1376 printf(" : ");
@@ -1621,6 +1629,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1621 char symfs_filename[PATH_MAX]; 1629 char symfs_filename[PATH_MAX];
1622 struct kcore_extract kce; 1630 struct kcore_extract kce;
1623 bool delete_extract = false; 1631 bool delete_extract = false;
1632 bool decomp = false;
1624 int stdout_fd[2]; 1633 int stdout_fd[2];
1625 int lineno = 0; 1634 int lineno = 0;
1626 int nline; 1635 int nline;
@@ -1654,6 +1663,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1654 tmp, sizeof(tmp)) < 0) 1663 tmp, sizeof(tmp)) < 0)
1655 goto out; 1664 goto out;
1656 1665
1666 decomp = true;
1657 strcpy(symfs_filename, tmp); 1667 strcpy(symfs_filename, tmp);
1658 } 1668 }
1659 1669
@@ -1740,7 +1750,7 @@ out_free_command:
1740out_remove_tmp: 1750out_remove_tmp:
1741 close(stdout_fd[0]); 1751 close(stdout_fd[0]);
1742 1752
1743 if (dso__needs_decompress(dso)) 1753 if (decomp)
1744 unlink(symfs_filename); 1754 unlink(symfs_filename);
1745 1755
1746 if (delete_extract) 1756 if (delete_extract)
@@ -1753,34 +1763,45 @@ out_close_stdout:
1753 goto out_free_command; 1763 goto out_free_command;
1754} 1764}
1755 1765
1756static void calc_percent(struct sym_hist *hist, 1766static void calc_percent(struct sym_hist *sym_hist,
1757 struct annotation_data *sample, 1767 struct hists *hists,
1768 struct annotation_data *data,
1758 s64 offset, s64 end) 1769 s64 offset, s64 end)
1759{ 1770{
1760 unsigned int hits = 0; 1771 unsigned int hits = 0;
1761 u64 period = 0; 1772 u64 period = 0;
1762 1773
1763 while (offset < end) { 1774 while (offset < end) {
1764 hits += hist->addr[offset].nr_samples; 1775 hits += sym_hist->addr[offset].nr_samples;
1765 period += hist->addr[offset].period; 1776 period += sym_hist->addr[offset].period;
1766 ++offset; 1777 ++offset;
1767 } 1778 }
1768 1779
1769 if (hist->nr_samples) { 1780 if (sym_hist->nr_samples) {
1770 sample->he.period = period; 1781 data->he.period = period;
1771 sample->he.nr_samples = hits; 1782 data->he.nr_samples = hits;
1772 sample->percent = 100.0 * hits / hist->nr_samples; 1783 data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
1773 } 1784 }
1785
1786 if (hists->stats.nr_non_filtered_samples)
1787 data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
1788
1789 if (sym_hist->period)
1790 data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
1791
1792 if (hists->stats.total_period)
1793 data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
1774} 1794}
1775 1795
1776static void annotation__calc_percent(struct annotation *notes, 1796static void annotation__calc_percent(struct annotation *notes,
1777 struct perf_evsel *evsel, s64 len) 1797 struct perf_evsel *leader, s64 len)
1778{ 1798{
1779 struct annotation_line *al, *next; 1799 struct annotation_line *al, *next;
1800 struct perf_evsel *evsel;
1780 1801
1781 list_for_each_entry(al, &notes->src->source, node) { 1802 list_for_each_entry(al, &notes->src->source, node) {
1782 s64 end; 1803 s64 end;
1783 int i; 1804 int i = 0;
1784 1805
1785 if (al->offset == -1) 1806 if (al->offset == -1)
1786 continue; 1807 continue;
@@ -1788,14 +1809,17 @@ static void annotation__calc_percent(struct annotation *notes,
1788 next = annotation_line__next(al, &notes->src->source); 1809 next = annotation_line__next(al, &notes->src->source);
1789 end = next ? next->offset : len; 1810 end = next ? next->offset : len;
1790 1811
1791 for (i = 0; i < al->samples_nr; i++) { 1812 for_each_group_evsel(evsel, leader) {
1792 struct annotation_data *sample; 1813 struct hists *hists = evsel__hists(evsel);
1793 struct sym_hist *hist; 1814 struct annotation_data *data;
1815 struct sym_hist *sym_hist;
1816
1817 BUG_ON(i >= al->data_nr);
1794 1818
1795 hist = annotation__histogram(notes, evsel->idx + i); 1819 sym_hist = annotation__histogram(notes, evsel->idx);
1796 sample = &al->samples[i]; 1820 data = &al->data[i++];
1797 1821
1798 calc_percent(hist, sample, al->offset, end); 1822 calc_percent(sym_hist, hists, data, al->offset, end);
1799 } 1823 }
1800 } 1824 }
1801} 1825}
@@ -1846,7 +1870,8 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1846 return symbol__disassemble(sym, &args); 1870 return symbol__disassemble(sym, &args);
1847} 1871}
1848 1872
1849static void insert_source_line(struct rb_root *root, struct annotation_line *al) 1873static void insert_source_line(struct rb_root *root, struct annotation_line *al,
1874 struct annotation_options *opts)
1850{ 1875{
1851 struct annotation_line *iter; 1876 struct annotation_line *iter;
1852 struct rb_node **p = &root->rb_node; 1877 struct rb_node **p = &root->rb_node;
@@ -1859,8 +1884,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
1859 1884
1860 ret = strcmp(iter->path, al->path); 1885 ret = strcmp(iter->path, al->path);
1861 if (ret == 0) { 1886 if (ret == 0) {
1862 for (i = 0; i < al->samples_nr; i++) 1887 for (i = 0; i < al->data_nr; i++) {
1863 iter->samples[i].percent_sum += al->samples[i].percent; 1888 iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
1889 opts->percent_type);
1890 }
1864 return; 1891 return;
1865 } 1892 }
1866 1893
@@ -1870,8 +1897,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
1870 p = &(*p)->rb_right; 1897 p = &(*p)->rb_right;
1871 } 1898 }
1872 1899
1873 for (i = 0; i < al->samples_nr; i++) 1900 for (i = 0; i < al->data_nr; i++) {
1874 al->samples[i].percent_sum = al->samples[i].percent; 1901 al->data[i].percent_sum = annotation_data__percent(&al->data[i],
1902 opts->percent_type);
1903 }
1875 1904
1876 rb_link_node(&al->rb_node, parent, p); 1905 rb_link_node(&al->rb_node, parent, p);
1877 rb_insert_color(&al->rb_node, root); 1906 rb_insert_color(&al->rb_node, root);
@@ -1881,10 +1910,10 @@ static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
1881{ 1910{
1882 int i; 1911 int i;
1883 1912
1884 for (i = 0; i < a->samples_nr; i++) { 1913 for (i = 0; i < a->data_nr; i++) {
1885 if (a->samples[i].percent_sum == b->samples[i].percent_sum) 1914 if (a->data[i].percent_sum == b->data[i].percent_sum)
1886 continue; 1915 continue;
1887 return a->samples[i].percent_sum > b->samples[i].percent_sum; 1916 return a->data[i].percent_sum > b->data[i].percent_sum;
1888 } 1917 }
1889 1918
1890 return 0; 1919 return 0;
@@ -1949,8 +1978,8 @@ static void print_summary(struct rb_root *root, const char *filename)
1949 int i; 1978 int i;
1950 1979
1951 al = rb_entry(node, struct annotation_line, rb_node); 1980 al = rb_entry(node, struct annotation_line, rb_node);
1952 for (i = 0; i < al->samples_nr; i++) { 1981 for (i = 0; i < al->data_nr; i++) {
1953 percent = al->samples[i].percent_sum; 1982 percent = al->data[i].percent_sum;
1954 color = get_percent_color(percent); 1983 color = get_percent_color(percent);
1955 color_fprintf(stdout, color, " %7.2f", percent); 1984 color_fprintf(stdout, color, " %7.2f", percent);
1956 1985
@@ -2029,10 +2058,12 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
2029 evsel_name = buf; 2058 evsel_name = buf;
2030 } 2059 }
2031 2060
2032 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 2061 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
2062 "percent: %s)\n",
2033 width, width, symbol_conf.show_total_period ? "Period" : 2063 width, width, symbol_conf.show_total_period ? "Period" :
2034 symbol_conf.show_nr_samples ? "Samples" : "Percent", 2064 symbol_conf.show_nr_samples ? "Samples" : "Percent",
2035 d_filename, evsel_name, h->nr_samples); 2065 d_filename, evsel_name, h->nr_samples,
2066 percent_type_str(opts->percent_type));
2036 2067
2037 printf("%-*.*s----\n", 2068 printf("%-*.*s----\n",
2038 graph_dotted_len, graph_dotted_len, graph_dotted_line); 2069 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -2052,7 +2083,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
2052 2083
2053 err = annotation_line__print(pos, sym, start, evsel, len, 2084 err = annotation_line__print(pos, sym, start, evsel, len,
2054 opts->min_pcnt, printed, opts->max_lines, 2085 opts->min_pcnt, printed, opts->max_lines,
2055 queue, addr_fmt_width); 2086 queue, addr_fmt_width, opts->percent_type);
2056 2087
2057 switch (err) { 2088 switch (err) {
2058 case 0: 2089 case 0:
@@ -2129,10 +2160,11 @@ static void FILE__write_graph(void *fp, int graph)
2129 fputs(s, fp); 2160 fputs(s, fp);
2130} 2161}
2131 2162
2132int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp) 2163static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
2164 struct annotation_options *opts)
2133{ 2165{
2134 struct annotation *notes = symbol__annotation(sym); 2166 struct annotation *notes = symbol__annotation(sym);
2135 struct annotation_write_ops ops = { 2167 struct annotation_write_ops wops = {
2136 .first_line = true, 2168 .first_line = true,
2137 .obj = fp, 2169 .obj = fp,
2138 .set_color = FILE__set_color, 2170 .set_color = FILE__set_color,
@@ -2146,15 +2178,16 @@ int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2146 list_for_each_entry(al, &notes->src->source, node) { 2178 list_for_each_entry(al, &notes->src->source, node) {
2147 if (annotation_line__filter(al, notes)) 2179 if (annotation_line__filter(al, notes))
2148 continue; 2180 continue;
2149 annotation_line__write(al, notes, &ops); 2181 annotation_line__write(al, notes, &wops, opts);
2150 fputc('\n', fp); 2182 fputc('\n', fp);
2151 ops.first_line = false; 2183 wops.first_line = false;
2152 } 2184 }
2153 2185
2154 return 0; 2186 return 0;
2155} 2187}
2156 2188
2157int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel) 2189int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
2190 struct annotation_options *opts)
2158{ 2191{
2159 const char *ev_name = perf_evsel__name(evsel); 2192 const char *ev_name = perf_evsel__name(evsel);
2160 char buf[1024]; 2193 char buf[1024];
@@ -2176,7 +2209,7 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
2176 2209
2177 fprintf(fp, "%s() %s\nEvent: %s\n\n", 2210 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2178 ms->sym->name, ms->map->dso->long_name, ev_name); 2211 ms->sym->name, ms->map->dso->long_name, ev_name);
2179 symbol__annotate_fprintf2(ms->sym, fp); 2212 symbol__annotate_fprintf2(ms->sym, fp, opts);
2180 2213
2181 fclose(fp); 2214 fclose(fp);
2182 err = 0; 2215 err = 0;
@@ -2346,7 +2379,8 @@ void annotation__update_column_widths(struct annotation *notes)
2346} 2379}
2347 2380
2348static void annotation__calc_lines(struct annotation *notes, struct map *map, 2381static void annotation__calc_lines(struct annotation *notes, struct map *map,
2349 struct rb_root *root) 2382 struct rb_root *root,
2383 struct annotation_options *opts)
2350{ 2384{
2351 struct annotation_line *al; 2385 struct annotation_line *al;
2352 struct rb_root tmp_root = RB_ROOT; 2386 struct rb_root tmp_root = RB_ROOT;
@@ -2355,13 +2389,14 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
2355 double percent_max = 0.0; 2389 double percent_max = 0.0;
2356 int i; 2390 int i;
2357 2391
2358 for (i = 0; i < al->samples_nr; i++) { 2392 for (i = 0; i < al->data_nr; i++) {
2359 struct annotation_data *sample; 2393 double percent;
2360 2394
2361 sample = &al->samples[i]; 2395 percent = annotation_data__percent(&al->data[i],
2396 opts->percent_type);
2362 2397
2363 if (sample->percent > percent_max) 2398 if (percent > percent_max)
2364 percent_max = sample->percent; 2399 percent_max = percent;
2365 } 2400 }
2366 2401
2367 if (percent_max <= 0.5) 2402 if (percent_max <= 0.5)
@@ -2369,18 +2404,19 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
2369 2404
2370 al->path = get_srcline(map->dso, notes->start + al->offset, NULL, 2405 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2371 false, true, notes->start + al->offset); 2406 false, true, notes->start + al->offset);
2372 insert_source_line(&tmp_root, al); 2407 insert_source_line(&tmp_root, al, opts);
2373 } 2408 }
2374 2409
2375 resort_source_line(root, &tmp_root); 2410 resort_source_line(root, &tmp_root);
2376} 2411}
2377 2412
2378static void symbol__calc_lines(struct symbol *sym, struct map *map, 2413static void symbol__calc_lines(struct symbol *sym, struct map *map,
2379 struct rb_root *root) 2414 struct rb_root *root,
2415 struct annotation_options *opts)
2380{ 2416{
2381 struct annotation *notes = symbol__annotation(sym); 2417 struct annotation *notes = symbol__annotation(sym);
2382 2418
2383 annotation__calc_lines(notes, map, root); 2419 annotation__calc_lines(notes, map, root, opts);
2384} 2420}
2385 2421
2386int symbol__tty_annotate2(struct symbol *sym, struct map *map, 2422int symbol__tty_annotate2(struct symbol *sym, struct map *map,
@@ -2389,7 +2425,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2389{ 2425{
2390 struct dso *dso = map->dso; 2426 struct dso *dso = map->dso;
2391 struct rb_root source_line = RB_ROOT; 2427 struct rb_root source_line = RB_ROOT;
2392 struct annotation *notes = symbol__annotation(sym); 2428 struct hists *hists = evsel__hists(evsel);
2393 char buf[1024]; 2429 char buf[1024];
2394 2430
2395 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0) 2431 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
@@ -2397,13 +2433,14 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2397 2433
2398 if (opts->print_lines) { 2434 if (opts->print_lines) {
2399 srcline_full_filename = opts->full_path; 2435 srcline_full_filename = opts->full_path;
2400 symbol__calc_lines(sym, map, &source_line); 2436 symbol__calc_lines(sym, map, &source_line, opts);
2401 print_summary(&source_line, dso->long_name); 2437 print_summary(&source_line, dso->long_name);
2402 } 2438 }
2403 2439
2404 annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel); 2440 hists__scnprintf_title(hists, buf, sizeof(buf));
2405 fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name); 2441 fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
2406 symbol__annotate_fprintf2(sym, stdout); 2442 buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
2443 symbol__annotate_fprintf2(sym, stdout, opts);
2407 2444
2408 annotated_source__purge(symbol__annotation(sym)->src); 2445 annotated_source__purge(symbol__annotation(sym)->src);
2409 2446
@@ -2424,7 +2461,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
2424 2461
2425 if (opts->print_lines) { 2462 if (opts->print_lines) {
2426 srcline_full_filename = opts->full_path; 2463 srcline_full_filename = opts->full_path;
2427 symbol__calc_lines(sym, map, &source_line); 2464 symbol__calc_lines(sym, map, &source_line, opts);
2428 print_summary(&source_line, dso->long_name); 2465 print_summary(&source_line, dso->long_name);
2429 } 2466 }
2430 2467
@@ -2441,14 +2478,21 @@ bool ui__has_annotation(void)
2441} 2478}
2442 2479
2443 2480
2444double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes) 2481static double annotation_line__max_percent(struct annotation_line *al,
2482 struct annotation *notes,
2483 unsigned int percent_type)
2445{ 2484{
2446 double percent_max = 0.0; 2485 double percent_max = 0.0;
2447 int i; 2486 int i;
2448 2487
2449 for (i = 0; i < notes->nr_events; i++) { 2488 for (i = 0; i < notes->nr_events; i++) {
2450 if (al->samples[i].percent > percent_max) 2489 double percent;
2451 percent_max = al->samples[i].percent; 2490
2491 percent = annotation_data__percent(&al->data[i],
2492 percent_type);
2493
2494 if (percent > percent_max)
2495 percent_max = percent;
2452 } 2496 }
2453 2497
2454 return percent_max; 2498 return percent_max;
@@ -2487,7 +2531,7 @@ call_like:
2487 2531
2488static void __annotation_line__write(struct annotation_line *al, struct annotation *notes, 2532static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2489 bool first_line, bool current_entry, bool change_color, int width, 2533 bool first_line, bool current_entry, bool change_color, int width,
2490 void *obj, 2534 void *obj, unsigned int percent_type,
2491 int (*obj__set_color)(void *obj, int color), 2535 int (*obj__set_color)(void *obj, int color),
2492 void (*obj__set_percent_color)(void *obj, double percent, bool current), 2536 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2493 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current), 2537 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
@@ -2495,7 +2539,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
2495 void (*obj__write_graph)(void *obj, int graph)) 2539 void (*obj__write_graph)(void *obj, int graph))
2496 2540
2497{ 2541{
2498 double percent_max = annotation_line__max_percent(al, notes); 2542 double percent_max = annotation_line__max_percent(al, notes, percent_type);
2499 int pcnt_width = annotation__pcnt_width(notes), 2543 int pcnt_width = annotation__pcnt_width(notes),
2500 cycles_width = annotation__cycles_width(notes); 2544 cycles_width = annotation__cycles_width(notes);
2501 bool show_title = false; 2545 bool show_title = false;
@@ -2514,15 +2558,18 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
2514 int i; 2558 int i;
2515 2559
2516 for (i = 0; i < notes->nr_events; i++) { 2560 for (i = 0; i < notes->nr_events; i++) {
2517 obj__set_percent_color(obj, al->samples[i].percent, current_entry); 2561 double percent;
2562
2563 percent = annotation_data__percent(&al->data[i], percent_type);
2564
2565 obj__set_percent_color(obj, percent, current_entry);
2518 if (notes->options->show_total_period) { 2566 if (notes->options->show_total_period) {
2519 obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period); 2567 obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2520 } else if (notes->options->show_nr_samples) { 2568 } else if (notes->options->show_nr_samples) {
2521 obj__printf(obj, "%6" PRIu64 " ", 2569 obj__printf(obj, "%6" PRIu64 " ",
2522 al->samples[i].he.nr_samples); 2570 al->data[i].he.nr_samples);
2523 } else { 2571 } else {
2524 obj__printf(obj, "%6.2f ", 2572 obj__printf(obj, "%6.2f ", percent);
2525 al->samples[i].percent);
2526 } 2573 }
2527 } 2574 }
2528 } else { 2575 } else {
@@ -2640,13 +2687,15 @@ print_addr:
2640} 2687}
2641 2688
2642void annotation_line__write(struct annotation_line *al, struct annotation *notes, 2689void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2643 struct annotation_write_ops *ops) 2690 struct annotation_write_ops *wops,
2691 struct annotation_options *opts)
2644{ 2692{
2645 __annotation_line__write(al, notes, ops->first_line, ops->current_entry, 2693 __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
2646 ops->change_color, ops->width, ops->obj, 2694 wops->change_color, wops->width, wops->obj,
2647 ops->set_color, ops->set_percent_color, 2695 opts->percent_type,
2648 ops->set_jumps_percent_color, ops->printf, 2696 wops->set_color, wops->set_percent_color,
2649 ops->write_graph); 2697 wops->set_jumps_percent_color, wops->printf,
2698 wops->write_graph);
2650} 2699}
2651 2700
2652int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel, 2701int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
@@ -2688,46 +2737,6 @@ out_free_offsets:
2688 return -1; 2737 return -1;
2689} 2738}
2690 2739
2691int __annotation__scnprintf_samples_period(struct annotation *notes,
2692 char *bf, size_t size,
2693 struct perf_evsel *evsel,
2694 bool show_freq)
2695{
2696 const char *ev_name = perf_evsel__name(evsel);
2697 char buf[1024], ref[30] = " show reference callgraph, ";
2698 char sample_freq_str[64] = "";
2699 unsigned long nr_samples = 0;
2700 int nr_members = 1;
2701 bool enable_ref = false;
2702 u64 nr_events = 0;
2703 char unit;
2704 int i;
2705
2706 if (perf_evsel__is_group_event(evsel)) {
2707 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2708 ev_name = buf;
2709 nr_members = evsel->nr_members;
2710 }
2711
2712 for (i = 0; i < nr_members; i++) {
2713 struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
2714
2715 nr_samples += ah->nr_samples;
2716 nr_events += ah->period;
2717 }
2718
2719 if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
2720 enable_ref = true;
2721
2722 if (show_freq)
2723 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2724
2725 nr_samples = convert_unit(nr_samples, &unit);
2726 return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2727 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2728 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2729}
2730
2731#define ANNOTATION__CFG(n) \ 2740#define ANNOTATION__CFG(n) \
2732 { .name = #n, .value = &annotation__default_options.n, } 2741 { .name = #n, .value = &annotation__default_options.n, }
2733 2742
@@ -2792,3 +2801,55 @@ void annotation_config__init(void)
2792 annotation__default_options.show_total_period = symbol_conf.show_total_period; 2801 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2793 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples; 2802 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2794} 2803}
2804
2805static unsigned int parse_percent_type(char *str1, char *str2)
2806{
2807 unsigned int type = (unsigned int) -1;
2808
2809 if (!strcmp("period", str1)) {
2810 if (!strcmp("local", str2))
2811 type = PERCENT_PERIOD_LOCAL;
2812 else if (!strcmp("global", str2))
2813 type = PERCENT_PERIOD_GLOBAL;
2814 }
2815
2816 if (!strcmp("hits", str1)) {
2817 if (!strcmp("local", str2))
2818 type = PERCENT_HITS_LOCAL;
2819 else if (!strcmp("global", str2))
2820 type = PERCENT_HITS_GLOBAL;
2821 }
2822
2823 return type;
2824}
2825
2826int annotate_parse_percent_type(const struct option *opt, const char *_str,
2827 int unset __maybe_unused)
2828{
2829 struct annotation_options *opts = opt->value;
2830 unsigned int type;
2831 char *str1, *str2;
2832 int err = -1;
2833
2834 str1 = strdup(_str);
2835 if (!str1)
2836 return -ENOMEM;
2837
2838 str2 = strchr(str1, '-');
2839 if (!str2)
2840 goto out;
2841
2842 *str2++ = 0;
2843
2844 type = parse_percent_type(str1, str2);
2845 if (type == (unsigned int) -1)
2846 type = parse_percent_type(str2, str1);
2847 if (type != (unsigned int) -1) {
2848 opts->percent_type = type;
2849 err = 0;
2850 }
2851
2852out:
2853 free(str1);
2854 return err;
2855}