Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753831AbdF1DOc (ORCPT ); Tue, 27 Jun 2017 23:14:32 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:33131 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753728AbdF1DOT (ORCPT ); Tue, 27 Jun 2017 23:14:19 -0400 From: Taeung Song To: Arnaldo Carvalho de Melo Cc: linux-kernel@vger.kernel.org, Milian Wolff , Jiri Olsa , Masami Hiramatsu , Adrian Hunter , Wang Nan , Jin Yao , Andi Kleen , Kim Phillips , David Ahern Subject: [PATCH/RFC 2/4] perf annotate: Add new source code view to the annotate TUI browser Date: Wed, 28 Jun 2017 12:14:12 +0900 Message-Id: <1498619652-763-1-git-send-email-treeze.taeung@gmail.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10649 Lines: 313 Unlike asm code level, the new source code view provides a additional viewpoint based on source code level for performance analysis. Of course, current disassembly view can show itself with pieces of source code but some users want to check the result of performance analysis based on full source code view. So add this view to the annotate TUI browser. Users can switch to the new source code view by a 'S' key and additionally support a 't' key toggling total period view. Suggested-by: Namhyung Kim Cc: Milian Wolff Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Adrian Hunter Cc: Wang Nan Cc: Jin Yao Cc: Andi Kleen Cc: Kim Phillips Cc: David Ahern Signed-off-by: Taeung Song --- tools/perf/ui/browsers/annotate.c | 153 +++++++++++++++++++++++++++++++++++++- tools/perf/util/annotate.c | 6 +- tools/perf/util/annotate.h | 7 ++ 3 files changed, 161 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index b075a32..028febe 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -44,7 +44,7 @@ static struct annotate_browser_opt { struct arch; struct annotate_browser { - struct ui_browser b; + struct ui_browser b, cb; struct rb_root entries; struct rb_node *curr_hot; struct disasm_line *selection; @@ -58,6 +58,7 @@ struct annotate_browser { int nr_jumps; bool searching_backwards; bool have_cycles; + bool has_src_code; u8 addr_width; u8 jumps_width; u8 target_width; @@ -110,6 +111,49 @@ static int annotate_browser__pcnt_width(struct annotate_browser *ab) return w; } +static void annotate_code_browser__write(struct ui_browser *browser, void *entry, int row) +{ + struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb); + struct code_line *cl = list_entry(entry, struct code_line, node); + bool current_entry = ui_browser__is_current_entry(browser, row); + int i, printed; + double percent, max_percent = 0.0; + char line[256]; + + for (i = 0; i < ab->nr_events; i++) { + if (cl->samples_sum[i].percent > max_percent) + max_percent = cl->samples_sum[i].percent; + } + + for (i = 0; i < ab->nr_events; i++) { + if (max_percent == 0.0) { + ui_browser__set_percent_color(browser, 0, current_entry); + ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); + break; + } + + percent = cl->samples_sum[i].percent; + ui_browser__set_percent_color(browser, percent, current_entry); + + if (annotate_browser__opts.show_total_period) + ui_browser__printf(browser, "%6" PRIu64 " ", + cl->samples_sum[i].nr); + else + ui_browser__printf(browser, "%6.2f ", percent); + + if (max_percent < percent) + max_percent = percent; + } + + SLsmg_write_char(' '); + + printed = scnprintf(line, sizeof(line), "%-*d ", + ab->addr_width + 2, cl->line_nr); + + ui_browser__write_nstring(browser, line, printed); + ui_browser__write_nstring(browser, cl->line, browser->width); +} + static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); @@ -304,6 +348,17 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) from, to); } +static unsigned int annotate_code_browser__refresh(struct ui_browser *browser) +{ + struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb); + int ret = ui_browser__list_head_refresh(browser); + int pcnt_width = annotate_browser__pcnt_width(ab); + + ui_browser__set_color(browser, HE_COLORSET_NORMAL); + __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); + return ret; +} + static unsigned int annotate_browser__refresh(struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); @@ -390,6 +445,31 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, browser->curr_hot = nd; } +static void annotate_code_browser__calc_percent(struct annotate_browser *browser, + struct perf_evsel *evsel) +{ + int i; + struct map_symbol *ms = browser->b.priv; + struct symbol *sym = ms->sym; + struct annotation *notes = symbol__annotation(sym); + struct code_line *cl; + struct list_head *code_lines = browser->cb.entries; + + pthread_mutex_lock(¬es->lock); + + list_for_each_entry(cl, code_lines, node) { + for (i = 0; i < browser->nr_events; i++) { + cl->samples_sum[i].percent = 0.0; + cl->samples_sum[i].nr = 0; + } + + for (i = 0; i < cl->nr_matched_dl; i++) + code_line__sum_samples(cl, cl->matched_dl[i], notes, evsel); + } + + pthread_mutex_unlock(¬es->lock); +} + static void annotate_browser__calc_percent(struct annotate_browser *browser, struct perf_evsel *evsel) { @@ -716,6 +796,46 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser browser->addr_width += browser->jumps_width + 1; } +static int annotate_code_browser__run(struct annotate_browser *browser, + struct perf_evsel *evsel, int delay_secs) +{ + int key; + + if (ui_browser__show(&browser->cb, browser->cb.title, ui_helpline__current) < 0) + return -1; + annotate_code_browser__calc_percent(browser, evsel); + + while (1) { + + key = ui_browser__run(&browser->cb, delay_secs); + if (delay_secs != 0) + annotate_code_browser__calc_percent(browser, evsel); + + switch (key) { + case K_F1: + case 'h': + ui_browser__help_window(&browser->cb, + "UP/DOWN/PGUP\n" + "PGDN/SPACE Navigate\n" + "q/ESC/CTRL+C Return to dissembly view\n\n" + "t Toggle total period view\n"); + continue; + case 't': + annotate_browser__opts.show_total_period = + !annotate_browser__opts.show_total_period; + continue; + case K_LEFT: + case K_ESC: + case 'q': + case CTRL('c'): + return 0; + default: + continue; + } + } + return 0; +} + static int annotate_browser__run(struct annotate_browser *browser, struct perf_evsel *evsel, struct hist_browser_timer *hbt) @@ -792,7 +912,8 @@ static int annotate_browser__run(struct annotate_browser *browser, "J Toggle showing number of jump sources on targets\n" "n Search next string\n" "o Toggle disassembler output/simplified view\n" - "s Toggle source code view\n" + "s Toggle pieces of source code view\n" + "S Switch to full source code view\n" "t Toggle total period view\n" "/ Search string\n" "k Toggle line numbers\n" @@ -815,6 +936,13 @@ static int annotate_browser__run(struct annotate_browser *browser, if (annotate_browser__toggle_source(browser)) ui_helpline__puts(help); continue; + case 'S': + if (browser->has_src_code) { + browser->cb.title = title; + annotate_code_browser__run(browser, evsel, delay_secs); + } else + ui_helpline__puts("No source code for the symbol"); + continue; case 'o': annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; annotate_browser__update_addr_width(browser); @@ -1116,6 +1244,26 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.b.entries = ¬es->src->source, browser.b.width += 18; /* Percentage */ + if (symbol__get_source_code(sym, map, evsel) == 0) { + struct source_code *code = notes->src->code; + struct code_line *cl; + + browser.has_src_code = true; + browser.cb.refresh = annotate_code_browser__refresh; + browser.cb.seek = ui_browser__list_head_seek; + browser.cb.write = annotate_code_browser__write; + browser.cb.use_navkeypressed = true; + browser.cb.entries = &code->lines; + + list_for_each_entry(cl, &code->lines, node) { + size_t line_len = strlen(cl->line); + + if (browser.cb.width < line_len) + browser.cb.width = line_len; + browser.cb.nr_entries++; + } + } + if (annotate_browser__opts.hide_src_code) annotate_browser__init_asm_mode(&browser); @@ -1126,6 +1274,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, list_del(&pos->node); disasm_line__free(pos); } + symbol__free_source_code(sym); out_free_offsets: free(browser.offsets); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4108520..667277a 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1419,7 +1419,7 @@ static void code_lines__free(struct list_head *code_lines) } } -static int symbol__free_source_code(struct symbol *sym) +int symbol__free_source_code(struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); struct source_code *code = notes->src->code; @@ -1433,7 +1433,7 @@ static int symbol__free_source_code(struct symbol *sym) return 0; } -static void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl, +void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl, struct annotation *notes, struct perf_evsel *evsel) { int i; @@ -1596,7 +1596,7 @@ static int source_code__collect(struct symbol *sym, struct map *map, return ret; } -static int symbol__get_source_code(struct symbol *sym, struct map *map, +int symbol__get_source_code(struct symbol *sym, struct map *map, struct perf_evsel *evsel) { int start_linenr, end_linenr, ret = -1; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 3513807..fb352cf 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -128,6 +128,9 @@ struct source_line { struct source_line_samples samples[1]; }; +void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl, + struct annotation *notes, struct perf_evsel *evsel); + /** struct annotated_source - symbols with hits have this attached as in sannotation * * @histogram: Array of addr hit histograms per event being monitored @@ -180,6 +183,10 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); int symbol__alloc_hist(struct symbol *sym); void symbol__annotate_zero_histograms(struct symbol *sym); +int symbol__free_source_code(struct symbol *sym); +int symbol__get_source_code(struct symbol *sym, struct map *map, + struct perf_evsel *evsel); + int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize, struct arch **parch); -- 2.7.4