提交 60517d28 编写于 作者: N Namhyung Kim 提交者: Arnaldo Carvalho de Melo

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: NNamhyung Kim <namhyung@kernel.org>
Acked-by: NJiri Olsa <jolsa@kernel.org>
Tested-by: NArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Wang Nan <wangnan0@huawei.com>
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: NArnaldo Carvalho de Melo <acme@redhat.com>
上级 c7c2a5e4
...@@ -997,6 +997,7 @@ void hist_entry__delete(struct hist_entry *he) ...@@ -997,6 +997,7 @@ void hist_entry__delete(struct hist_entry *he)
if (he->srcfile && he->srcfile[0]) if (he->srcfile && he->srcfile[0])
free(he->srcfile); free(he->srcfile);
free_callchain(he->callchain); free_callchain(he->callchain);
free(he->trace_output);
free(he->raw_data); free(he->raw_data);
free(he); free(he);
} }
......
...@@ -1560,6 +1560,62 @@ static int hde_width(struct hpp_dynamic_entry *hde) ...@@ -1560,6 +1560,62 @@ static int hde_width(struct hpp_dynamic_entry *hde)
return hde->hpp.len; 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, static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
struct perf_evsel *evsel __maybe_unused) struct perf_evsel *evsel __maybe_unused)
{ {
...@@ -1594,7 +1650,10 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, ...@@ -1594,7 +1650,10 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
{ {
struct hpp_dynamic_entry *hde; struct hpp_dynamic_entry *hde;
size_t len = fmt->user_len; 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; int ret;
hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 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, ...@@ -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) if (hists_to_evsel(he->hists) != hde->evsel)
return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, "N/A"); return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, "N/A");
trace_seq_init(&seq); field = hde->field;
pevent_print_field(&seq, he->raw_data, hde->field);
ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, seq.buffer); namelen = strlen(field->name);
trace_seq_destroy(&seq); 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; return ret;
} }
...@@ -1638,6 +1730,9 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt, ...@@ -1638,6 +1730,9 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
} else { } else {
offset = field->offset; offset = field->offset;
size = field->size; size = field->size;
update_dynamic_len(hde, a);
update_dynamic_len(hde, b);
} }
return memcmp(a->raw_data + offset, b->raw_data + offset, size); return memcmp(a->raw_data + offset, b->raw_data + offset, size);
......
...@@ -124,6 +124,7 @@ struct hist_entry { ...@@ -124,6 +124,7 @@ struct hist_entry {
struct mem_info *mem_info; struct mem_info *mem_info;
void *raw_data; void *raw_data;
u32 raw_size; u32 raw_size;
void *trace_output;
struct callchain_root callchain[0]; /* must be last member */ struct callchain_root callchain[0]; /* must be last member */
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册