perf annotate: Add support for event group view (v1)
Namhyung Kim
maintainercover perf annotate: Add support for event group view (v1)
Hi,
This is a patchset to support event grouping on perf annotate.
It depends on perf report event group view patchset [1] and contains a couple of annotate fixup/cleanup patches that I sent yesterday (although I fixed a compile problem and added a cleanup patch).
The symbol histograms already contain hit counts for every event so it was relatively easier to support than that of perf report case. I added a sort of flexible array to struct source_line and browser_disasm_line for gathering percent values for each group members.
Patch 0001-0004 are cleanups and can be merged separately. I sent
similar patches yesterday, and this is the up-to-date version.
Patch 0005-0006 are preparation for later patches and Patch 0007 added event group view for --stdio.
Patch 0008-0009 added event group view for --print-line and Patch 0010-0012 added event group view for --tui.
Patch 0013 added --group option to enable group view suport.
Let me show you an example:
$ 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
Percent | Source code & Disassembly of ld-2.11.1.so
------------------------------------------------------------------
:
:
:
: Disassembly of section .text:
:
: 0000000000001120 <_dl_rtld_di_serinfo-0x7a20>:
0.00 0.00 : 1120: push %rbp
0.00 0.00 : 1121: mov %rsp,%rbp
0.00 0.00 : 1124: push %r15
0.00 0.00 : 1126: push %r14
0.00 0.00 : 1128: push %r13
0.00 0.00 : 112a: push %r12
0.00 0.00 : 112c: push %rbx
0.00 0.00 : 112d: mov %rdi,%rbx
0.00 0.00 : 1130: sub $0x28,%rsp
0.00 0.00 : 1134: rdtsc
0.00 0.00 : 1136: shl $0x20,%rdx
0.00 0.00 : 113a: mov %eax,%eax
0.00 0.00 : 113c: or %rax,%rdx
0.00 0.00 : 113f: lea -0x26(%rip),%r13 # 1120 <free@plt+0x648>
0.00 0.00 : 1146: sub 0x21ea93(%rip),%r13 # 21fbe0 <calloc+0x208c80>
/build/buildd/eglibc-2.11.1/elf/rtld.c:381
33.33 0.00 : 114d: mov %rdx,0x21ec54(%rip) # 21fda8 <_rtld_global_ro+0x1a8>
0.00 0.00 : 1154: mov %r13,%rdx...
You can access it via my tree as well.
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git perf/annotate-group-v1
As always, any comments are welcome, thanks.
Namhyung
[1] http://www.mail-archive.com/[email protected]/msg337706.html
Namhyung Kim (13):
perf annotate: Parse --asm-raw output properly
perf annotate: Whitespace fixups
perf annotate: Merge same lines in summary view
perf annotate: Don't try to follow jump target on PLT symbols perf annotate: Pass evsel instead of evidx on annotation functions perf annotate: Factor out disasm__calc_percent()
perf annotate: Basic support for event group view
perf annotate: Factor out struct source_line_percent perf annotate: Support event group view for --print-line perf annotate browser: Make browser_disasm_line->percent an array perf annotate browser: Use disasm__calc_percent()
perf annotate browser: Support event group view on TUI perf annotate: Add --group option
tools/perf/builtin-annotate.c | 20 ++- tools/perf/builtin-top.c | 2 +- tools/perf/ui/browsers/annotate.c | 151 ++++++++++------ tools/perf/ui/browsers/hists.c | 2 +- tools/perf/util/annotate.c | 349 ++++++++++++++++++++++++++++++------- tools/perf/util/annotate.h | 28 ++- tools/perf/util/hist.h | 5 +- 7 files changed, 418 insertions(+), 139 deletions(-)
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 1/13 perf annotate: Parse --asm-raw output properly
From: Namhyung Kim <[email protected]>
If --asm-raw option was given, objdump output will contain hex numbers of the instruction before the symbolic name. However current parser code doesn't handle it properly. Fix it.
--- tools/perf/ui/browsers/annotate.c | 2 ++ tools/perf/util/annotate.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-)
tools/perf/ui/browsers/annotate.c +2 -0
@@ -117,6 +117,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ab->addr_width, " ");slsmg_write_nstring (bf, printed);slsmg_write_nstring (dl->line, width - printed -6 ); + }else if (!dl->name) { +slsmg_write_nstring (" " , width -7 ); }else {u64 addr = dl->offset;int color =-1 ;
tools/perf/util/annotate.c +34 -2
@@ -162,7 +162,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)static int lock__parse (struct ins_operands *ops) { -char *name; +char *name =NULL ; ops->locked.ops =zalloc (sizeof (*ops->locked.ops));if (ops->locked.ops ==NULL )
@@ -171,7 +171,10 @@ static int lock__parse(struct ins_operands *ops)if (disasm_line__parse (ops->raw, &name, &ops->locked.ops->raw) <0 ) goto out_free_ops; - ops->locked.ins =ins__find (name); +if (name ==NULL ) + goto out_free_ops; + + ops->locked.ins =ins__find (name);if (ops->locked.ins ==NULL ) goto out_free_ops;
@@ -492,6 +495,9 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,static void disasm_line__init_ins (struct disasm_line *dl) { +if (dl->name ==NULL ) +return ; + dl->ins =ins__find (dl->name);if (dl->ins ==NULL )
@@ -514,6 +520,32 @@ static int disasm_line__parse(char *line, char **namep, char **rawp)if (name[0 ] =='\0' )return -1 ; +if (symbol_conf.annotate_asm_raw) { +/* +* If --asm-raw option was given, objdump output will contain +* hex numbers of the instructions before the symbolic name. +* They are separated by at least two space characters: +* +* 400540: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp) +* 400547: 00 +* +* It sometimes was broken to multiple lines due to a limited +* width. In this case following condition will be met: +* +* dl->offset != -1 && dl->name == NULL. +*/ + name =strstr (name," " ); +if (name ==NULL ) +return 0 ; + +while (isspace (name[0 ])) + ++name; + +if (name[0 ] =='\0' ) +return -1 ; + + } + *rawp = name +1 ;while ((*rawp)[0 ] !='\0' && !isspace ((*rawp)[0 ]))
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 2/13 perf annotate: Whitespace fixups
In reply to Namhyung KimSome lines are indented by whitespace characters rather than tabs. Fix them.
--- tools/perf/util/annotate.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
tools/perf/util/annotate.c +6 -6
@@ -175,14 +175,14 @@ static int lock__parse(struct ins_operands *ops) goto out_free_ops; ops->locked.ins =ins__find (name); -if (ops->locked.ins ==NULL ) - goto out_free_ops; +if (ops->locked.ins ==NULL ) + goto out_free_ops; -if (!ops->locked.ins->ops) -return 0 ; +if (!ops->locked.ins->ops) +return 0 ; -if (ops->locked.ins->ops->parse) - ops->locked.ins->ops->parse (ops->locked.ops); +if (ops->locked.ins->ops->parse) + ops->locked.ins->ops->parse (ops->locked.ops);return 0 ;
Signature · 1 line
1.7.9.2
tip-bot for Namhyung Kim
maintainer[tip:perf/core] perf annotate: Whitespace fixups
Commit-ID: 2ba34aaa6db8b61cf1fa14132f885ba6bc7c9ae0 Gitweb: http://git.kernel.org/tip/2ba34aaa6db8b61cf1fa14132f885ba6bc7c9ae0 Author: Namhyung Kim <[email protected]> AuthorDate: Sat, 10 Nov 2012 02:27:13 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 9 Nov 2012 16:22:46 -0300
perf annotate: Whitespace fixups
Some lines are indented by whitespace characters rather than tabs. Fix them.
--- tools/perf/util/annotate.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
tools/perf/util/annotate.c +7 -7
@@ -171,15 +171,15 @@ static int lock__parse(struct ins_operands *ops)if (disasm_line__parse (ops->raw, &name, &ops->locked.ops->raw) <0 ) goto out_free_ops; - ops->locked.ins =ins__find (name); -if (ops->locked.ins ==NULL ) - goto out_free_ops; + ops->locked.ins =ins__find (name); +if (ops->locked.ins ==NULL ) + goto out_free_ops; -if (!ops->locked.ins->ops) -return 0 ; +if (!ops->locked.ins->ops) +return 0 ; -if (ops->locked.ins->ops->parse) - ops->locked.ins->ops->parse (ops->locked.ops); +if (ops->locked.ins->ops->parse) + ops->locked.ins->ops->parse (ops->locked.ops);return 0 ;
Namhyung Kim
maintainerPATCH 3/13 perf annotate: Merge same lines in summary view
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
The --print-line option of perf annotate command shows summary for each source line. But it didn't merge same lines so that it can appear multiple times.
* before:
Sorted summary for file /home/namhyung/bin/mcol
----------------------------------------------
21.71 /home/namhyung/tmp/mcol.c:26
20.66 /home/namhyung/tmp/mcol.c:25
9.53 /home/namhyung/tmp/mcol.c:24
7.68 /home/namhyung/tmp/mcol.c:25
7.67 /home/namhyung/tmp/mcol.c:25
7.66 /home/namhyung/tmp/mcol.c:26
7.49 /home/namhyung/tmp/mcol.c:26
6.92 /home/namhyung/tmp/mcol.c:25
6.81 /home/namhyung/tmp/mcol.c:25
1.07 /home/namhyung/tmp/mcol.c:26
0.52 /home/namhyung/tmp/mcol.c:25
0.51 /home/namhyung/tmp/mcol.c:25
0.51 /home/namhyung/tmp/mcol.c:24* after:
Sorted summary for file /home/namhyung/bin/mcol
----------------------------------------------
50.77 /home/namhyung/tmp/mcol.c:25 37.94 /home/namhyung/tmp/mcol.c:26 10.04 /home/namhyung/tmp/mcol.c:24
To do that, introduce percent_sum field so that the normal line-by-line output doesn't get changed.
--- tools/perf/util/annotate.c | 55 +++++++++++++++++++++++++++++++++++++++++--- tools/perf/util/annotate.h | 1 + 2 files changed, 53 insertions(+), 3 deletions(-)
tools/perf/util/annotate.c +52 -3
@@ -890,12 +890,41 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linstruct source_line *iter;struct rb_node **p = &root->rb_node;struct rb_node *parent =NULL ; +int ret;while (*p !=NULL ) { parent = *p; iter = rb_entry(parent, struct source_line, node); -if (src_line->percent > iter->percent) + ret =strcmp (iter->path, src_line->path); +if (ret ==0 ) { + iter->percent_sum += src_line->percent; +return ; + } + +if (ret <0 ) + p = &(*p)->rb_left; +else + p = &(*p)->rb_right; + } + + src_line->percent_sum = src_line->percent; + +rb_link_node (&src_line->node, parent, p); +rb_insert_color (&src_line->node, root); +} + +static void __resort_source_line (struct rb_root *root,struct source_line *src_line) +{ +struct source_line *iter; +struct rb_node **p = &root->rb_node; +struct rb_node *parent =NULL ; + +while (*p !=NULL ) { + parent = *p; + iter = rb_entry(parent, struct source_line, node); + +if (src_line->percent_sum > iter->percent_sum) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -905,6 +934,24 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linrb_insert_color (&src_line->node, root); } +static void resort_source_line (struct rb_root *dest_root,struct rb_root *src_root) +{ +struct source_line *src_line; +struct rb_node *node; + + node =rb_first (src_root); +while (node) { +struct rb_node *next; + + src_line = rb_entry(node, struct source_line, node); + next =rb_next (node); +rb_erase (node, src_root); + +__resort_source_line (dest_root, src_line); + node = next; + } +} +static void symbol__free_source_line (struct symbol *sym,int len) {struct annotation *notes =symbol__annotation (sym);
@@ -929,6 +976,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,struct source_line *src_line;struct annotation *notes =symbol__annotation (sym);struct sym_hist *h =annotation__histogram (notes, evidx); +struct rb_root tmp_root =RB_ROOT ;if (!h->sum)return 0 ;
@@ -963,12 +1011,13 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, goto next;strcpy (src_line[i].path, path); -insert_source_line (root, &src_line[i]); +insert_source_line (&tmp_root, &src_line[i]); next:pclose (fp); } +resort_source_line (root, &tmp_root);return 0 ; }
@@ -992,7 +1041,7 @@ static void print_summary(struct rb_root *root, const char *filename)char *path; src_line = rb_entry(node, struct source_line, node); - percent = src_line->percent; + percent = src_line->percent_sum; color =get_percent_color (percent); path = src_line->path;
tools/perf/util/annotate.h +1 -0
@@ -76,6 +76,7 @@ struct sym_hist {struct source_line {struct rb_node node;double percent; +double percent_sum;char *path; };
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 4/13 perf annotate: Don't try to follow jump target on PLT symbols
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
The perf annotate browser on TUI can identify a jump target for a selected instruction. It assumes that the jump target is within the function but it's not the case of PLT symbols which have offset out of the function as a target. Since it caused a segmentation fault, do not try to follow jump target on the PLT symbols.
--- tools/perf/ui/browsers/annotate.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
tools/perf/ui/browsers/annotate.c +12 -0
@@ -190,6 +190,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)struct disasm_line *cursor = ab->selection, *target;struct browser_disasm_line *btarget, *bcursor;unsigned int from, to; +struct map_symbol *ms = ab->b.priv; +struct symbol *sym = ms->sym; + +/* PLT symbols contain external offsets */ +if (strstr (sym->name,"@plt" )) +return ;if (!cursor || !cursor->ins || !ins__is_jump (cursor->ins) || !disasm_line__has_offset (cursor))
@@ -773,6 +779,12 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser size_t size) {u64 offset; +struct map_symbol *ms = browser->b.priv; +struct symbol *sym = ms->sym; + +/* PLT symbols contain external offsets */ +if (strstr (sym->name,"@plt" )) +return ;for (offset =0 ; offset < size; ++offset) {struct disasm_line *dl = browser->offsets[offset], *dlt;
Signature · 1 line
1.7.9.2
[tip:perf/core] perf annotate: Don' t try to follow jump target on PLT symbols
Commit-ID: 32ae1efd9d40645601cd4e09fa83a2711dd1ad6d Gitweb: http://git.kernel.org/tip/32ae1efd9d40645601cd4e09fa83a2711dd1ad6d Author: Namhyung Kim <[email protected]> AuthorDate: Sat, 10 Nov 2012 02:27:15 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 9 Nov 2012 16:23:21 -0300
perf annotate: Don't try to follow jump target on PLT symbols
The perf annotate browser on TUI can identify a jump target for a selected instruction. It assumes that the jump target is within the function but it's not the case of PLT symbols which have offset out of the function as a target.
Since it caused a segmentation fault, do not try to follow jump target on the PLT symbols.
--- tools/perf/ui/browsers/annotate.c | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
tools/perf/ui/browsers/annotate.c +12 -0
@@ -188,6 +188,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)struct disasm_line *cursor = ab->selection, *target;struct browser_disasm_line *btarget, *bcursor;unsigned int from, to; +struct map_symbol *ms = ab->b.priv; +struct symbol *sym = ms->sym; + +/* PLT symbols contain external offsets */ +if (strstr (sym->name,"@plt" )) +return ;if (!cursor || !cursor->ins || !ins__is_jump (cursor->ins) || !disasm_line__has_offset (cursor))
@@ -771,6 +777,12 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser size_t size) {u64 offset; +struct map_symbol *ms = browser->b.priv; +struct symbol *sym = ms->sym; + +/* PLT symbols contain external offsets */ +if (strstr (sym->name,"@plt" )) +return ;for (offset =0 ; offset < size; ++offset) {struct disasm_line *dl = browser->offsets[offset], *dlt;
Namhyung Kim
maintainerPATCH 5/13 perf annotate: Pass evsel instead of evidx on annotation functions
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Pass evsel instead of evidx. This is a preparation for supporting event group view in annotation and no functional change is intended.
--- tools/perf/builtin-annotate.c | 14 ++++++++------ tools/perf/builtin-top.c | 2 +- tools/perf/ui/browsers/annotate.c | 30 +++++++++++++++++------------- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/util/annotate.c | 33 ++++++++++++++++++--------------- tools/perf/util/annotate.h | 17 +++++++++-------- tools/perf/util/hist.h | 5 +++-- 7 files changed, 57 insertions(+), 46 deletions(-)
tools/perf/builtin-annotate.c +8 -6
@@ -108,14 +108,16 @@ static int process_sample_event(struct perf_tool *tool,return 0 ; } -static int hist_entry__tty_annotate (struct hist_entry *he,int evidx, +static int hist_entry__tty_annotate (struct hist_entry *he, +struct perf_evsel *evsel,struct perf_annotate *ann) { -return symbol__tty_annotate (he->ms.sym, he->ms.map, evidx, +return symbol__tty_annotate (he->ms.sym, he->ms.map, evsel, ann->print_line, ann->full_paths,0 ,0 ); } -static void hists__find_annotations (struct hists *self,int evidx, +static void hists__find_annotations (struct hists *self, +struct perf_evsel *evsel,struct perf_annotate *ann) {struct rb_node *nd =rb_first (&self->entries), *next;
@@ -139,7 +141,7 @@ find_next: }if (use_browser >0 ) { - key =hist_entry__tui_annotate (he, evidx,NULL ); + key =hist_entry__tui_annotate (he, evsel,NULL );switch (key) {case K_RIGHT : next =rb_next (nd);
@@ -154,7 +156,7 @@ find_next:if (next !=NULL ) nd = next; }else { -hist_entry__tty_annotate (he, evidx, ann); +hist_entry__tty_annotate (he, evsel, ann); nd =rb_next (nd);/* * Since we have a hist_entry per IP for the same
@@ -216,7 +218,7 @@ static int __cmd_annotate(struct perf_annotate *ann) total_nr_samples += nr_samples;hists__collapse_resort (hists);hists__output_resort (hists); -hists__find_annotations (hists, pos->idx, ann); +hists__find_annotations (hists, pos, ann); } }
tools/perf/builtin-top.c +1 -1
@@ -251,7 +251,7 @@ static void perf_top__show_details(struct perf_top *top)printf ("Showing %s for %s\n" ,perf_evsel__name (top->sym_evsel), symbol->name);printf (" Events Pcnt (>=%d%%)\n" , top->sym_pcnt_filter); - more =symbol__annotate_printf (symbol, he->ms.map, top->sym_evsel->idx, + more =symbol__annotate_printf (symbol, he->ms.map, top->sym_evsel,0 , top->sym_pcnt_filter, top->print_entries,4 );if (top->zero)symbol__annotate_zero_histogram (symbol, top->sym_evsel->idx);
tools/perf/ui/browsers/annotate.c +17 -13
@@ -8,6 +8,7 @@#include "../../util/hist.h" #include "../../util/sort.h" #include "../../util/symbol.h" +#include "../../util/evsel.h" #include <pthread.h> #include <newt.h>
@@ -324,7 +325,7 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, }static void annotate_browser__calc_percent (struct annotate_browser *browser, -int evidx) +struct perf_evsel *evsel) {struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;
@@ -337,7 +338,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,list_for_each_entry (pos, ¬es->src->source, node) {struct browser_disasm_line *bpos =disasm_line__browser (pos); - bpos->percent =disasm_line__calc_percent (pos, sym, evidx); + bpos->percent =disasm_line__calc_percent (pos, sym, evsel->idx);if (bpos->percent <0.01 ) {RB_CLEAR_NODE (&bpos->rb_node);continue ;
@@ -394,7 +395,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser) browser->b.nr_entries = browser->nr_asm_entries; } -static bool annotate_browser__callq (struct annotate_browser *browser,int evidx, +static bool annotate_browser__callq (struct annotate_browser *browser, +struct perf_evsel *evsel,struct hist_browser_timer *hbt) {struct map_symbol *ms = browser->b.priv;
@@ -425,7 +427,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, int evidx, }pthread_mutex_unlock (¬es->lock); -symbol__tui_annotate (target, ms->map, evidx, hbt); +symbol__tui_annotate (target, ms->map, evsel, hbt);ui_browser__show_title (&browser->b, sym->name);return true; }
@@ -608,7 +610,8 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser browser->addr_width += browser->jumps_width +1 ; } -static int annotate_browser__run (struct annotate_browser *browser,int evidx, +static int annotate_browser__run (struct annotate_browser *browser, +struct perf_evsel *evsel,struct hist_browser_timer *hbt) {struct rb_node *nd =NULL ;
@@ -621,7 +624,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,if (ui_browser__show (&browser->b, sym->name, help) <0 )return -1 ; -annotate_browser__calc_percent (browser, evidx); +annotate_browser__calc_percent (browser, evsel);if (browser->curr_hot) {annotate_browser__set_rb_top (browser, browser->curr_hot);
@@ -634,7 +637,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx, key =ui_browser__run (&browser->b, delay_secs);if (delay_secs !=0 ) { -annotate_browser__calc_percent (browser, evidx); +annotate_browser__calc_percent (browser, evsel);/* * Current line focus got out of the list of most active * lines, NULL it so that if TAB|UNTAB is pressed, we
@@ -650,7 +653,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx, hbt->timer (hbt->arg);if (delay_secs !=0 ) -symbol__annotate_decay_histogram (sym, evidx); +symbol__annotate_decay_histogram (sym, evsel->idx);continue ;case K_TAB :if (nd !=NULL ) {
@@ -747,7 +750,7 @@ show_help: goto show_sup_ins; goto out; }else if (!(annotate_browser__jump (browser) || -annotate_browser__callq (browser, evidx, hbt))) { +annotate_browser__callq (browser, evsel, hbt))) { show_sup_ins:ui_helpline__puts ("Actions are only available for 'callq', 'retq' & jump instructions." ); }
@@ -769,10 +772,10 @@ out:return key; } -int hist_entry__tui_annotate (struct hist_entry *he,int evidx, +int hist_entry__tui_annotate (struct hist_entry *he,struct perf_evsel *evsel,struct hist_browser_timer *hbt) { -return symbol__tui_annotate (he->ms.sym, he->ms.map, evidx, hbt); +return symbol__tui_annotate (he->ms.sym, he->ms.map, evsel, hbt); } static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
@@ -827,7 +830,8 @@ static inline int width_jumps(int n)return 1 ; } -int symbol__tui_annotate (struct symbol *sym,struct map *map,int evidx, +int symbol__tui_annotate (struct symbol *sym,struct map *map, +struct perf_evsel *evsel,struct hist_browser_timer *hbt) {struct disasm_line *pos, *n;
@@ -910,7 +914,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,annotate_browser__update_addr_width (&browser); - ret =annotate_browser__run (&browser, evidx, hbt); + ret =annotate_browser__run (&browser, evsel, hbt);list_for_each_entry_safe (pos, n, ¬es->src->source, node) {list_del (&pos->node);disasm_line__free (pos);
tools/perf/ui/browsers/hists.c +1 -1
@@ -1439,7 +1439,7 @@ do_annotate:* Don't let this be freed, say, by hists__decay_entry. */ he->used = true; - err =hist_entry__tui_annotate (he, evsel->idx, hbt); + err =hist_entry__tui_annotate (he, evsel, hbt); he->used = false;/* * offer option to annotate the other branch source or target
tools/perf/util/annotate.c +18 -15
@@ -14,6 +14,7 @@#include "symbol.h" #include "debug.h" #include "annotate.h" +#include "evsel.h" #include <pthread.h> #include <linux/bitops.h>
@@ -635,7 +636,7 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa }static int disasm_line__print (struct disasm_line *dl,struct symbol *sym,u64 start, -int evidx,u64 len,int min_pcnt,int printed, +struct perf_evsel *evsel,u64 len,int min_pcnt,int printed,int max_lines,struct disasm_line *queue) {static const char *prev_line;
@@ -648,7 +649,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 stconst char *color;struct annotation *notes =symbol__annotation (sym);struct source_line *src_line = notes->src->lines; -struct sym_hist *h =annotation__histogram (notes, evidx); +struct sym_hist *h =annotation__histogram (notes, evsel->idx);s64 offset = dl->offset;const u64 addr = start + offset;struct disasm_line *next;
@@ -680,7 +681,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 stlist_for_each_entry_from (queue, ¬es->src->source, node) {if (queue == dl)break ; -disasm_line__print (queue, sym, start, evidx, len, +disasm_line__print (queue, sym, start, evsel, len,0 ,0 ,1 ,NULL ); } }
@@ -967,7 +968,8 @@ static void symbol__free_source_line(struct symbol *sym, int len)/* Get the filename:line for the colored entries */ static int symbol__get_source_line (struct symbol *sym,struct map *map, -int evidx,struct rb_root *root,int len, +struct perf_evsel *evsel, +struct rb_root *root,int len,const char *filename) {u64 start;
@@ -975,7 +977,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,char cmd[PATH_MAX *2 ];struct source_line *src_line;struct annotation *notes =symbol__annotation (sym); -struct sym_hist *h =annotation__histogram (notes, evidx); +struct sym_hist *h =annotation__histogram (notes, evsel->idx);struct rb_root tmp_root =RB_ROOT ;if (!h->sum)
@@ -1050,10 +1052,10 @@ static void print_summary(struct rb_root *root, const char *filename) } } -static void symbol__annotate_hits (struct symbol *sym,int evidx) +static void symbol__annotate_hits (struct symbol *sym,struct perf_evsel *evsel) {struct annotation *notes =symbol__annotation (sym); -struct sym_hist *h =annotation__histogram (notes, evidx); +struct sym_hist *h =annotation__histogram (notes, evsel->idx);u64 len =symbol__size (sym), offset;for (offset =0 ; offset < len; ++offset)
@@ -1063,9 +1065,9 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)printf ("%*s: %" PRIu64"\n" ,BITS_PER_LONG /2 ,"h->sum" , h->sum); } -int symbol__annotate_printf (struct symbol *sym,struct map *map,int evidx, -bool full_paths,int min_pcnt,int max_lines, -int context) +int symbol__annotate_printf (struct symbol *sym,struct map *map, +struct perf_evsel *evsel,bool full_paths, +int min_pcnt,int max_lines,int context) {struct dso *dso = map->dso;char *filename;
@@ -1092,7 +1094,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,printf ("------------------------------------------------\n" );if (verbose) -symbol__annotate_hits (sym, evidx); +symbol__annotate_hits (sym, evsel);list_for_each_entry (pos, ¬es->src->source, node) {if (context && queue ==NULL ) {
@@ -1100,7 +1102,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, queue_len =0 ; } -switch (disasm_line__print (pos, sym, start, evidx, len, +switch (disasm_line__print (pos, sym, start, evsel, len, min_pcnt, printed, max_lines, queue)) {case 0 :
@@ -1195,7 +1197,8 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)return printed; } -int symbol__tty_annotate (struct symbol *sym,struct map *map,int evidx, +int symbol__tty_annotate (struct symbol *sym,struct map *map, +struct perf_evsel *evsel,bool print_lines,bool full_paths,int min_pcnt,int max_lines) {
@@ -1210,12 +1213,12 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, len =symbol__size (sym);if (print_lines) { -symbol__get_source_line (sym, map, evidx, &source_line, +symbol__get_source_line (sym, map, evsel, &source_line, len, filename);print_summary (&source_line, filename); } -symbol__annotate_printf (sym, map, evidx, full_paths, +symbol__annotate_printf (sym, map, evsel, full_paths, min_pcnt, max_lines,0 );if (print_lines)symbol__free_source_line (sym, len);
tools/perf/util/annotate.h +9 -8
@@ -129,24 +129,25 @@ void symbol__annotate_zero_histograms(struct symbol *sym);int symbol__annotate (struct symbol *sym,struct map *map,size_t privsize);int symbol__annotate_init (struct map *map__maybe_unused ,struct symbol *sym); -int symbol__annotate_printf (struct symbol *sym,struct map *map,int evidx, -bool full_paths,int min_pcnt,int max_lines, -int context); +int symbol__annotate_printf (struct symbol *sym,struct map *map, +struct perf_evsel *evsel,bool full_paths, +int min_pcnt,int max_lines,int context);void symbol__annotate_zero_histogram (struct symbol *sym,int evidx);void symbol__annotate_decay_histogram (struct symbol *sym,int evidx);void disasm__purge (struct list_head *head); -int symbol__tty_annotate (struct symbol *sym,struct map *map,int evidx, -bool print_lines,bool full_paths,int min_pcnt, -int max_lines); +int symbol__tty_annotate (struct symbol *sym,struct map *map, +struct perf_evsel *evsel,bool print_lines, +bool full_paths,int min_pcnt,int max_lines);#ifdef NEWT_SUPPORT -int symbol__tui_annotate (struct symbol *sym,struct map *map,int evidx, +int symbol__tui_annotate (struct symbol *sym,struct map *map, +struct perf_evsel *evsel,struct hist_browser_timer *hbt);#else static inline int symbol__tui_annotate (struct symbol *sym__maybe_unused ,struct map *map__maybe_unused , -int evidx__maybe_unused , +struct perf_evsel *evsel__maybe_unused ,struct hist_browser_timer *hbt__maybe_unused ) {
tools/perf/util/hist.h +3 -2
@@ -167,7 +167,7 @@ struct hist_browser_timer {#ifdef NEWT_SUPPORT #include "../ui/keysyms.h" -int hist_entry__tui_annotate (struct hist_entry *he,int evidx, +int hist_entry__tui_annotate (struct hist_entry *he,struct perf_evsel *evsel,struct hist_browser_timer *hbt); int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
@@ -186,7 +186,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,static inline int hist_entry__tui_annotate (struct hist_entry *self__maybe_unused , -int evidx__maybe_unused , +struct perf_evsel *evsel +__maybe_unused ,struct hist_browser_timer *hbt__maybe_unused ) {
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 6/13 perf annotate: Factor out disasm__calc_percent()
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Factor out calculation of histogram of a symbol into disasm__calc_percent. It'll be used for event group view.
--- tools/perf/util/annotate.c | 52 +++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 17 deletions(-)
tools/perf/util/annotate.c +35 -17
@@ -635,6 +635,38 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disareturn NULL ; } +static void disasm__calc_percent (struct symbol *sym,struct perf_evsel *evsel, +s64 from,s64 to,const char **path, +double *percent) +{ +struct annotation *notes =symbol__annotation (sym); +struct source_line *src_line = notes->src->lines; +struct sym_hist *h; +unsigned int hits =0 ; +s64 offset = from; + + *percent =0.0 ; + +if (src_line) { +while (offset < to) { +if (*path ==NULL ) + *path = src_line[offset].path; + + *percent += src_line[offset].percent; + ++offset; + } + }else { + h =annotation__histogram (notes, evsel->idx); + +while (offset < to) { + hits += h->addr[offset]; + } + +if (h->sum) + *percent =100.0 * hits / h->sum; + } +} +static int disasm_line__print (struct disasm_line *dl,struct symbol *sym,u64 start,struct perf_evsel *evsel,u64 len,int min_pcnt,int printed,int max_lines,struct disasm_line *queue)
@@ -644,32 +676,18 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 stif (dl->offset !=-1 ) {const char *path =NULL ; -unsigned int hits =0 ;double percent =0.0 ;const char *color;struct annotation *notes =symbol__annotation (sym); -struct source_line *src_line = notes->src->lines; -struct sym_hist *h =annotation__histogram (notes, evsel->idx);s64 offset = dl->offset;const u64 addr = start + offset;struct disasm_line *next; next =disasm__get_next_ip_line (¬es->src->source, dl); -while (offset < (s64 )len && - (next ==NULL || offset < next->offset)) { -if (src_line) { -if (path ==NULL ) - path = src_line[offset].path; - percent += src_line[offset].percent; - }else - hits += h->addr[offset]; - - ++offset; - } - -if (src_line ==NULL && h->sum) - percent =100.0 * hits / h->sum; +disasm__calc_percent (sym, evsel, offset, + next ? next->offset : (s64 ) len, + &path, &percent);if (percent < min_pcnt)return -1 ;
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 7/13 perf annotate: Basic support for event group view
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Add support for event group view when symbol_conf.event_group enabled.
--- tools/perf/util/annotate.c | 86 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 17 deletions(-)
tools/perf/util/annotate.c +69 -17
@@ -637,15 +637,17 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disastatic void disasm__calc_percent (struct symbol *sym,struct perf_evsel *evsel,s64 from,s64 to,const char **path, -double *percent) +double *percent,int nr_percent) {struct annotation *notes =symbol__annotation (sym);struct source_line *src_line = notes->src->lines;struct sym_hist *h; -unsigned int hits =0 ; +unsigned int hits;s64 offset = from; +int evidx = evsel->idx; +int i; - *percent =0.0 ; +memset (percent,0 ,sizeof (percent) * nr_percent);if (src_line) {while (offset < to) {
@@ -656,14 +658,19 @@ static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel, ++offset; } }else { - h =annotation__histogram (notes, evsel->idx); +for (i =0 ; i < nr_percent; i++) { + hits =0 ; + offset = from; + h =annotation__histogram (notes, evidx + i); + +while (offset < to) { + hits += h->addr[offset]; + offset++; + } -while (offset < to) { - hits += h->addr[offset]; +if (h->sum) + percent[i] =100.0 * hits / h->sum; } - -if (h->sum) - *percent =100.0 * hits / h->sum; } }
@@ -677,19 +684,39 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 stif (dl->offset !=-1 ) {const char *path =NULL ;double percent =0.0 ; +double percent_max =0.0 ; +double *ppercents = &percent; +int i, nr_percents =1 ;const char *color;struct annotation *notes =symbol__annotation (sym);s64 offset = dl->offset;const u64 addr = start + offset;struct disasm_line *next; +if (symbol_conf.event_group) { +if (perf_evsel__is_group_leader (evsel) && + evsel->nr_members >0 ) { + nr_percents = evsel->nr_members +1 ; + ppercents =calloc (nr_percents,sizeof (double )); +if (ppercents ==NULL ) +return -1 ; + } + } + next =disasm__get_next_ip_line (¬es->src->source, dl);disasm__calc_percent (sym, evsel, offset, next ? next->offset : (s64 ) len, - &path, &percent); + &path, ppercents, nr_percents); + +for (i =0 ; i < nr_percents; i++) { + percent = ppercents[i]; + +if (percent > percent_max) + percent_max = percent; + } -if (percent < min_pcnt) +if (percent_max < min_pcnt)return -1 ;if (max_lines && printed >= max_lines)
@@ -704,7 +731,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st } } - color =get_percent_color (percent); + color =get_percent_color (percent_max);/* * Also color the filename and line if needed, with
@@ -720,20 +747,35 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st } } -color_fprintf (stdout, color," %7.2f" , percent); +for (i =0 ; i < nr_percents; i++) { + percent = ppercents[i]; + color =get_percent_color (percent); +color_fprintf (stdout, color," %7.2f" , percent); + } +printf (" : " );color_fprintf (stdout,PERF_COLOR_MAGENTA ," %" PRIx64":" , addr);color_fprintf (stdout,PERF_COLOR_BLUE ,"%s\n" , dl->line); + +if (ppercents != &percent) +free (ppercents); }else if (max_lines && printed >= max_lines)return 1 ;else { +int width =8 ; +if (queue)return -1 ; +if (symbol_conf.event_group) { +if (perf_evsel__is_group_leader (evsel)) + width *= evsel->nr_members +1 ; + } +if (!*dl->line) -printf (" :\n" ); +printf (" %*s:\n" , width," " );else -printf (" : %s\n" , dl->line); +printf (" %*s: %s\n" , width," " , dl->line); }return 0 ;
@@ -1096,6 +1138,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,int printed =2 , queue_len =0 ;int more =0 ;u64 len; +int width =8 ; +int namelen; filename =strdup (dso->long_name);if (!filename)
@@ -1108,8 +1152,16 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, len =symbol__size (sym); -printf (" Percent | Source code & Disassembly of %s\n" , d_filename); -printf ("------------------------------------------------\n" ); +if (symbol_conf.event_group) { +if (perf_evsel__is_group_leader (evsel)) + width *= evsel->nr_members +1 ; + } + namelen =strlen (d_filename); + +printf (" %-*.*s| Source code & Disassembly of %s\n" , + width, width,"Percent" , d_filename); +printf ("-%-*.*s-------------------------------------\n" , + width + namelen, width + namelen, graph_dotted_line);if (verbose)symbol__annotate_hits (sym, evsel);
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 8/13 perf annotate: Factor out struct source_line_percent
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
The source_line_percent struct contains percentage value of the symbol histogram. This is a preparation of event group view change.
--- tools/perf/ui/browsers/annotate.c | 2 +- tools/perf/util/annotate.c | 14 +++++++------- tools/perf/util/annotate.h | 8 ++++++-- 3 files changed, 14 insertions(+), 10 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -1
@@ -250,7 +250,7 @@ static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *swhile (offset < (s64 )len && (next ==NULL || offset < next->offset)) {if (src_line) { - percent += src_line[offset].percent; + percent += src_line[offset].p[0 ].percent; }else hits += h->addr[offset];
tools/perf/util/annotate.c +7 -7
@@ -654,7 +654,7 @@ static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,if (*path ==NULL ) *path = src_line[offset].path; - *percent += src_line[offset].percent; + *percent += src_line[offset].p[0 ].percent; ++offset; } }else {
@@ -959,7 +959,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin ret =strcmp (iter->path, src_line->path);if (ret ==0 ) { - iter->percent_sum += src_line->percent; + iter->p[0 ].percent_sum += src_line->p[0 ].percent;return ; }
@@ -969,7 +969,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin p = &(*p)->rb_right; } - src_line->percent_sum = src_line->percent; + src_line->p[0 ].percent_sum = src_line->p[0 ].percent;rb_link_node (&src_line->node, parent, p);rb_insert_color (&src_line->node, root);
@@ -985,7 +985,7 @@ static void __resort_source_line(struct rb_root *root, struct source_line *src_l parent = *p; iter = rb_entry(parent, struct source_line, node); -if (src_line->percent_sum > iter->percent_sum) +if (src_line->p[0 ].percent_sum > iter->p[0 ].percent_sum) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -1055,8 +1055,8 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,u64 offset;FILE *fp; - src_line[i].percent =100.0 * h->addr[i] / h->sum; -if (src_line[i].percent <=0.5 ) + src_line[i].p[0 ].percent =100.0 * h->addr[i] / h->sum; +if (src_line[i].p[0 ].percent <=0.5 )continue ; offset = start + i;
@@ -1103,7 +1103,7 @@ static void print_summary(struct rb_root *root, const char *filename)char *path; src_line = rb_entry(node, struct source_line, node); - percent = src_line->percent_sum; + percent = src_line->p[0 ].percent_sum; color =get_percent_color (percent); path = src_line->path;
tools/perf/util/annotate.h +6 -2
@@ -73,11 +73,15 @@ struct sym_hist {u64 addr[0 ]; }; -struct source_line { -struct rb_node node; +struct source_line_percent {double percent;double percent_sum; +}; + +struct source_line { +struct rb_node node;char *path; +struct source_line_percent p[1 ]; };/** struct annotated_source - symbols with hits have this attached as in sannotation
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 9/13 perf annotate: Support event group view for --print-line
In reply to Namhyung KimDynamically 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.
--- tools/perf/util/annotate.c | 123 +++++++++++++++++++++++++++++++++----------- tools/perf/util/annotate.h | 1 + 2 files changed, 95 insertions(+), 29 deletions(-)
tools/perf/util/annotate.c +94 -29
@@ -650,11 +650,19 @@ static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,memset (percent,0 ,sizeof (percent) * nr_percent);if (src_line) { +size_t sizeof_src_line =sizeof (*src_line) + +sizeof (src_line->p) * (src_line->nr_pcnt -1 ); +while (offset < to) { -if (*path ==NULL ) - *path = src_line[offset].path; + src_line = (void *)notes->src->lines + + (sizeof_src_line * offset); + +if (path && *path ==NULL ) + *path = src_line->path; + +for (i =0 ; i < nr_percent; i++) + percent[i] += src_line->p[i].percent; - *percent += src_line[offset].p[0 ].percent; ++offset; } }else {
@@ -951,7 +959,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linstruct source_line *iter;struct rb_node **p = &root->rb_node;struct rb_node *parent =NULL ; -int ret; +int i, ret;while (*p !=NULL ) { parent = *p;
@@ -959,7 +967,8 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin ret =strcmp (iter->path, src_line->path);if (ret ==0 ) { - iter->p[0 ].percent_sum += src_line->p[0 ].percent; +for (i =0 ; i < src_line->nr_pcnt; i++) + iter->p[i].percent_sum += src_line->p[i].percent;return ; }
@@ -969,12 +978,26 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin p = &(*p)->rb_right; } - src_line->p[0 ].percent_sum = src_line->p[0 ].percent; +for (i =0 ; i < src_line->nr_pcnt; i++) + src_line->p[i].percent_sum = src_line->p[i].percent;rb_link_node (&src_line->node, parent, p);rb_insert_color (&src_line->node, root); } +static int cmp_source_line (struct source_line *a,struct source_line *b) +{ +int i; + +for (i =0 ; i < a->nr_pcnt; i++) { +if (a->p[i].percent_sum == b->p[i].percent_sum) +continue ; +return a->p[i].percent_sum > b->p[i].percent_sum; + } + +return 0 ; +} +static void __resort_source_line (struct rb_root *root,struct source_line *src_line) {struct source_line *iter;
@@ -985,7 +1008,7 @@ static void __resort_source_line(struct rb_root *root, struct source_line *src_l parent = *p; iter = rb_entry(parent, struct source_line, node); -if (src_line->p[0 ].percent_sum > iter->p[0 ].percent_sum) +if (cmp_source_line (src_line, iter)) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -1017,12 +1040,18 @@ static void symbol__free_source_line(struct symbol *sym, int len) {struct annotation *notes =symbol__annotation (sym);struct source_line *src_line = notes->src->lines; +size_t sizeof_src_line;int i; -for (i =0 ; i < len; i++) -free (src_line[i].path); + sizeof_src_line =sizeof (*src_line) + + (sizeof (src_line->p) * (src_line->nr_pcnt -1 )); -free (src_line); +for (i =0 ; i < len; i++) { +free (src_line->path); + src_line = (void *)src_line + sizeof_src_line; + } + +free (notes->src->lines); notes->src->lines =NULL ; }
@@ -1033,17 +1062,32 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, const char *filename) {u64 start; -int i; +int i, k; +int evidx = evsel->idx;char cmd[PATH_MAX *2 ];struct source_line *src_line;struct annotation *notes =symbol__annotation (sym); -struct sym_hist *h =annotation__histogram (notes, evsel->idx); +struct sym_hist *h =annotation__histogram (notes, evidx);struct rb_root tmp_root =RB_ROOT ; +int nr_pcnt =1 ; +u64 h_sum = h->sum; +size_t sizeof_src_line =sizeof (struct source_line ); -if (!h->sum) +if (symbol_conf.event_group) { +if (perf_evsel__is_group_leader (evsel)) { +for (i =0 ; i < evsel->nr_members; i++) { + h =annotation__histogram (notes, evidx + i); + h_sum += h->sum; + } + nr_pcnt += evsel->nr_members; + sizeof_src_line += (nr_pcnt -1 ) *sizeof (src_line->p); + } + } + +if (!h_sum)return 0 ; - src_line = notes->src->lines =calloc (len,sizeof (struct source_line )); + src_line = notes->src->lines =calloc (len, sizeof_src_line);if (!notes->src->lines)return -1 ;
@@ -1054,29 +1098,41 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,size_t line_len;u64 offset;FILE *fp; +double percent_max =0.0 ; - src_line[i].p[0 ].percent =100.0 * h->addr[i] / h->sum; -if (src_line[i].p[0 ].percent <=0.5 ) -continue ; + src_line->nr_pcnt = nr_pcnt; + +for (k =0 ; k < nr_pcnt; k++) { + h =annotation__histogram (notes, evidx + k); + src_line->p[k].percent =100.0 * h->addr[i] / h->sum; + +if (src_line->p[k].percent > percent_max) + percent_max = src_line->p[k].percent; + } + +if (percent_max <=0.5 ) + goto next; offset = start + i;sprintf (cmd,"addr2line -e %s %016" PRIx64, filename, offset); fp =popen (cmd,"r" );if (!fp) -continue ; + goto next;if (getline (&path, &line_len, fp) <0 || !line_len) - goto next; + goto next_close; - src_line[i].path =malloc (sizeof (char ) * line_len +1 ); -if (!src_line[i].path) - goto next; + src_line->path =malloc (sizeof (char ) * line_len +1 ); +if (!src_line->path) + goto next_close; -strcpy (src_line[i].path, path); -insert_source_line (&tmp_root, &src_line[i]); +strcpy (src_line->path, path); +insert_source_line (&tmp_root, src_line); - next: + next_close:pclose (fp); + next: + src_line = (void *)src_line + sizeof_src_line; }resort_source_line (root, &tmp_root);
@@ -1098,16 +1154,25 @@ static void print_summary(struct rb_root *root, const char *filename) node =rb_first (root);while (node) { -double percent; +double percent, percent_max =0.0 ;const char *color;char *path; +int i; src_line = rb_entry(node, struct source_line, node); - percent = src_line->p[0 ].percent_sum; - color =get_percent_color (percent); +for (i =0 ; i < src_line->nr_pcnt; i++) { + percent = src_line->p[i].percent_sum; + color =get_percent_color (percent); +color_fprintf (stdout, color," %7.2f" , percent); + +if (percent > percent_max) + percent_max = percent; + } + path = src_line->path; + color =get_percent_color (percent_max); +color_fprintf (stdout, color," %s" , path); -color_fprintf (stdout, color," %7.2f %s" , percent, path); node =rb_next (node); } }
tools/perf/util/annotate.h +1 -0
@@ -81,6 +81,7 @@ struct source_line_percent {struct source_line {struct rb_node node;char *path; +int nr_pcnt;struct source_line_percent p[1 ]; };
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 10/13 perf annotate browser: Make browser_disasm_line->percent an array
In reply to Namhyung KimMake percent field of struct browser_disasm_line an array and move it to the last. This is a preparation of event group view feature.
--- tools/perf/ui/browsers/annotate.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
tools/perf/ui/browsers/annotate.c +7 -7
@@ -14,10 +14,10 @@struct browser_disasm_line {struct rb_node rb_node; -double percent;u32 idx;int idx_asm;int jump_sources; +double percent[1 ]; }; static struct annotate_browser_opt {
@@ -97,9 +97,9 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intint width = browser->width, printed;char bf[256 ]; -if (dl->offset !=-1 && bdl->percent !=0.0 ) { -ui_browser__set_percent_color (browser, bdl->percent, current_entry); -slsmg_printf ("%6.2f " , bdl->percent); +if (dl->offset !=-1 && bdl->percent[0 ] !=0.0 ) { +ui_browser__set_percent_color (browser, bdl->percent[0 ], current_entry); +slsmg_printf ("%6.2f " , bdl->percent[0 ]); }else {ui_browser__set_percent_color (browser,0 , current_entry);slsmg_write_nstring (" " ,7 );
@@ -276,7 +276,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_lwhile (*p !=NULL ) { parent = *p; l = rb_entry(parent, struct browser_disasm_line, rb_node); -if (bdl->percent < l->percent) +if (bdl->percent[0 ] < l->percent[0 ]) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -338,8 +338,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,list_for_each_entry (pos, ¬es->src->source, node) {struct browser_disasm_line *bpos =disasm_line__browser (pos); - bpos->percent =disasm_line__calc_percent (pos, sym, evsel->idx); -if (bpos->percent <0.01 ) { + bpos->percent[0 ] =disasm_line__calc_percent (pos, sym, evsel->idx); +if (bpos->percent[0 ] <0.01 ) {RB_CLEAR_NODE (&bpos->rb_node);continue ; }
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 11/13 perf annotate browser: Use disasm__calc_percent()
In reply to Namhyung KimThe disasm_line__calc_percent() which was used by annotate browser code almost duplicates disasm__calc_percent. Since the latter can handle multiple events properly, use it and get rid of the code duplication.
--- tools/perf/ui/browsers/annotate.c | 50 +++++++++++-------------------------- tools/perf/util/annotate.c | 6 ++--- tools/perf/util/annotate.h | 3 +++ 3 files changed, 20 insertions(+), 39 deletions(-)
tools/perf/ui/browsers/annotate.c +14 -36
@@ -233,40 +233,6 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)return ret; } -static double disasm_line__calc_percent (struct disasm_line *dl,struct symbol *sym,int evidx) -{ -double percent =0.0 ; - -if (dl->offset !=-1 ) { -int len = sym->end - sym->start; -unsigned int hits =0 ; -struct annotation *notes =symbol__annotation (sym); -struct source_line *src_line = notes->src->lines; -struct sym_hist *h =annotation__histogram (notes, evidx); -s64 offset = dl->offset; -struct disasm_line *next; - - next =disasm__get_next_ip_line (¬es->src->source, dl); -while (offset < (s64 )len && - (next ==NULL || offset < next->offset)) { -if (src_line) { - percent += src_line[offset].p[0 ].percent; - }else - hits += h->addr[offset]; - - ++offset; - } -/* -* If the percentage wasn't already calculated in -* symbol__get_source_line, do it now: -*/ -if (src_line ==NULL && h->sum) - percent =100.0 * hits / h->sum; - } - -return percent; -} -static void disasm_rb_tree__insert (struct rb_root *root,struct browser_disasm_line *bdl) {struct rb_node **p = &root->rb_node;
@@ -330,7 +296,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -struct disasm_line *pos; +struct disasm_line *pos, *next; +u64 len = sym->end - sym->start; browser->entries =RB_ROOT ;
@@ -338,7 +305,18 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,list_for_each_entry (pos, ¬es->src->source, node) {struct browser_disasm_line *bpos =disasm_line__browser (pos); - bpos->percent[0 ] =disasm_line__calc_percent (pos, sym, evsel->idx); + +if (pos->offset ==-1 ) { +RB_CLEAR_NODE (&bpos->rb_node); +continue ; + } + + next =disasm__get_next_ip_line (¬es->src->source, pos); + +disasm__calc_percent (sym, evsel, pos->offset, + next ? next->offset : (s64 ) len, +NULL , bpos->percent,1 ); +if (bpos->percent[0 ] <0.01 ) {RB_CLEAR_NODE (&bpos->rb_node);continue ;
tools/perf/util/annotate.c +3 -3
@@ -635,9 +635,9 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disareturn NULL ; } -static void disasm__calc_percent (struct symbol *sym,struct perf_evsel *evsel, -s64 from,s64 to,const char **path, -double *percent,int nr_percent) +void disasm__calc_percent (struct symbol *sym,struct perf_evsel *evsel, +s64 from,s64 to,const char **path, +double *percent,int nr_percent) {struct annotation *notes =symbol__annotation (sym);struct source_line *src_line = notes->src->lines;
tools/perf/util/annotate.h +3 -0
@@ -67,6 +67,9 @@ void disasm_line__free(struct disasm_line *dl);struct disasm_line *disasm__get_next_ip_line (struct list_head *head,struct disasm_line *pos);int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp); +void disasm__calc_percent (struct symbol *sym,struct perf_evsel *evsel, +s64 from,s64 to,const char **path, +double *percent,int nr_percent);struct sym_hist {u64 sum;
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 12/13 perf annotate browser: Support event group view on TUI
In reply to Namhyung KimDynamically allocate browser_disasm_line according to a number of group members and save nr_pcnt to the struct. This way we can handle multiple events in a general manner.
--- tools/perf/ui/browsers/annotate.c | 69 ++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 12 deletions(-)
tools/perf/ui/browsers/annotate.c +57 -12
@@ -17,6 +17,7 @@ struct browser_disasm_line {u32 idx;int idx_asm;int jump_sources; +int nr_pcnt;double percent[1 ]; };
@@ -95,14 +96,25 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int (!current_entry || (browser->use_navkeypressed && !browser->navkeypressed)));int width = browser->width, printed; +int i, pcnt_width =7 * bdl->nr_pcnt; +double percent_max =0.0 ;char bf[256 ]; -if (dl->offset !=-1 && bdl->percent[0 ] !=0.0 ) { -ui_browser__set_percent_color (browser, bdl->percent[0 ], current_entry); -slsmg_printf ("%6.2f " , bdl->percent[0 ]); +for (i =0 ; i < bdl->nr_pcnt; i++) { +if (bdl->percent[i] > percent_max) + percent_max = bdl->percent[i]; + } + +if (dl->offset !=-1 && percent_max !=0.0 ) { +for (i =0 ; i < bdl->nr_pcnt; i++) { +ui_browser__set_percent_color (browser, + bdl->percent[i], + current_entry); +slsmg_printf ("%6.2f " , bdl->percent[i]); + } }else {ui_browser__set_percent_color (browser,0 , current_entry); -slsmg_write_nstring (" " ,7 ); +slsmg_write_nstring (" " , pcnt_width); }SLsmg_write_char (' ' );
@@ -112,14 +124,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int width +=1 ;if (!*dl->line) -slsmg_write_nstring (" " , width -7 ); +slsmg_write_nstring (" " , width - pcnt_width);else if (dl->offset ==-1 ) { printed =scnprintf (bf,sizeof (bf),"%*s " , ab->addr_width," " );slsmg_write_nstring (bf, printed); -slsmg_write_nstring (dl->line, width - printed -6 ); +slsmg_write_nstring (dl->line, width - printed - pcnt_width +1 ); }else if (!dl->name) { -slsmg_write_nstring (" " , width -7 ); +slsmg_write_nstring (" " , width - pcnt_width); }else {u64 addr = dl->offset;int color =-1 ;
@@ -178,7 +190,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int }disasm_line__scnprintf (dl, bf,sizeof (bf), !annotate_browser__opts.use_offset); -slsmg_write_nstring (bf, width -10 - printed); +slsmg_write_nstring (bf, width - pcnt_width -3 - printed); }if (current_entry)
@@ -193,6 +205,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)unsigned int from, to;struct map_symbol *ms = ab->b.priv;struct symbol *sym = ms->sym; +u8 pcnt_width =7 ;/* PLT symbols contain external offsets */ if (strstr (sym->name,"@plt" ))
@@ -217,22 +230,43 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) to = (u64 )btarget->idx; } + pcnt_width *= bcursor->nr_pcnt; +ui_browser__set_color (browser,HE_COLORSET_CODE ); -__ui_browser__line_arrow (browser,9 + ab->addr_width, from, to); +__ui_browser__line_arrow (browser, pcnt_width +2 + ab->addr_width, + from, to); }static unsigned int annotate_browser__refresh (struct ui_browser *browser) { + struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); +struct disasm_line *cursor = ab->offsets[0 ]; +struct browser_disasm_line *bcursor =disasm_line__browser (cursor);int ret =ui_browser__list_head_refresh (browser); +int pcnt_width =7 * bcursor->nr_pcnt;if (annotate_browser__opts.jump_arrows)annotate_browser__draw_current_jump (browser);ui_browser__set_color (browser,HE_COLORSET_NORMAL ); -__ui_browser__vline (browser,7 ,0 , browser->height -1 ); +__ui_browser__vline (browser, pcnt_width,0 , browser->height -1 );return ret; } +static int disasm__cmp (struct browser_disasm_line *a, +struct browser_disasm_line *b) +{ +int i; + +for (i =0 ; i < a->nr_pcnt; i++) { +if (a->percent[i] == b->percent[i]) +continue ; +return a->percent[i] < b->percent[i]; + } + +return 0 ; +} +static void disasm_rb_tree__insert (struct rb_root *root,struct browser_disasm_line *bdl) {struct rb_node **p = &root->rb_node;
@@ -242,7 +276,8 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_lwhile (*p !=NULL ) { parent = *p; l = rb_entry(parent, struct browser_disasm_line, rb_node); -if (bdl->percent[0 ] < l->percent[0 ]) + +if (disasm__cmp (bdl, l)) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -830,6 +865,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, }, };int ret =-1 ; +int nr_pcnt =1 ; +size_t sizeof_bdl =sizeof (struct browser_disasm_line );if (sym ==NULL )return -1 ;
@@ -845,7 +882,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,return -1 ; } -if (symbol__annotate (sym, map,sizeof (struct browser_disasm_line )) <0 ) { +if (symbol_conf.event_group) { +if (perf_evsel__is_group_leader (evsel)) { + sizeof_bdl +=sizeof (double ) * evsel->nr_members; + nr_pcnt += evsel->nr_members; + } + } + +if (symbol__annotate (sym, map, sizeof_bdl) <0 ) {ui__error ("%s" , ui_helpline__last_msg); goto out_free_offsets; }
@@ -862,6 +906,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (browser.b.width < line_len) browser.b.width = line_len; bpos =disasm_line__browser (pos); + bpos->nr_pcnt = nr_pcnt; bpos->idx = browser.nr_entries++;if (pos->offset !=-1 ) { bpos->idx_asm = browser.nr_asm_entries++;
Signature · 1 line
1.7.9.2
Namhyung Kim
maintainerPATCH 13/13 perf annotate: Add --group option
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
Add --group option to enable event grouping. When enabled, all the group members information will be shown together with the leader so skip non-leader events.
--- tools/perf/builtin-annotate.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/perf/builtin-annotate.c +6 -0
@@ -214,6 +214,10 @@ static int __cmd_annotate(struct perf_annotate *ann)struct hists *hists = &pos->hists;u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE ]; +if (symbol_conf.event_group && + !perf_evsel__is_group_leader (pos)) +continue ; +if (nr_samples >0 ) { total_nr_samples += nr_samples;hists__collapse_resort (hists);
@@ -293,6 +297,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) "Specify disassembler style (e.g. -M intel for intel syntax)"),OPT_STRING (0 ,"objdump" , &objdump_path,"path" ,"objdump binary to use for disassembly and annotations" ), +OPT_BOOLEAN (0 ,"group" , &symbol_conf.event_group, +"Show event grou information together" ), OPT_END() };
Signature · 1 line
1.7.9.2