From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756080AbcAIQZA (ORCPT ); Sat, 9 Jan 2016 11:25:00 -0500 Received: from terminus.zytor.com ([198.137.202.10]:41668 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755365AbcAIQY5 (ORCPT ); Sat, 9 Jan 2016 11:24:57 -0500 Date: Sat, 9 Jan 2016 08:24:09 -0800 From: tip-bot for Namhyung Kim Message-ID: Cc: rostedt@goodmis.org, fweisbec@gmail.com, hpa@zytor.com, wangnan0@huawei.com, linux-kernel@vger.kernel.org, acme@redhat.com, andi@firstfloor.org, tglx@linutronix.de, dsahern@gmail.com, peterz@infradead.org, jolsa@kernel.org, namhyung@kernel.org, mingo@kernel.org Reply-To: hpa@zytor.com, rostedt@goodmis.org, fweisbec@gmail.com, wangnan0@huawei.com, acme@redhat.com, linux-kernel@vger.kernel.org, andi@firstfloor.org, tglx@linutronix.de, dsahern@gmail.com, peterz@infradead.org, jolsa@kernel.org, namhyung@kernel.org, mingo@kernel.org In-Reply-To: <1450804030-29193-7-git-send-email-namhyung@kernel.org> References: <1450804030-29193-7-git-send-email-namhyung@kernel.org> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/core] perf tools: Try to show pretty printed output for dynamic sort keys Git-Commit-ID: 60517d28fbd91629686dcf9a39aef4e068a3d5f6 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 60517d28fbd91629686dcf9a39aef4e068a3d5f6 Gitweb: http://git.kernel.org/tip/60517d28fbd91629686dcf9a39aef4e068a3d5f6 Author: Namhyung Kim AuthorDate: Wed, 23 Dec 2015 02:07:03 +0900 Committer: Arnaldo Carvalho de Melo CommitDate: Wed, 6 Jan 2016 20:11:11 -0300 perf tools: Try to show pretty printed output for dynamic sort keys Each tracepoint event has format string for print to improve readability. Try to parse the output and match the field name. If it finds one, use that for the result. If not, fallbacks to the original output. For example, sort on kmem:kmalloc.gfp_flags looks like below: (Note: libtraceevent plugins are not installed on my system. They might affect the output below) Before: # Overhead Command gfp_flags # ........ ....... .......... # 99.89% perf 32848 0.06% sleep 208 0.03% perf 32976 0.01% perf 208 After: # Overhead Command gfp_flags # ........ ....... ................... # 99.89% perf GFP_NOFS|GFP_ZERO 0.06% sleep GFP_KERNEL 0.03% perf GFP_KERNEL|GFP_ZERO 0.01% perf GFP_KERNEL Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Steven Rostedt Cc: Wang Nan Link: http://lkml.kernel.org/r/1450804030-29193-7-git-send-email-namhyung@kernel.org [ Fixed clash with earlier, updated patch in this patchkit ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 1 + tools/perf/util/sort.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++--- tools/perf/util/sort.h | 1 + 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 2dcf38a..fdb97e1 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -997,6 +997,7 @@ void hist_entry__delete(struct hist_entry *he) if (he->srcfile && he->srcfile[0]) free(he->srcfile); free_callchain(he->callchain); + free(he->trace_output); free(he->raw_data); free(he); } diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index cc659ba..22d28c7 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1560,6 +1560,62 @@ static int hde_width(struct hpp_dynamic_entry *hde) return hde->hpp.len; } +static char *get_trace_output(struct hist_entry *he) +{ + struct trace_seq seq; + struct perf_evsel *evsel; + struct pevent_record rec = { + .data = he->raw_data, + .size = he->raw_size, + }; + + evsel = hists_to_evsel(he->hists); + + trace_seq_init(&seq); + pevent_event_info(&seq, evsel->tp_format, &rec); + return seq.buffer; +} + +static void update_dynamic_len(struct hpp_dynamic_entry *hde, + struct hist_entry *he) +{ + char *str, *pos; + struct format_field *field = hde->field; + size_t namelen; + bool last = false; + + /* parse pretty print result and update max length */ + if (!he->trace_output) + he->trace_output = get_trace_output(he); + + namelen = strlen(field->name); + str = he->trace_output; + + while (str) { + pos = strchr(str, ' '); + if (pos == NULL) { + last = true; + pos = str + strlen(str); + } + + if (!strncmp(str, field->name, namelen)) { + size_t len; + + str += namelen + 1; + len = pos - str; + + if (len > hde->dynamic_len) + hde->dynamic_len = len; + break; + } + + if (last) + str = NULL; + else + str = pos + 1; + } +} + static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct perf_evsel *evsel __maybe_unused) { @@ -1594,7 +1650,10 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, { struct hpp_dynamic_entry *hde; size_t len = fmt->user_len; - struct trace_seq seq; + char *str, *pos; + struct format_field *field; + size_t namelen; + bool last = false; int ret; hde = container_of(fmt, struct hpp_dynamic_entry, hpp); @@ -1605,10 +1664,43 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, if (hists_to_evsel(he->hists) != hde->evsel) return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, "N/A"); - trace_seq_init(&seq); - pevent_print_field(&seq, he->raw_data, hde->field); - ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, seq.buffer); - trace_seq_destroy(&seq); + field = hde->field; + + namelen = strlen(field->name); + str = he->trace_output; + + while (str) { + pos = strchr(str, ' '); + if (pos == NULL) { + last = true; + pos = str + strlen(str); + } + + if (!strncmp(str, field->name, namelen)) { + str += namelen + 1; + str = strndup(str, pos - str); + + if (str == NULL) + return scnprintf(hpp->buf, hpp->size, + "%*.*s", len, len, "ERROR"); + break; + } + + if (last) + str = NULL; + else + str = pos + 1; + } + + if (str == NULL) { + struct trace_seq seq; + trace_seq_init(&seq); + pevent_print_field(&seq, he->raw_data, hde->field); + str = seq.buffer; + } + + ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, str); + free(str); return ret; } @@ -1638,6 +1730,9 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt, } else { offset = field->offset; size = field->size; + + update_dynamic_len(hde, a); + update_dynamic_len(hde, b); } return memcmp(a->raw_data + offset, b->raw_data + offset, size); diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 1a00f1e..f6d2a7e 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -124,6 +124,7 @@ struct hist_entry { struct mem_info *mem_info; void *raw_data; u32 raw_size; + void *trace_output; struct callchain_root callchain[0]; /* must be last member */ };