From de63403bfd14ae8d613f30c9a0d415581b4cb37e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 26 Jul 2017 14:02:04 +0200 Subject: perf tools: Add perf_evsel__read_size function Currently we use the size of struct perf_counts_values to read the event, which prevents us to put any new member to the struct. Adding perf_evsel__read_size to return size of the buffer needed for event read. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170726120206.9099-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 450b5fadf8cb..4dd0fcc06db9 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1261,15 +1261,42 @@ void perf_counts_values__scale(struct perf_counts_values *count, *pscaled = scaled; } +static int perf_evsel__read_size(struct perf_evsel *evsel) +{ + u64 read_format = evsel->attr.read_format; + int entry = sizeof(u64); /* value */ + int size = 0; + int nr = 1; + + if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + size += sizeof(u64); + + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + size += sizeof(u64); + + if (read_format & PERF_FORMAT_ID) + entry += sizeof(u64); + + if (read_format & PERF_FORMAT_GROUP) { + nr = evsel->nr_members; + size += sizeof(u64); + } + + size += entry * nr; + return size; +} + int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count) { + size_t size = perf_evsel__read_size(evsel); + memset(count, 0, sizeof(*count)); if (FD(evsel, cpu, thread) < 0) return -EINVAL; - if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0) + if (readn(FD(evsel, cpu, thread), count->values, size) <= 0) return -errno; return 0; -- cgit v1.2.3-55-g7522 From f7794d525447f1e4e4b2228dd29dba084005e6bf Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 26 Jul 2017 14:02:05 +0200 Subject: perf evsel: Add read_counter() Add perf_evsel__read_counter() to read single or group counter. After calling this function the counter's evsel::counts struct is filled with values for the counter and member of its group if there are any. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170726120206.9099-3-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 2 + tools/perf/util/stat.c | 4 ++ tools/perf/util/stat.h | 5 ++- 4 files changed, 109 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 4dd0fcc06db9..89aecf3a35c7 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1302,6 +1302,106 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, return 0; } +static int +perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread) +{ + struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread); + + return perf_evsel__read(evsel, cpu, thread, count); +} + +static void +perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread, + u64 val, u64 ena, u64 run) +{ + struct perf_counts_values *count; + + count = perf_counts(counter->counts, cpu, thread); + + count->val = val; + count->ena = ena; + count->run = run; +} + +static int +perf_evsel__process_group_data(struct perf_evsel *leader, + int cpu, int thread, u64 *data) +{ + u64 read_format = leader->attr.read_format; + struct sample_read_value *v; + u64 nr, ena = 0, run = 0, i; + + nr = *data++; + + if (nr != (u64) leader->nr_members) + return -EINVAL; + + if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + ena = *data++; + + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + run = *data++; + + v = (struct sample_read_value *) data; + + perf_evsel__set_count(leader, cpu, thread, + v[0].value, ena, run); + + for (i = 1; i < nr; i++) { + struct perf_evsel *counter; + + counter = perf_evlist__id2evsel(leader->evlist, v[i].id); + if (!counter) + return -EINVAL; + + perf_evsel__set_count(counter, cpu, thread, + v[i].value, ena, run); + } + + return 0; +} + +static int +perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread) +{ + struct perf_stat_evsel *ps = leader->priv; + u64 read_format = leader->attr.read_format; + int size = perf_evsel__read_size(leader); + u64 *data = ps->group_data; + + if (!(read_format & PERF_FORMAT_ID)) + return -EINVAL; + + if (!perf_evsel__is_group_leader(leader)) + return -EINVAL; + + if (!data) { + data = zalloc(size); + if (!data) + return -ENOMEM; + + ps->group_data = data; + } + + if (FD(leader, cpu, thread) < 0) + return -EINVAL; + + if (readn(FD(leader, cpu, thread), data, size) <= 0) + return -errno; + + return perf_evsel__process_group_data(leader, cpu, thread, data); +} + +int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread) +{ + u64 read_format = evsel->attr.read_format; + + if (read_format & PERF_FORMAT_GROUP) + return perf_evsel__read_group(evsel, cpu, thread); + else + return perf_evsel__read_one(evsel, cpu, thread); +} + int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, int cpu, int thread, bool scale) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index fb40ca3c6519..de03c18daaf0 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -299,6 +299,8 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count); +int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread); + int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, int cpu, int thread, bool scale); diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 53b9a994a3dc..35e9848734d6 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -128,6 +128,10 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) { + struct perf_stat_evsel *ps = evsel->priv; + + if (ps) + free(ps->group_data); zfree(&evsel->priv); } diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 7522bf10b03e..eacaf958e19d 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -28,8 +28,9 @@ enum perf_stat_evsel_id { }; struct perf_stat_evsel { - struct stats res_stats[3]; - enum perf_stat_evsel_id id; + struct stats res_stats[3]; + enum perf_stat_evsel_id id; + u64 *group_data; }; enum aggr_mode { -- cgit v1.2.3-55-g7522 From 82bf311e15d22e2fa45423b1fb4a21cf925381fe Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 26 Jul 2017 14:02:06 +0200 Subject: perf stat: Use group read for event groups Make perf stat use group read if there are groups defined. The group read will get the values for all member of groups within a single syscall instead of calling read syscall for every event. We can see considerable less amount of kernel cycles spent on single group read, than reading each event separately, like for following perf stat command: # perf stat -e {cycles,instructions} -I 10 -a sleep 1 Monitored with "perf stat -r 5 -e '{cycles:u,cycles:k}'" Before: 24,325,676 cycles:u 297,040,775 cycles:k 1.038554134 seconds time elapsed After: 25,034,418 cycles:u 158,256,395 cycles:k 1.036864497 seconds time elapsed The perf_evsel__open fallback changes contributed by Andi Kleen. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170726120206.9099-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 30 +++++++++++++++++++++++++++--- tools/perf/util/counts.h | 1 + tools/perf/util/evsel.c | 10 ++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 48ac53b199fc..866da7aa54bf 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -213,10 +213,20 @@ static void perf_stat__reset_stats(void) static int create_perf_stat_counter(struct perf_evsel *evsel) { struct perf_event_attr *attr = &evsel->attr; + struct perf_evsel *leader = evsel->leader; - if (stat_config.scale) + if (stat_config.scale) { attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; + } + + /* + * The event is part of non trivial group, let's enable + * the group read (for leader) and ID retrieval for all + * members. + */ + if (leader->nr_members > 1) + attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP; attr->inherit = !no_inherit; @@ -333,13 +343,21 @@ static int read_counter(struct perf_evsel *counter) struct perf_counts_values *count; count = perf_counts(counter->counts, cpu, thread); - if (perf_evsel__read(counter, cpu, thread, count)) { + + /* + * The leader's group read loads data into its group members + * (via perf_evsel__read_counter) and sets threir count->loaded. + */ + if (!count->loaded && + perf_evsel__read_counter(counter, cpu, thread)) { counter->counts->scaled = -1; perf_counts(counter->counts, cpu, thread)->ena = 0; perf_counts(counter->counts, cpu, thread)->run = 0; return -1; } + count->loaded = false; + if (STAT_RECORD) { if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { pr_err("failed to write stat event\n"); @@ -559,6 +577,11 @@ static int store_counter_ids(struct perf_evsel *counter) return __store_counter_ids(counter, cpus, threads); } +static bool perf_evsel__should_store_id(struct perf_evsel *counter) +{ + return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; +} + static int __run_perf_stat(int argc, const char **argv) { int interval = stat_config.interval; @@ -631,7 +654,8 @@ try_again: if (l > unit_width) unit_width = l; - if (STAT_RECORD && store_counter_ids(counter)) + if (perf_evsel__should_store_id(counter) && + store_counter_ids(counter)) return -1; } diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h index 34d8baaf558a..cb45a6aecf9d 100644 --- a/tools/perf/util/counts.h +++ b/tools/perf/util/counts.h @@ -12,6 +12,7 @@ struct perf_counts_values { }; u64 values[3]; }; + bool loaded; }; struct perf_counts { diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 89aecf3a35c7..3735c9e0080d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -49,6 +49,7 @@ static struct { bool clockid_wrong; bool lbr_flags; bool write_backward; + bool group_read; } perf_missing_features; static clockid_t clockid; @@ -1321,6 +1322,7 @@ perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread, count->val = val; count->ena = ena; count->run = run; + count->loaded = true; } static int @@ -1677,6 +1679,8 @@ fallback_missing_features: if (perf_missing_features.lbr_flags) evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | PERF_SAMPLE_BRANCH_NO_CYCLES); + if (perf_missing_features.group_read && evsel->attr.inherit) + evsel->attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID); retry_sample_id: if (perf_missing_features.sample_id_all) evsel->attr.sample_id_all = 0; @@ -1832,6 +1836,12 @@ try_fallback: perf_missing_features.lbr_flags = true; pr_debug2("switching off branch sample type no (cycles/flags)\n"); goto fallback_missing_features; + } else if (!perf_missing_features.group_read && + evsel->attr.inherit && + (evsel->attr.read_format & PERF_FORMAT_GROUP)) { + perf_missing_features.group_read = true; + pr_debug2("switching off group read\n"); + goto fallback_missing_features; } out_close: do { -- cgit v1.2.3-55-g7522 From c6c13be76c1fc8a3169dbd29cd1d42af1d64773f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jul 2017 16:52:25 -0300 Subject: perf annotate: Do not overwrite perf_sample->weight When we parse an event we may get a value from the kernel in response to PERF_SAMPLE_WEIGHT being set in perf_event_attr->sample_type, and if it is not set, then perf_sample->weight will be set to zero, which should be ok according to a discussion with Andi Kleen [1]: 1: https://lkml.kernel.org/r/20170724174637.GS3044@two.firstfloor.org Acked-by: Andi Kleen Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Taeung Song Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-8ev8ufk3lzmvgz37yg9nv3qz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6db782dfce96..658c920d74b9 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -177,8 +177,6 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, */ process_branch_stack(sample->branch_stack, al, sample); - sample->weight = 1; - he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); if (he == NULL) return -ENOMEM; -- cgit v1.2.3-55-g7522 From 64831a21db13495008665b33878e31b48c1e3dc7 Mon Sep 17 00:00:00 2001 From: David Carrillo-Cisneros Date: Thu, 20 Jul 2017 22:11:57 -0700 Subject: perf sort: Use default sort if evlist is empty Fixes bug noted by Jiri in https://lkml.org/lkml/2017/6/13/755 and caused by commit d49dadea7862 ("perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events") not taking into account that evlist is empty in pipe-mode. Before this commit, pipe mode will only show bogus "100.00% N/A" instead of correct output as follows: $ perf record -o - sleep 1 | perf report -i - # To display the perf.data header info, please use --header/--header-only options. # [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.000 MB - ] # # Total Lost Samples: 0 # # Samples: 8 of event 'cycles:ppH' # Event count (approx.): 145658 # # Overhead Trace output # ........ ............ # 100.00% N/A Correct output, after patch: $ perf record -o - sleep 1 | perf report -i - # To display the perf.data header info, please use --header/--header-only options. # [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.000 MB - ] # # Total Lost Samples: 0 # # Samples: 8 of event 'cycles:ppH' # Event count (approx.): 191331 # # Overhead Command Shared Object Symbol # ........ ....... ................. ................................. # 81.63% sleep libc-2.19.so [.] _exit 13.58% sleep ld-2.19.so [.] do_lookup_x 2.34% sleep [kernel.kallsyms] [k] context_switch 2.34% sleep libc-2.19.so [.] __GI___libc_nanosleep 0.11% perf [kernel.kallsyms] [k] __intel_pmu_enable_a Reported-by: Jiri Olsa Report-Link: https://lkml.kernel.org/r/20170613185422.GA6092@krava Signed-off-by: David Carrillo-Cisneros Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Namhyung Kim Cc: Paul Turner Cc: Simon Que Cc: Stephane Eranian Cc: Wang Nan Fixes: d49dadea7862 ("perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events") Link: https://lkml.kernel.org/r/20170721051157.47331-1-davidcc@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.h | 5 +++++ tools/perf/util/sort.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 0843746bc389..bf2c4936e35f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -265,6 +265,11 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist); void perf_evlist__splice_list_tail(struct perf_evlist *evlist, struct list_head *list); +static inline bool perf_evlist__empty(struct perf_evlist *evlist) +{ + return list_empty(&evlist->entries); +} + static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) { return list_entry(evlist->entries.next, struct perf_evsel, node); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b327c955a4f..12359bd986db 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2563,7 +2563,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist) BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); - if (evlist == NULL) + if (evlist == NULL || perf_evlist__empty(evlist)) goto out_no_evlist; evlist__for_each_entry(evlist, evsel) { -- cgit v1.2.3-55-g7522 From ce9ee4a2de20062a97ad50ecc11ebda7e7618fd1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jul 2017 17:16:46 -0300 Subject: perf annotate stdio: Set enough columns for --show-total-period Now that we set the first column header according to wether --show-total-period is being used, we need to size it accordingly. Based-on-a-patch-by: Taeung Song Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Link: http://lkml.kernel.org/n/tip-pu504ffnit4m334k09hxcbs3@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index c2b4b00166ed..5125c2bbacaa 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1142,7 +1142,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st color = get_percent_color(percent); if (symbol_conf.show_total_period) - color_fprintf(stdout, color, " %7" PRIu64, + color_fprintf(stdout, color, " %11" PRIu64, sample.period); else color_fprintf(stdout, color, " %7.2f", percent); @@ -1165,7 +1165,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st } else if (max_lines && printed >= max_lines) return 1; else { - int width = 8; + int width = symbol_conf.show_total_period ? 12 : 8; if (queue) return -1; @@ -1806,7 +1806,7 @@ 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 width = symbol_conf.show_total_period ? 12 : 8; int graph_dotted_len; filename = strdup(dso->long_name); -- cgit v1.2.3-55-g7522 From 48cc33085253d607706e68a67ac98fe2a6abdd3d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 28 Jul 2017 12:49:02 -0300 Subject: perf annotate: Fix storing per line sym_hist_entry The existing loop incremented the offset while using it as the array index, when we went to an array of sym_hist_entry instances, we should've moved the increment to outside of the array element reference, oops, fix it. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Taeung Song Cc: Wang Nan Fixes: 461c17f00f40 ("perf annotate: Store the sample period in each histogram bucket") Link: http://lkml.kernel.org/n/tip-s3dm6uyrazlpag3f0psfia07@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 5125c2bbacaa..2dab0e5a7f2f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -963,8 +963,9 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, u64 period = 0; while (offset < end) { - hits += h->addr[offset++].nr_samples; - period += h->addr[offset++].period; + hits += h->addr[offset].nr_samples; + period += h->addr[offset].period; + ++offset; } if (h->nr_samples) { -- cgit v1.2.3-55-g7522 From bb79a232b0881ce47f921a53f40612a9f9996482 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 27 Jul 2017 11:24:59 -0300 Subject: perf annotate TUI: Use sym_hist_entry in disasm_line_samples Just paving the way to fix --show-total-period in the TUI, i.e. now we save in struct disasm_line_samples not just the number of samples, but also the total period. Based-on-a-patch-by: Taeung Song Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Link: http://lkml.kernel.org/n/tip-1sup5hkwrxocjvrmrmhs732o@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index dbe4e630b90f..680fff70f7a0 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -17,8 +17,8 @@ #include struct disasm_line_samples { - double percent; - u64 nr; + double percent; + struct sym_hist_entry he; }; #define IPC_WIDTH 6 @@ -152,7 +152,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int current_entry); if (annotate_browser__opts.show_total_period) { ui_browser__printf(browser, "%6" PRIu64 " ", - bdl->samples[i].nr); + bdl->samples[i].he.nr_samples); } else { ui_browser__printf(browser, "%6.2f ", bdl->samples[i].percent); @@ -457,7 +457,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, pos->offset, next ? next->offset : len, &path, &sample); - bpos->samples[i].nr = sample.nr_samples; + bpos->samples[i].he = sample; if (max_percent < bpos->samples[i].percent) max_percent = bpos->samples[i].percent; -- cgit v1.2.3-55-g7522 From 29dc267f270a4ad5ae1341e7fdc8539ac7dc907a Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 27 Jul 2017 11:33:20 -0300 Subject: perf annotate TUI: Fix --show-total-period We were showing the number of samples, not the total period, fix it. Reported-by: Namhyung Kim Signed-off-by: Taeung Song Tested-by: Arnaldo Carvalho de Melo Cc: Martin Liška Cc: Milian Wolff Cc: Jiri Olsa Fixes: 0c4a5bcea460 ("perf annotate: Display total number of samples with --show-total-period") Link: http://lkml.kernel.org/r/1500500223-16753-1-git-send-email-treeze.taeung@gmail.com [ extracted from a larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 680fff70f7a0..c382b1d8af42 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -152,7 +152,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int current_entry); if (annotate_browser__opts.show_total_period) { ui_browser__printf(browser, "%6" PRIu64 " ", - bdl->samples[i].he.nr_samples); + bdl->samples[i].he.period); } else { ui_browser__printf(browser, "%6.2f ", bdl->samples[i].percent); -- cgit v1.2.3-55-g7522 From bc1e5d60cebb711ca3783a87a969d18db376d357 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 27 Jul 2017 12:05:58 -0300 Subject: perf annotate TUI: Clarify calculation of column header widths In commit f8f4aaead579 ("perf annotate: Finally display IPC and cycle accounting") the 'pcnt_width' variable was abused in a few places to also include the optional width of the "IPC" and "cycles" columns, while in other places we stopped using 'pcnt_width' and instead its previous equation... Now that we need to tap into annotate_browser__pcnt_width() to consider if --show-total-period is being used and instead of that hardcoded 7 (strlen("Percent")) we need to use it or strlen("Event count") we need this properly clarified to avoid having to touch all the (7 * nr_events) places. Clarify this by introducing a separate annotate_browser__cycles_width() to leave the pcnt_width calculate just what its name implies. Cc: Taeung Song Cc: Milian Wolff Cc: Namhyung Kim Cc: Jiri Olsa Cc: Andi Kleen Link: http://lkml.kernel.org/n/tip-szgb07t4k5wtvks8nzwkg710@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index c382b1d8af42..0f4bcc0d140c 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -110,11 +110,12 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *br static int annotate_browser__pcnt_width(struct annotate_browser *ab) { - int w = 7 * ab->nr_events; + return 7 * ab->nr_events; +} - if (ab->have_cycles) - w += IPC_WIDTH + CYCLES_WIDTH; - return w; +static int annotate_browser__cycles_width(struct annotate_browser *ab) +{ + return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0; } static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) @@ -127,7 +128,8 @@ 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 = annotate_browser__pcnt_width(ab); + int i, pcnt_width = annotate_browser__pcnt_width(ab), + cycles_width = annotate_browser__cycles_width(ab); double percent_max = 0.0; char bf[256]; bool show_title = false; @@ -162,7 +164,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ui_browser__set_percent_color(browser, 0, current_entry); if (!show_title) - ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); + ui_browser__write_nstring(browser, " ", pcnt_width); else ui_browser__printf(browser, "%*s", 7, "Percent"); } @@ -190,7 +192,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int width += 1; if (!*dl->line) - ui_browser__write_nstring(browser, " ", width - pcnt_width); + ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width); else if (dl->offset == -1) { if (dl->line_nr && annotate_browser__opts.show_linenr) printed = scnprintf(bf, sizeof(bf), "%-*d ", @@ -199,7 +201,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int printed = scnprintf(bf, sizeof(bf), "%*s ", ab->addr_width, " "); ui_browser__write_nstring(browser, bf, printed); - ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1); + ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width - cycles_width + 1); } else { u64 addr = dl->offset; int color = -1; @@ -256,7 +258,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); - ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed); + ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); } if (current_entry) -- cgit v1.2.3-55-g7522 From f67d395c6e3895c3c8c67c8f7523f6a94d61a82d Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Fri, 28 Jul 2017 12:04:32 -0300 Subject: perf annotate TUI: Fix column header when toggling period/percent We have the 't' hotkey to toggle showing either the total period or the percentage of samples for a given line, but we forgot to toggle as well the column header, always showing "Percent", even when showing the period, fix it. Signed-off-by: Taeung Song Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/r/1501172169-6761-1-git-send-email-treeze.taeung@gmail.com [ Extracted from a larger patch, s/Event count/Period/g ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 0f4bcc0d140c..46f297a4e94b 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -166,7 +166,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int if (!show_title) ui_browser__write_nstring(browser, " ", pcnt_width); else - ui_browser__printf(browser, "%*s", 7, "Percent"); + ui_browser__printf(browser, "%*s", 7, annotate_browser__opts.show_total_period ? "Period" : "Percent"); } if (ab->have_cycles) { if (dl->ipc) -- cgit v1.2.3-55-g7522 From 3861c4a49bea432c57d6e7cbd89c8b71ed4445b7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 28 Jul 2017 13:19:32 -0300 Subject: perf annotate TUI: Set appropriate column width for period/percent Either when we start 'perf annotate' or 'perf report' with --show-total-period or when we, in the annotate browser, press 't' to toggle period/percent for the first column, we need to adjust the width for the 'period' case. Based-on-a-patch-by: Taeung Song Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-n2np5qcs20u6qjdr9orygne6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 46f297a4e94b..80f38dab9c3a 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -110,7 +110,7 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *br static int annotate_browser__pcnt_width(struct annotate_browser *ab) { - return 7 * ab->nr_events; + return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events; } static int annotate_browser__cycles_width(struct annotate_browser *ab) @@ -153,7 +153,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int bdl->samples[i].percent, current_entry); if (annotate_browser__opts.show_total_period) { - ui_browser__printf(browser, "%6" PRIu64 " ", + ui_browser__printf(browser, "%11" PRIu64 " ", bdl->samples[i].he.period); } else { ui_browser__printf(browser, "%6.2f ", @@ -165,8 +165,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int if (!show_title) ui_browser__write_nstring(browser, " ", pcnt_width); - else - ui_browser__printf(browser, "%*s", 7, annotate_browser__opts.show_total_period ? "Period" : "Percent"); + else { + ui_browser__printf(browser, "%*s", pcnt_width, + annotate_browser__opts.show_total_period ? "Period" : "Percent"); + } } if (ab->have_cycles) { if (dl->ipc) -- cgit v1.2.3-55-g7522 From a3073c8e590d7baa5a6cb01438cb945c92bfcd91 Mon Sep 17 00:00:00 2001 From: Geneviève Bastien Date: Thu, 27 Jul 2017 14:12:03 -0400 Subject: perf data: Add callchain to CTF conversion The field perf_callchain, if available, is added to the sampling events during the CTF conversion. It is an array of u64 values. The perf_callchain_size field contains the size of the array. It will allow the analysis of sampling data in trace visualization tools like Trace Compass. Possible analyses with those data: dynamic flamegraphs, correlation with other tracing data like a userspace trace. Here follows a babeltrace CTF output of a trace with callchain: $ babeltrace ./myctftrace [17:38:45.672760285] (+?.?????????) cycles:ppp: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF81063EE4, perf_tid = 25841, perf_pid = 25774, perf_period = 1, perf_callchain_size = 7, perf_callchain = [ [0] = 0xFFFFFFFFFFFFFF80, [1] = 0xFFFFFFFF81063EE4, [2] = 0xFFFFFFFF8100C770, [3] = 0xFFFFFFFF81006EC6, [4] = 0xFFFFFFFF8118245E, [5] = 0xFFFFFFFF810A9224, [6] = 0xFFFFFFFF8164A4C6 ] } [17:38:45.672777672] (+0.000017387) cycles:ppp: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF81063EE4, perf_tid = 25841, perf_pid = 25774, perf_period = 1, perf_callchain_size = 8, perf_callchain = [ [0] = 0xFFFFFFFFFFFFFF80, [1] = 0xFFFFFFFF81063EE4, [2] = 0xFFFFFFFF8100C770, [3] = 0xFFFFFFFF81006EC6, [4] = 0xFFFFFFFF8118245E, [5] = 0xFFFFFFFF810A9224, [6] = 0xFFFFFFFF8164A4C6, [7] = 0xFFFFFFFF8164ABAD ] } [17:38:45.672786700] (+0.000009028) cycles:ppp: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF81063EE4, perf_tid = 25841, perf_pid = 25774, perf_period = 70, perf_callchain_size = 3, perf_callchain = [ [0] = 0xFFFFFFFFFFFFFF80, [1] = 0xFFFFFFFF81063EE4, [2] = 0xFFFFFFFF8100C770 ] } Signed-off-by: Geneviève Bastien Acked-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Francis Deslauriers Cc: Julien Desfossez Cc: Mathieu Desnoyers Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170727181205.24843-1-gbastien@versatic.net [ Removed PERF_SAMPLE_CALLCHAIN from the TODO list, jolsa ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data-convert-bt.c | 92 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 3149b70799fd..eeb2590a3ddf 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -506,6 +506,81 @@ put_len_type: return ret; } +static int +add_callchain_output_values(struct bt_ctf_event_class *event_class, + struct bt_ctf_event *event, + struct ip_callchain *callchain) +{ + struct bt_ctf_field_type *len_type, *seq_type; + struct bt_ctf_field *len_field, *seq_field; + unsigned int nr_elements = callchain->nr; + unsigned int i; + int ret; + + len_type = bt_ctf_event_class_get_field_by_name( + event_class, "perf_callchain_size"); + len_field = bt_ctf_field_create(len_type); + if (!len_field) { + pr_err("failed to create 'perf_callchain_size' for callchain output event\n"); + ret = -1; + goto put_len_type; + } + + ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements); + if (ret) { + pr_err("failed to set field value for perf_callchain_size\n"); + goto put_len_field; + } + ret = bt_ctf_event_set_payload(event, "perf_callchain_size", len_field); + if (ret) { + pr_err("failed to set payload to perf_callchain_size\n"); + goto put_len_field; + } + + seq_type = bt_ctf_event_class_get_field_by_name( + event_class, "perf_callchain"); + seq_field = bt_ctf_field_create(seq_type); + if (!seq_field) { + pr_err("failed to create 'perf_callchain' for callchain output event\n"); + ret = -1; + goto put_seq_type; + } + + ret = bt_ctf_field_sequence_set_length(seq_field, len_field); + if (ret) { + pr_err("failed to set length of 'perf_callchain'\n"); + goto put_seq_field; + } + + for (i = 0; i < nr_elements; i++) { + struct bt_ctf_field *elem_field = + bt_ctf_field_sequence_get_field(seq_field, i); + + ret = bt_ctf_field_unsigned_integer_set_value(elem_field, + ((u64 *)(callchain->ips))[i]); + + bt_ctf_field_put(elem_field); + if (ret) { + pr_err("failed to set callchain[%d]\n", i); + goto put_seq_field; + } + } + + ret = bt_ctf_event_set_payload(event, "perf_callchain", seq_field); + if (ret) + pr_err("failed to set payload for raw_data\n"); + +put_seq_field: + bt_ctf_field_put(seq_field); +put_seq_type: + bt_ctf_field_type_put(seq_type); +put_len_field: + bt_ctf_field_put(len_field); +put_len_type: + bt_ctf_field_type_put(len_type); + return ret; +} + static int add_generic_values(struct ctf_writer *cw, struct bt_ctf_event *event, struct perf_evsel *evsel, @@ -519,7 +594,6 @@ static int add_generic_values(struct ctf_writer *cw, * PERF_SAMPLE_TIME - not needed as we have it in * ctf event header * PERF_SAMPLE_READ - TODO - * PERF_SAMPLE_CALLCHAIN - TODO * PERF_SAMPLE_RAW - tracepoint fields are handled separately * PERF_SAMPLE_BRANCH_STACK - TODO * PERF_SAMPLE_REGS_USER - TODO @@ -720,6 +794,7 @@ static int process_sample_event(struct perf_tool *tool, struct bt_ctf_event_class *event_class; struct bt_ctf_event *event; int ret; + unsigned long type = evsel->attr.sample_type; if (WARN_ONCE(!priv, "Failed to setup all events.\n")) return 0; @@ -751,6 +826,13 @@ static int process_sample_event(struct perf_tool *tool, return -1; } + if (type & PERF_SAMPLE_CALLCHAIN) { + ret = add_callchain_output_values(event_class, + event, sample->callchain); + if (ret) + return -1; + } + if (perf_evsel__is_bpf_output(evsel)) { ret = add_bpf_output_values(event_class, event, sample); if (ret) @@ -1043,6 +1125,14 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, if (type & PERF_SAMPLE_TRANSACTION) ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); + if (type & PERF_SAMPLE_CALLCHAIN) { + ADD_FIELD(event_class, cw->data.u32, "perf_callchain_size"); + ADD_FIELD(event_class, + bt_ctf_field_type_sequence_create( + cw->data.u64_hex, "perf_callchain_size"), + "perf_callchain"); + } + #undef ADD_FIELD return 0; } -- cgit v1.2.3-55-g7522 From f9f6f2a90343c5be3294d1336da055a99c28897d Mon Sep 17 00:00:00 2001 From: Geneviève Bastien Date: Thu, 27 Jul 2017 14:12:04 -0400 Subject: perf data: Add mmap[2] events to CTF conversion This adds the mmap and mmap2 events to the CTF trace obtained from perf data. These events will allow CTF trace visualization tools like Trace Compass to automatically resolve the symbols of the callchain to the corresponding function or origin library. To include those events, one needs to convert with the --all option. Here follows an output of babeltrace: $ sudo perf data convert --all --to-ctf myctftrace $ babeltrace ./myctftrace [19:00:00.000000000] (+0.000000000) perf_mmap2: { cpu_id = 0 }, { pid = 638, tid = 638, start = 0x7F54AE39E000, filename = "/usr/lib/ld-2.25.so" } [19:00:00.000000000] (+0.000000000) perf_mmap2: { cpu_id = 0 }, { pid = 638, tid = 638, start = 0x7F54AE565000, filename = "/usr/lib/libudev.so.1.6.6" } [19:00:00.000000000] (+0.000000000) perf_mmap2: { cpu_id = 0 }, { pid = 638, tid = 638, start = 0x7FFC093EA000, filename = "[vdso]" } Signed-off-by: Geneviève Bastien Acked-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Francis Deslauriers Cc: Julien Desfossez Cc: Mathieu Desnoyers Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170727181205.24843-2-gbastien@versatic.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data-convert-bt.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index eeb2590a3ddf..2346cecb8ea2 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -76,6 +76,8 @@ struct ctf_writer { struct bt_ctf_event_class *comm_class; struct bt_ctf_event_class *exit_class; struct bt_ctf_event_class *fork_class; + struct bt_ctf_event_class *mmap_class; + struct bt_ctf_event_class *mmap2_class; }; struct convert { @@ -915,6 +917,18 @@ __FUNC_PROCESS_NON_SAMPLE(exit, __NON_SAMPLE_SET_FIELD(fork, u32, ptid); __NON_SAMPLE_SET_FIELD(fork, u64, time); ) +__FUNC_PROCESS_NON_SAMPLE(mmap, + __NON_SAMPLE_SET_FIELD(mmap, u32, pid); + __NON_SAMPLE_SET_FIELD(mmap, u32, tid); + __NON_SAMPLE_SET_FIELD(mmap, u64_hex, start); + __NON_SAMPLE_SET_FIELD(mmap, string, filename); +) +__FUNC_PROCESS_NON_SAMPLE(mmap2, + __NON_SAMPLE_SET_FIELD(mmap2, u32, pid); + __NON_SAMPLE_SET_FIELD(mmap2, u32, tid); + __NON_SAMPLE_SET_FIELD(mmap2, u64_hex, start); + __NON_SAMPLE_SET_FIELD(mmap2, string, filename); +) #undef __NON_SAMPLE_SET_FIELD #undef __FUNC_PROCESS_NON_SAMPLE @@ -1254,6 +1268,19 @@ __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit, __NON_SAMPLE_ADD_FIELD(u64, time); ) +__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap, + __NON_SAMPLE_ADD_FIELD(u32, pid); + __NON_SAMPLE_ADD_FIELD(u32, tid); + __NON_SAMPLE_ADD_FIELD(u64_hex, start); + __NON_SAMPLE_ADD_FIELD(string, filename); +) + +__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap2, + __NON_SAMPLE_ADD_FIELD(u32, pid); + __NON_SAMPLE_ADD_FIELD(u32, tid); + __NON_SAMPLE_ADD_FIELD(u64_hex, start); + __NON_SAMPLE_ADD_FIELD(string, filename); +) #undef __NON_SAMPLE_ADD_FIELD #undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS @@ -1269,6 +1296,12 @@ static int setup_non_sample_events(struct ctf_writer *cw, if (ret) return ret; ret = add_fork_event(cw); + if (ret) + return ret; + ret = add_mmap_event(cw); + if (ret) + return ret; + ret = add_mmap2_event(cw); if (ret) return ret; return 0; @@ -1572,6 +1605,8 @@ int bt_convert__perf2ctf(const char *input, const char *path, c.tool.comm = process_comm_event; c.tool.exit = process_exit_event; c.tool.fork = process_fork_event; + c.tool.mmap = process_mmap_event; + c.tool.mmap2 = process_mmap2_event; } err = perf_config(convert__config, &c); -- cgit v1.2.3-55-g7522 From 6b7007af728df7258bb60ed73099be3b59b3030e Mon Sep 17 00:00:00 2001 From: Geneviève Bastien Date: Thu, 27 Jul 2017 14:12:05 -0400 Subject: perf data: Add doc when no conversion support compiled This adds documentation on the environment variables needed to the message telling that no conversion support is compiled in. Committer testing: $ make -C tools/perf install $ perf data convert --all --to-ctf myctftrace No conversion support compiled in. perf should be compiled with environment variables LIBBABELTRACE=1 and LIBBABELTRACE_DIR=/path/to/libbabeltrace/ $ Signed-off-by: Geneviève Bastien Acked-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Francis Deslauriers Cc: Julien Desfossez Cc: Mathieu Desnoyers Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170727181205.24843-3-gbastien@versatic.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c index 0adb5f82335a..46cd8490baf4 100644 --- a/tools/perf/builtin-data.c +++ b/tools/perf/builtin-data.c @@ -69,7 +69,7 @@ static int cmd_data_convert(int argc, const char **argv) }; #ifndef HAVE_LIBBABELTRACE_SUPPORT - pr_err("No conversion support compiled in.\n"); + pr_err("No conversion support compiled in. perf should be compiled with environment variables LIBBABELTRACE=1 and LIBBABELTRACE_DIR=/path/to/libbabeltrace/\n"); return -1; #endif -- cgit v1.2.3-55-g7522