[PATCH 6/6] perf tools: Try to show pretty printed output for dynamic sort keys

From: Namhyung Kim
Date: Mon Dec 14 2015 - 10:47:46 EST


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

Cc: Steven Rostedt <rostedt@xxxxxxxxxxx>
Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
---
tools/perf/util/sort.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++--
tools/perf/util/sort.h | 1 +
2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 8e4444514054..57945be4b81c 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1560,6 +1560,47 @@ static int hde_width(struct hpp_dynamic_entry *hde)
return hde->hpp.len;
}

+static void update_dynamic_len(struct hpp_dynamic_entry *hde,
+ struct hist_entry *he)
+{
+ char *str, *pos;
+ struct trace_seq seq;
+ struct format_field *field = hde->field;
+ struct pevent_record rec = {
+ .cpu = he->cpu,
+ .data = he->raw_data,
+ .size = he->raw_size,
+ };
+ size_t namelen;
+
+ if (he->dynlen_updated)
+ return;
+
+ /* parse pretty print result and update max length */
+ trace_seq_init(&seq);
+ pevent_event_info(&seq, field->event, &rec);
+
+ namelen = strlen(field->name);
+ str = strtok_r(seq.buffer, " ", &pos);
+ while (str) {
+ if (!strncmp(str, field->name, namelen)) {
+ size_t len;
+
+ str += namelen + 1;
+ len = strlen(str);
+
+ if (len > hde->dynamic_len)
+ hde->dynamic_len = len;
+ break;
+ }
+
+ str = strtok_r(NULL, " ", &pos);
+ }
+ trace_seq_destroy(&seq);
+
+ he->dynlen_updated = true;
+}
+
static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
struct perf_evsel *evsel __maybe_unused)
{
@@ -1595,6 +1636,14 @@ 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;
+ struct pevent_record rec = {
+ .cpu = he->cpu,
+ .data = he->raw_data,
+ .size = he->raw_size,
+ };
+ size_t namelen;
int ret;

hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
@@ -1605,9 +1654,28 @@ 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");

+ field = hde->field;
trace_seq_init(&seq);
- print_event_field(&seq, he->raw_data, hde->field);
- ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, seq.buffer);
+ pevent_event_info(&seq, field->event, &rec);
+
+ namelen = strlen(field->name);
+ str = strtok_r(seq.buffer, " ", &pos);
+ while (str) {
+ if (!strncmp(str, field->name, namelen)) {
+ str += namelen + 1;
+ break;
+ }
+
+ str = strtok_r(NULL, " ", &pos);
+ }
+
+ if (str == NULL) {
+ trace_seq_reset(&seq);
+ print_event_field(&seq, he->raw_data, hde->field);
+ str = seq.buffer;
+ }
+
+ ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, str);
trace_seq_destroy(&seq);
return ret;
}
@@ -1638,6 +1706,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 dd1c2973a836..aefcc2f8f173 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -97,6 +97,7 @@ struct hist_entry {

/* We are added by hists__add_dummy_entry. */
bool dummy;
+ bool dynlen_updated;

char level;
u8 filtered;
--
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/