Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1291295 > unrolled thread
| Started by | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| First post | 2015-12-14 16:50 +0100 |
| Last post | 2015-12-15 02:50 +0100 |
| Articles | 8 — 3 participants |
Back to article view | Back to linux.kernel
[RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) Namhyung Kim <namhyung@kernel.org> - 2015-12-14 16:50 +0100
[PATCH 1/6] perf hist: Pass struct sample to __hists__add_entry() Namhyung Kim <namhyung@kernel.org> - 2015-12-14 16:50 +0100
[PATCH 3/6] tools lib traceevent: Factor out and export print_event_field() Namhyung Kim <namhyung@kernel.org> - 2015-12-14 16:50 +0100
[PATCH 4/6] perf tools: Pass evlist to setup_sorting() Namhyung Kim <namhyung@kernel.org> - 2015-12-14 16:50 +0100
[PATCH 2/6] perf hist: Save raw_data/size for tracepoint events Namhyung Kim <namhyung@kernel.org> - 2015-12-14 16:50 +0100
Re: [RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-14 18:50 +0100
Re: [RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) David Ahern <dsahern@gmail.com> - 2015-12-14 23:40 +0100
Re: [RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) Namhyung Kim <namhyung@kernel.org> - 2015-12-15 02:50 +0100
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-12-14 16:50 +0100 |
| Subject | [RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) |
| Message-ID | <qFDxU-83l-1@gated-at.bofh.it> |
Hello,
This is an attempt to improve perf to deal with tracepoint events
better. The perf tools can handle tracepoint events but perf report
on them is less useful since they're always sampled in a fixed
location and not provide event specific info. We can use perf script
but I always wishes there's more convenient way to see the result.
I suggest dynamic sort keys created for each event.field on demand.
Consider following example:
# Overhead Command Shared Object Symbol
# ........ ............... ................ ..............
#
47.22% swapper [kernel.vmlinux] [k] __schedule
21.67% transmission-gt [kernel.vmlinux] [k] __schedule
8.23% netctl-auto [kernel.vmlinux] [k] __schedule
5.53% kworker/0:1H [kernel.vmlinux] [k] __schedule
1.98% Xephyr [kernel.vmlinux] [k] __schedule
1.33% irq/33-iwlwifi [kernel.vmlinux] [k] __schedule
1.17% wpa_cli [kernel.vmlinux] [k] __schedule
1.13% rcu_preempt [kernel.vmlinux] [k] __schedule
0.85% ksoftirqd/0 [kernel.vmlinux] [k] __schedule
0.77% Timer [kernel.vmlinux] [k] __schedule
...
Currently perf report only shows this but important info is on the
event fields, that is:
# sudo cat /sys/kernel/debug/tracing/events/sched/sched_switch/format
name: sched_switch
ID: 268
format:
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:char prev_comm[16]; offset:8; size:16; signed:1;
field:pid_t prev_pid; offset:24; size:4; signed:1;
field:int prev_prio; offset:28; size:4; signed:1;
field:long prev_state; offset:32; size:8; signed:1;
field:char next_comm[16]; offset:40; size:16; signed:1;
field:pid_t next_pid; offset:56; size:4; signed:1;
field:int next_prio; offset:60; size:4; signed:1;
print fmt: "prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s%s ==>
next_comm=%s next_pid=%d next_prio=%d",
REC->prev_comm, REC->prev_pid, REC->prev_prio,
REC->prev_state & (2048-1) ? __print_flags(REC->prev_state & (2048-1),
"|", { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" }, { 16, "Z" }, { 32, "X" },
{ 64, "x" }, { 128, "K"}, { 256, "W" }, { 512, "P" }, { 1024, "N" }) : "R",
REC->prev_state & 2048 ? "+" : "", REC->next_comm, REC->next_pid, REC->next_prio
With dynamic sort keys, you can use <event.field> as a sort key. Those
dynamic keys are checked and created on demand. For instance, below is
to sort by next_pid field on the same data file.
$ perf report -s comm,sched:sched_switch.next_pid --stdio
...
# Overhead Command next_pid
# ........ ............... ..........
#
21.23% transmission-gt 0
20.86% swapper 17773
6.62% netctl-auto 0
5.25% swapper 109
5.21% kworker/0:1H 0
1.98% Xephyr 0
1.98% swapper 6524
1.98% swapper 27478
1.37% swapper 27476
1.17% swapper 233
Multiple dynamic sort keys are also supported:
$ perf report -s comm,sched:sched_switch.next_pid,sched:sched_switch.next_comm --stdio
...
# Overhead Command next_pid next_comm
# ........ ............... .......... ................
#
20.86% swapper 17773 transmission-gt
9.64% transmission-gt 0 swapper/0
9.16% transmission-gt 0 swapper/2
5.25% swapper 109 kworker/0:1H
5.21% kworker/0:1H 0 swapper/0
2.14% netctl-auto 0 swapper/2
1.98% netctl-auto 0 swapper/0
1.98% swapper 6524 Xephyr
1.98% swapper 27478 netctl-auto
1.78% transmission-gt 0 swapper/3
1.53% Xephyr 0 swapper/0
1.29% netctl-auto 0 swapper/1
1.29% swapper 27476 netctl-auto
1.21% netctl-auto 0 swapper/3
1.17% swapper 233 irq/33-iwlwifi
Note that pid 0 exists for each cpu so have comm of 'swapper/N'.
This is available on 'perf/dynamic-sort-v1' branch in my tree
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
Any comments are welcome, thanks!
Namhyung
Namhyung Kim (6):
perf hist: Pass struct sample to __hists__add_entry()
perf hist: Save raw_data/size for tracepoint events
tools lib traceevent: Factor out and export print_event_field()
perf tools: Pass evlist to setup_sorting()
perf tools: Add dynamic sort key for tracepoint events
perf tools: Try to show pretty printed output for dynamic sort keys
tools/lib/traceevent/event-parse.c | 124 ++++++++-------
tools/lib/traceevent/event-parse.h | 2 +
tools/perf/builtin-annotate.c | 9 +-
tools/perf/builtin-diff.c | 13 +-
tools/perf/builtin-report.c | 2 +-
tools/perf/builtin-top.c | 14 +-
tools/perf/tests/hists_cumulate.c | 8 +-
tools/perf/tests/hists_filter.c | 2 +-
tools/perf/tests/hists_link.c | 8 +-
tools/perf/tests/hists_output.c | 10 +-
tools/perf/util/hist.c | 33 ++--
tools/perf/util/hist.h | 4 +-
tools/perf/util/sort.c | 309 ++++++++++++++++++++++++++++++++++++-
tools/perf/util/sort.h | 8 +-
14 files changed, 432 insertions(+), 114 deletions(-)
--
2.6.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-12-14 16:50 +0100 |
| Subject | [PATCH 1/6] perf hist: Pass struct sample to __hists__add_entry() |
| Message-ID | <qFDxU-83l-19@gated-at.bofh.it> |
| In reply to | #1291295 |
This is a preparation to add more info into the hist_entry. Also it
already passes too many argument, so passing sample directly will reduce
the overhead of the function call.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-annotate.c | 7 +++++--
tools/perf/builtin-diff.c | 11 +++++------
tools/perf/tests/hists_link.c | 6 +++---
tools/perf/util/hist.c | 31 +++++++++++++++++--------------
tools/perf/util/hist.h | 4 ++--
5 files changed, 32 insertions(+), 27 deletions(-)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1f00dc7cecba..e193340853ba 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -47,7 +47,7 @@ struct perf_annotate {
};
static int perf_evsel__add_sample(struct perf_evsel *evsel,
- struct perf_sample *sample __maybe_unused,
+ struct perf_sample *sample,
struct addr_location *al,
struct perf_annotate *ann)
{
@@ -72,7 +72,10 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
return 0;
}
- he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true);
+ sample->period = 1;
+ sample->weight = 1;
+
+ he = __hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
if (he == NULL)
return -ENOMEM;
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 0b180a885ba3..69f5b1feff39 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -311,11 +311,11 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
}
static int hists__add_entry(struct hists *hists,
- struct addr_location *al, u64 period,
- u64 weight, u64 transaction)
+ struct addr_location *al,
+ struct perf_sample *sample)
{
- if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
- transaction, true) != NULL)
+ if (__hists__add_entry(hists, al, NULL, NULL, NULL,
+ sample, true) != NULL)
return 0;
return -ENOMEM;
}
@@ -336,8 +336,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
return -1;
}
- if (hists__add_entry(hists, &al, sample->period,
- sample->weight, sample->transaction)) {
+ if (hists__add_entry(hists, &al, sample)) {
pr_warning("problem incrementing symbol period, skipping event\n");
goto out_put;
}
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 6243e2b2a245..9eac98daecb8 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -64,7 +64,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
struct perf_evsel *evsel;
struct addr_location al;
struct hist_entry *he;
- struct perf_sample sample = { .period = 1, };
+ struct perf_sample sample = { .period = 1, .weight = 1, };
size_t i = 0, k;
/*
@@ -90,7 +90,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
goto out;
he = __hists__add_entry(hists, &al, NULL,
- NULL, NULL, 1, 1, 0, true);
+ NULL, NULL, &sample, true);
if (he == NULL) {
addr_location__put(&al);
goto out;
@@ -116,7 +116,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
goto out;
he = __hists__add_entry(hists, &al, NULL,
- NULL, NULL, 1, 1, 0, true);
+ NULL, NULL, &sample, true);
if (he == NULL) {
addr_location__put(&al);
goto out;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 56e97f5af598..039bb91d0a92 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -461,7 +461,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
struct symbol *sym_parent,
struct branch_info *bi,
struct mem_info *mi,
- u64 period, u64 weight, u64 transaction,
+ struct perf_sample *sample,
bool sample_self)
{
struct hist_entry entry = {
@@ -478,15 +478,15 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
.level = al->level,
.stat = {
.nr_events = 1,
- .period = period,
- .weight = weight,
+ .period = sample->period,
+ .weight = sample->weight,
},
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent) | al->filtered,
.hists = hists,
.branch_info = bi,
.mem_info = mi,
- .transaction = transaction,
+ .transaction = sample->transaction,
};
return hists__findnew_entry(hists, &entry, al, sample_self);
@@ -526,12 +526,13 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
u64 cost;
struct mem_info *mi = iter->priv;
struct hists *hists = evsel__hists(iter->evsel);
+ struct perf_sample *sample = iter->sample;
struct hist_entry *he;
if (mi == NULL)
return -EINVAL;
- cost = iter->sample->weight;
+ cost = sample->weight;
if (!cost)
cost = 1;
@@ -542,8 +543,10 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
* and this is indirectly achieved by passing period=weight here
* and the he_stat__add_period() function.
*/
+ sample->period = cost;
+
he = __hists__add_entry(hists, al, iter->parent, NULL, mi,
- cost, cost, 0, true);
+ sample, true);
if (!he)
return -ENOMEM;
@@ -630,6 +633,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
struct branch_info *bi;
struct perf_evsel *evsel = iter->evsel;
struct hists *hists = evsel__hists(evsel);
+ struct perf_sample *sample = iter->sample;
struct hist_entry *he = NULL;
int i = iter->curr;
int err = 0;
@@ -643,9 +647,11 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
* The report shows the percentage of total branches captured
* and not events sampled. Thus we use a pseudo period of 1.
*/
+ sample->period = 1;
+ sample->weight = bi->flags.cycles ? bi->flags.cycles : 1;
+
he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
- 1, bi->flags.cycles ? bi->flags.cycles : 1,
- 0, true);
+ sample, true);
if (he == NULL)
return -ENOMEM;
@@ -682,8 +688,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
struct hist_entry *he;
he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
- sample->period, sample->weight,
- sample->transaction, true);
+ sample, true);
if (he == NULL)
return -ENOMEM;
@@ -744,8 +749,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
int err = 0;
he = __hists__add_entry(hists, al, iter->parent, NULL, NULL,
- sample->period, sample->weight,
- sample->transaction, true);
+ sample, true);
if (he == NULL)
return -ENOMEM;
@@ -818,8 +822,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
}
he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
- sample->period, sample->weight,
- sample->transaction, false);
+ sample, false);
if (he == NULL)
return -ENOMEM;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a48a2078d288..36439bfad059 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -114,8 +114,8 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
struct addr_location *al,
struct symbol *parent,
struct branch_info *bi,
- struct mem_info *mi, u64 period,
- u64 weight, u64 transaction,
+ struct mem_info *mi,
+ struct perf_sample *sample,
bool sample_self);
int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
int max_stack_depth, void *arg);
--
2.6.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-12-14 16:50 +0100 |
| Subject | [PATCH 3/6] tools lib traceevent: Factor out and export print_event_field() |
| Message-ID | <qFDxV-83l-31@gated-at.bofh.it> |
| In reply to | #1291295 |
The print_event_field() is to print basic information of a given field
without the print format. It'll be used by dynamic sort keys later.
Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/lib/traceevent/event-parse.c | 124 ++++++++++++++++++++-----------------
tools/lib/traceevent/event-parse.h | 2 +
2 files changed, 68 insertions(+), 58 deletions(-)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 68276f35e323..bd53b562c171 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -4735,73 +4735,81 @@ static int is_printable_array(char *p, unsigned int len)
return 1;
}
+void print_event_field(struct trace_seq *s, void *data,
+ struct format_field *field)
+{
+ unsigned long long val;
+ unsigned int offset, len, i;
+ struct pevent *pevent = field->event->pevent;
+
+ if (field->flags & FIELD_IS_ARRAY) {
+ offset = field->offset;
+ len = field->size;
+ if (field->flags & FIELD_IS_DYNAMIC) {
+ val = pevent_read_number(pevent, data + offset, len);
+ offset = val;
+ len = offset >> 16;
+ offset &= 0xffff;
+ }
+ if (field->flags & FIELD_IS_STRING &&
+ is_printable_array(data + offset, len)) {
+ trace_seq_printf(s, "%s", (char *)data + offset);
+ } else {
+ trace_seq_puts(s, "ARRAY[");
+ for (i = 0; i < len; i++) {
+ if (i)
+ trace_seq_puts(s, ", ");
+ trace_seq_printf(s, "%02x",
+ *((unsigned char *)data + offset + i));
+ }
+ trace_seq_putc(s, ']');
+ field->flags &= ~FIELD_IS_STRING;
+ }
+ } else {
+ val = pevent_read_number(pevent, data + field->offset,
+ field->size);
+ if (field->flags & FIELD_IS_POINTER) {
+ trace_seq_printf(s, "0x%llx", val);
+ } else if (field->flags & FIELD_IS_SIGNED) {
+ switch (field->size) {
+ case 4:
+ /*
+ * If field is long then print it in hex.
+ * A long usually stores pointers.
+ */
+ if (field->flags & FIELD_IS_LONG)
+ trace_seq_printf(s, "0x%x", (int)val);
+ else
+ trace_seq_printf(s, "%d", (int)val);
+ break;
+ case 2:
+ trace_seq_printf(s, "%2d", (short)val);
+ break;
+ case 1:
+ trace_seq_printf(s, "%1d", (char)val);
+ break;
+ default:
+ trace_seq_printf(s, "%lld", val);
+ }
+ } else {
+ if (field->flags & FIELD_IS_LONG)
+ trace_seq_printf(s, "0x%llx", val);
+ else
+ trace_seq_printf(s, "%llu", val);
+ }
+ }
+}
+
static void print_event_fields(struct trace_seq *s, void *data,
int size __maybe_unused,
struct event_format *event)
{
struct format_field *field;
- unsigned long long val;
- unsigned int offset, len, i;
field = event->format.fields;
while (field) {
trace_seq_printf(s, " %s=", field->name);
- if (field->flags & FIELD_IS_ARRAY) {
- offset = field->offset;
- len = field->size;
- if (field->flags & FIELD_IS_DYNAMIC) {
- val = pevent_read_number(event->pevent, data + offset, len);
- offset = val;
- len = offset >> 16;
- offset &= 0xffff;
- }
- if (field->flags & FIELD_IS_STRING &&
- is_printable_array(data + offset, len)) {
- trace_seq_printf(s, "%s", (char *)data + offset);
- } else {
- trace_seq_puts(s, "ARRAY[");
- for (i = 0; i < len; i++) {
- if (i)
- trace_seq_puts(s, ", ");
- trace_seq_printf(s, "%02x",
- *((unsigned char *)data + offset + i));
- }
- trace_seq_putc(s, ']');
- field->flags &= ~FIELD_IS_STRING;
- }
- } else {
- val = pevent_read_number(event->pevent, data + field->offset,
- field->size);
- if (field->flags & FIELD_IS_POINTER) {
- trace_seq_printf(s, "0x%llx", val);
- } else if (field->flags & FIELD_IS_SIGNED) {
- switch (field->size) {
- case 4:
- /*
- * If field is long then print it in hex.
- * A long usually stores pointers.
- */
- if (field->flags & FIELD_IS_LONG)
- trace_seq_printf(s, "0x%x", (int)val);
- else
- trace_seq_printf(s, "%d", (int)val);
- break;
- case 2:
- trace_seq_printf(s, "%2d", (short)val);
- break;
- case 1:
- trace_seq_printf(s, "%1d", (char)val);
- break;
- default:
- trace_seq_printf(s, "%lld", val);
- }
- } else {
- if (field->flags & FIELD_IS_LONG)
- trace_seq_printf(s, "0x%llx", val);
- else
- trace_seq_printf(s, "%llu", val);
- }
- }
+ print_event_field(s, data, field);
field = field->next;
}
}
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 6fc83c7edbe9..4388fd303b99 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -705,6 +705,8 @@ struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *com
struct cmdline *next);
int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
+void print_event_field(struct trace_seq *s, void *data,
+ struct format_field *field);
void pevent_event_info(struct trace_seq *s, struct event_format *event,
struct pevent_record *record);
int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
--
2.6.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-12-14 16:50 +0100 |
| Subject | [PATCH 4/6] perf tools: Pass evlist to setup_sorting() |
| Message-ID | <qFDxU-83l-23@gated-at.bofh.it> |
| In reply to | #1291295 |
This is a preparation to support dynamic sort keys for tracepoint
events. Dynamic sort keys can be created for specific fields in trace
events so it needs the event information.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-annotate.c | 2 +-
tools/perf/builtin-diff.c | 2 +-
tools/perf/builtin-report.c | 2 +-
tools/perf/builtin-top.c | 14 +++++++-------
tools/perf/tests/hists_cumulate.c | 8 ++++----
tools/perf/tests/hists_filter.c | 2 +-
tools/perf/tests/hists_link.c | 2 +-
tools/perf/tests/hists_output.c | 10 +++++-----
tools/perf/util/sort.c | 15 +++++++++------
tools/perf/util/sort.h | 5 +++--
10 files changed, 33 insertions(+), 29 deletions(-)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index e193340853ba..8ed582a44b39 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -370,7 +370,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
if (ret < 0)
goto out_delete;
- if (setup_sorting() < 0)
+ if (setup_sorting(NULL) < 0)
usage_with_options(annotate_usage, options);
if (annotate.use_stdio)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 69f5b1feff39..87063835d741 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -1279,7 +1279,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
sort__mode = SORT_MODE__DIFF;
- if (setup_sorting() < 0)
+ if (setup_sorting(NULL) < 0)
usage_with_options(diff_usage, options);
setup_pager();
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5a454669d075..3b8eb77d586d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -897,7 +897,7 @@ repeat:
symbol_conf.cumulate_callchain = false;
}
- if (setup_sorting() < 0) {
+ if (setup_sorting(session->evlist) < 0) {
if (sort_order)
parse_options_usage(report_usage, options, "s", 1);
if (field_order)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 92fe963e43c4..feb9f5e1ef3d 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1231,11 +1231,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
if (argc)
usage_with_options(top_usage, options);
+ if (!top.evlist->nr_entries &&
+ perf_evlist__add_default(top.evlist) < 0) {
+ pr_err("Not enough memory for event selector list\n");
+ goto out_delete_evlist;
+ }
+
sort__mode = SORT_MODE__TOP;
/* display thread wants entries to be collapsed in a different tree */
sort__need_collapse = 1;
- if (setup_sorting() < 0) {
+ if (setup_sorting(top.evlist) < 0) {
if (sort_order)
parse_options_usage(top_usage, options, "s", 1);
if (field_order)
@@ -1277,12 +1283,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
goto out_delete_evlist;
}
- if (!top.evlist->nr_entries &&
- perf_evlist__add_default(top.evlist) < 0) {
- ui__error("Not enough memory for event selector list\n");
- goto out_delete_evlist;
- }
-
symbol_conf.nr_events = top.evlist->nr_entries;
if (top.delay_secs < 1)
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 8292948bc5f9..e36089212061 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -281,7 +281,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
symbol_conf.cumulate_callchain = false;
perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
- setup_sorting();
+ setup_sorting(NULL);
callchain_register_param(&callchain_param);
err = add_hist_entries(hists, machine);
@@ -428,7 +428,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
symbol_conf.cumulate_callchain = false;
perf_evsel__set_sample_bit(evsel, CALLCHAIN);
- setup_sorting();
+ setup_sorting(NULL);
callchain_register_param(&callchain_param);
err = add_hist_entries(hists, machine);
@@ -486,7 +486,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
symbol_conf.cumulate_callchain = true;
perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
- setup_sorting();
+ setup_sorting(NULL);
callchain_register_param(&callchain_param);
err = add_hist_entries(hists, machine);
@@ -670,7 +670,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
symbol_conf.cumulate_callchain = true;
perf_evsel__set_sample_bit(evsel, CALLCHAIN);
- setup_sorting();
+ setup_sorting(NULL);
callchain_register_param(&callchain_param);
err = add_hist_entries(hists, machine);
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index ccb5b4921f25..2a784befd9ce 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -122,7 +122,7 @@ int test__hists_filter(int subtest __maybe_unused)
goto out;
/* default sort order (comm,dso,sym) will be used */
- if (setup_sorting() < 0)
+ if (setup_sorting(NULL) < 0)
goto out;
machines__init(&machines);
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 9eac98daecb8..c764d69ac6ef 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -294,7 +294,7 @@ int test__hists_link(int subtest __maybe_unused)
goto out;
/* default sort order (comm,dso,sym) will be used */
- if (setup_sorting() < 0)
+ if (setup_sorting(NULL) < 0)
goto out;
machines__init(&machines);
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index 248beec1d917..ebe6cd485b5d 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -134,7 +134,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
field_order = NULL;
sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */
- setup_sorting();
+ setup_sorting(NULL);
/*
* expected output:
@@ -236,7 +236,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
field_order = "overhead,cpu";
sort_order = "pid";
- setup_sorting();
+ setup_sorting(NULL);
/*
* expected output:
@@ -292,7 +292,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
field_order = "comm,overhead,dso";
sort_order = NULL;
- setup_sorting();
+ setup_sorting(NULL);
/*
* expected output:
@@ -366,7 +366,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
field_order = "dso,sym,comm,overhead,dso";
sort_order = "sym";
- setup_sorting();
+ setup_sorting(NULL);
/*
* expected output:
@@ -468,7 +468,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
field_order = "cpu,pid,comm,dso,sym";
sort_order = "dso,pid";
- setup_sorting();
+ setup_sorting(NULL);
/*
* expected output:
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2d8ccd4d9e1b..0c038a27fe5c 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -4,6 +4,8 @@
#include "comm.h"
#include "symbol.h"
#include "evsel.h"
+#include "evlist.h"
+#include <traceevent/event-parse.h>
regex_t parent_regex;
const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -1583,7 +1585,8 @@ int hpp_dimension__add_output(unsigned col)
return __hpp_dimension__add_output(&hpp_sort_dimensions[col]);
}
-int sort_dimension__add(const char *tok)
+static int sort_dimension__add(const char *tok,
+ struct perf_evlist *evlist __maybe_unused)
{
unsigned int i;
@@ -1712,7 +1715,7 @@ static int setup_sort_order(void)
return 0;
}
-static int __setup_sorting(void)
+static int __setup_sorting(struct perf_evlist *evlist)
{
char *tmp, *tok, *str;
const char *sort_keys;
@@ -1743,7 +1746,7 @@ static int __setup_sorting(void)
for (tok = strtok_r(str, ", ", &tmp);
tok; tok = strtok_r(NULL, ", ", &tmp)) {
- ret = sort_dimension__add(tok);
+ ret = sort_dimension__add(tok, evlist);
if (ret == -EINVAL) {
error("Invalid --sort key: `%s'", tok);
break;
@@ -1954,16 +1957,16 @@ out:
return ret;
}
-int setup_sorting(void)
+int setup_sorting(struct perf_evlist *evlist)
{
int err;
- err = __setup_sorting();
+ err = __setup_sorting(evlist);
if (err < 0)
return err;
if (parent_pattern != default_parent_pattern) {
- err = sort_dimension__add("parent");
+ err = sort_dimension__add("parent", evlist);
if (err < 0)
return err;
}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 1c08cd8a5e3b..dd1c2973a836 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -226,10 +226,11 @@ struct sort_entry {
extern struct sort_entry sort_thread;
extern struct list_head hist_entry__sort_list;
-int setup_sorting(void);
+struct perf_evlist;
+struct pevent;
+int setup_sorting(struct perf_evlist *evlist);
int setup_output_field(void);
void reset_output_field(void);
-extern int sort_dimension__add(const char *);
void sort__setup_elide(FILE *fp);
void perf_hpp__set_elide(int idx, bool elide);
--
2.6.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-12-14 16:50 +0100 |
| Subject | [PATCH 2/6] perf hist: Save raw_data/size for tracepoint events |
| Message-ID | <qFDxV-83l-45@gated-at.bofh.it> |
| In reply to | #1291295 |
The raw_data and raw_size fields are to provide tracepoint specific
information. They will be used by dynamic sort keys later.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/hist.c | 2 ++
tools/perf/util/sort.h | 2 ++
2 files changed, 4 insertions(+)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 039bb91d0a92..99a6f1c17806 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -487,6 +487,8 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
.branch_info = bi,
.mem_info = mi,
.transaction = sample->transaction,
+ .raw_data = sample->raw_data,
+ .raw_size = sample->raw_size,
};
return hists__findnew_entry(hists, &entry, al, sample_self);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 31228851e397..1c08cd8a5e3b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -122,6 +122,8 @@ struct hist_entry {
struct branch_info *branch_info;
struct hists *hists;
struct mem_info *mem_info;
+ void *raw_data;
+ u32 raw_size;
struct callchain_root callchain[0]; /* must be last member */
};
--
2.6.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-12-14 18:50 +0100 |
| Subject | Re: [RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) |
| Message-ID | <qFFq3-Q8-21@gated-at.bofh.it> |
| In reply to | #1291295 |
Em Tue, Dec 15, 2015 at 12:46:07AM +0900, Namhyung Kim escreveu:
> Hello,
>
> This is an attempt to improve perf to deal with tracepoint events
> better. The perf tools can handle tracepoint events but perf report
> on them is less useful since they're always sampled in a fixed
> location and not provide event specific info. We can use perf script
> but I always wishes there's more convenient way to see the result.
>
> I suggest dynamic sort keys created for each event.field on demand.
> Consider following example:
>
> # Overhead Command Shared Object Symbol
> # ........ ............... ................ ..............
> #
> 47.22% swapper [kernel.vmlinux] [k] __schedule
> 21.67% transmission-gt [kernel.vmlinux] [k] __schedule
> 8.23% netctl-auto [kernel.vmlinux] [k] __schedule
> 5.53% kworker/0:1H [kernel.vmlinux] [k] __schedule
> 1.98% Xephyr [kernel.vmlinux] [k] __schedule
> 1.33% irq/33-iwlwifi [kernel.vmlinux] [k] __schedule
> 1.17% wpa_cli [kernel.vmlinux] [k] __schedule
> 1.13% rcu_preempt [kernel.vmlinux] [k] __schedule
> 0.85% ksoftirqd/0 [kernel.vmlinux] [k] __schedule
> 0.77% Timer [kernel.vmlinux] [k] __schedule
> ...
>
> Currently perf report only shows this but important info is on the
> event fields, that is:
>
> # sudo cat /sys/kernel/debug/tracing/events/sched/sched_switch/format
> name: sched_switch
> ID: 268
> format:
> field:unsigned short common_type; offset:0; size:2; signed:0;
> field:unsigned char common_flags; offset:2; size:1; signed:0;
> field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
> field:int common_pid; offset:4; size:4; signed:1;
>
> field:char prev_comm[16]; offset:8; size:16; signed:1;
> field:pid_t prev_pid; offset:24; size:4; signed:1;
> field:int prev_prio; offset:28; size:4; signed:1;
> field:long prev_state; offset:32; size:8; signed:1;
> field:char next_comm[16]; offset:40; size:16; signed:1;
> field:pid_t next_pid; offset:56; size:4; signed:1;
> field:int next_prio; offset:60; size:4; signed:1;
>
> print fmt: "prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s%s ==>
> next_comm=%s next_pid=%d next_prio=%d",
> REC->prev_comm, REC->prev_pid, REC->prev_prio,
> REC->prev_state & (2048-1) ? __print_flags(REC->prev_state & (2048-1),
> "|", { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" }, { 16, "Z" }, { 32, "X" },
> { 64, "x" }, { 128, "K"}, { 256, "W" }, { 512, "P" }, { 1024, "N" }) : "R",
> REC->prev_state & 2048 ? "+" : "", REC->next_comm, REC->next_pid, REC->next_prio
>
> With dynamic sort keys, you can use <event.field> as a sort key. Those
> dynamic keys are checked and created on demand. For instance, below is
> to sort by next_pid field on the same data file.
>
> $ perf report -s comm,sched:sched_switch.next_pid --stdio
> ...
> # Overhead Command next_pid
> # ........ ............... ..........
> #
> 21.23% transmission-gt 0
> 20.86% swapper 17773
> 6.62% netctl-auto 0
> 5.25% swapper 109
> 5.21% kworker/0:1H 0
> 1.98% Xephyr 0
> 1.98% swapper 6524
> 1.98% swapper 27478
> 1.37% swapper 27476
> 1.17% swapper 233
>
> Multiple dynamic sort keys are also supported:
>
> $ perf report -s comm,sched:sched_switch.next_pid,sched:sched_switch.next_comm --stdio
> ...
> # Overhead Command next_pid next_comm
> # ........ ............... .......... ................
> #
> 20.86% swapper 17773 transmission-gt
> 9.64% transmission-gt 0 swapper/0
> 9.16% transmission-gt 0 swapper/2
> 5.25% swapper 109 kworker/0:1H
> 5.21% kworker/0:1H 0 swapper/0
> 2.14% netctl-auto 0 swapper/2
> 1.98% netctl-auto 0 swapper/0
> 1.98% swapper 6524 Xephyr
> 1.98% swapper 27478 netctl-auto
> 1.78% transmission-gt 0 swapper/3
> 1.53% Xephyr 0 swapper/0
> 1.29% netctl-auto 0 swapper/1
> 1.29% swapper 27476 netctl-auto
> 1.21% netctl-auto 0 swapper/3
> 1.17% swapper 233 irq/33-iwlwifi
>
> Note that pid 0 exists for each cpu so have comm of 'swapper/N'.
> This is available on 'perf/dynamic-sort-v1' branch in my tree
>
> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
>
> Any comments are welcome, thanks!
> Namhyung
I'll look at the patches for style, but the idea is so nice and natural
I thought about blind merging it :-)
- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | David Ahern <dsahern@gmail.com> |
|---|---|
| Date | 2015-12-14 23:40 +0100 |
| Subject | Re: [RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) |
| Message-ID | <qFJWH-3Ss-57@gated-at.bofh.it> |
| In reply to | #1291376 |
On 12/14/15 10:47 AM, Arnaldo Carvalho de Melo wrote: >> With dynamic sort keys, you can use <event.field> as a sort key. Those >> dynamic keys are checked and created on demand. For instance, below is >> to sort by next_pid field on the same data file. >> >> $ perf report -s comm,sched:sched_switch.next_pid --stdio >> ... >> # Overhead Command next_pid >> # ........ ............... .......... >> # >> 21.23% transmission-gt 0 >> 20.86% swapper 17773 >> 6.62% netctl-auto 0 >> 5.25% swapper 109 >> 5.21% kworker/0:1H 0 >> 1.98% Xephyr 0 >> 1.98% swapper 6524 >> 1.98% swapper 27478 >> 1.37% swapper 27476 >> 1.17% swapper 233 >> >> Multiple dynamic sort keys are also supported: >> >> $ perf report -s comm,sched:sched_switch.next_pid,sched:sched_switch.next_comm --stdio >> ... >> # Overhead Command next_pid next_comm >> # ........ ............... .......... ................ >> # >> 20.86% swapper 17773 transmission-gt >> 9.64% transmission-gt 0 swapper/0 >> 9.16% transmission-gt 0 swapper/2 >> 5.25% swapper 109 kworker/0:1H >> 5.21% kworker/0:1H 0 swapper/0 >> 2.14% netctl-auto 0 swapper/2 >> 1.98% netctl-auto 0 swapper/0 >> 1.98% swapper 6524 Xephyr >> 1.98% swapper 27478 netctl-auto >> 1.78% transmission-gt 0 swapper/3 >> 1.53% Xephyr 0 swapper/0 >> 1.29% netctl-auto 0 swapper/1 >> 1.29% swapper 27476 netctl-auto >> 1.21% netctl-auto 0 swapper/3 >> 1.17% swapper 233 irq/33-iwlwifi >> >> Note that pid 0 exists for each cpu so have comm of 'swapper/N'. > >> This is available on 'perf/dynamic-sort-v1' branch in my tree >> >> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git >> >> Any comments are welcome, thanks! >> Namhyung > > I'll look at the patches for style, but the idea is so nice and natural > I thought about blind merging it :-) > yes, that is a cool feature. For scheduling tracepoints the analysis could be added to perf-sched to ease the burden of the command line syntax. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-12-15 02:50 +0100 |
| Subject | Re: [RFC/PATCHSET 0/6] perf tools: Support dynamic sort keys for tracepoints (v1) |
| Message-ID | <qFMUx-5Li-3@gated-at.bofh.it> |
| In reply to | #1291639 |
Hi David and Arnaldo, On Mon, Dec 14, 2015 at 03:32:06PM -0700, David Ahern wrote: > On 12/14/15 10:47 AM, Arnaldo Carvalho de Melo wrote: > >>With dynamic sort keys, you can use <event.field> as a sort key. Those > >>dynamic keys are checked and created on demand. For instance, below is > >>to sort by next_pid field on the same data file. > >> > >> $ perf report -s comm,sched:sched_switch.next_pid --stdio > >> ... > >> # Overhead Command next_pid > >> # ........ ............... .......... > >> # > >> 21.23% transmission-gt 0 > >> 20.86% swapper 17773 > >> 6.62% netctl-auto 0 > >> 5.25% swapper 109 > >> 5.21% kworker/0:1H 0 > >> 1.98% Xephyr 0 > >> 1.98% swapper 6524 > >> 1.98% swapper 27478 > >> 1.37% swapper 27476 > >> 1.17% swapper 233 > >> > >>Multiple dynamic sort keys are also supported: > >> > >> $ perf report -s comm,sched:sched_switch.next_pid,sched:sched_switch.next_comm --stdio > >> ... > >> # Overhead Command next_pid next_comm > >> # ........ ............... .......... ................ > >> # > >> 20.86% swapper 17773 transmission-gt > >> 9.64% transmission-gt 0 swapper/0 > >> 9.16% transmission-gt 0 swapper/2 > >> 5.25% swapper 109 kworker/0:1H > >> 5.21% kworker/0:1H 0 swapper/0 > >> 2.14% netctl-auto 0 swapper/2 > >> 1.98% netctl-auto 0 swapper/0 > >> 1.98% swapper 6524 Xephyr > >> 1.98% swapper 27478 netctl-auto > >> 1.78% transmission-gt 0 swapper/3 > >> 1.53% Xephyr 0 swapper/0 > >> 1.29% netctl-auto 0 swapper/1 > >> 1.29% swapper 27476 netctl-auto > >> 1.21% netctl-auto 0 swapper/3 > >> 1.17% swapper 233 irq/33-iwlwifi > >> > >>Note that pid 0 exists for each cpu so have comm of 'swapper/N'. > > > >>This is available on 'perf/dynamic-sort-v1' branch in my tree > >> > >> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git > >> > >>Any comments are welcome, thanks! > >>Namhyung > > > >I'll look at the patches for style, but the idea is so nice and natural > >I thought about blind merging it :-) Hehe, thanks! > > yes, that is a cool feature. > > For scheduling tracepoints the analysis could be added to perf-sched to ease > the burden of the command line syntax. Yes, the existing tracepoints analysis command might use or wrap it. For command line syntax, I think it'd be better to provide shorter way to identify the events - like (non-ambiguous) substring match or positional parameter (e.g. %1 for first event). For example, the last example above can be: $ perf report -s comm,switch.next_pid,switch.next_comm or $ perf report -s comm,%1.next_pid,%1.next_comm Thanks, Namhyung -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web