summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/hist.c1
-rw-r--r--tools/perf/util/sort.c105
-rw-r--r--tools/perf/util/sort.h1
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 */
};