All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4)
@ 2015-12-22 17:06 Namhyung Kim
  2015-12-22 17:06 ` [PATCH 01/13] perf hist: Pass struct sample to __hists__add_entry() Namhyung Kim
                   ` (13 more replies)
  0 siblings, 14 replies; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

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.

 * changes in v4)
  - support '<event>.*' syntax for dynamic sort key
  - skip unrelated dynamic fields in the output
  - add 'trace_fields' sort key  (Jiri)
  - reuse get_trace_output function  (Jiri)
  
 * changes in v3)
  - save trace_output for dynamic entries  (Jiri)
  - update field length for each entry

 * changes in v2)
  - add 'trace' sort key and make it default  (Jiri)
  - add '--raw-trace' option and '/raw' field modifier  (Jiri)
  - support event name shortcuts  (David)


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 and the event name can
be simplified (or even omitted in a couple of ways (see patch 10/10):

  $ perf report -s comm,switch.next_pid,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'.

Also now it add a new 'trace' sort key to print whole trace output.
Below is the output using sched_switch plugin.

  $ perf report -s trace --stdio
  ...
  # Overhead  Trace output                                                 
  # ........  ...................................................
  #
       9.48%  swapper/0:0 [120] R ==> transmission-gt:17773 [120]          
       9.48%  transmission-gt:17773 [120] S ==> swapper/0:0 [120]          
       9.04%  swapper/2:0 [120] R ==> transmission-gt:17773 [120]          
       8.92%  transmission-gt:17773 [120] S ==> swapper/2:0 [120]          
       5.25%  swapper/0:0 [120] R ==> kworker/0:1H:109 [100]               
       5.21%  kworker/0:1H:109 [100] S ==> swapper/0:0 [120]               
       1.78%  swapper/3:0 [120] R ==> transmission-gt:17773 [120]          
       1.78%  transmission-gt:17773 [120] S ==> swapper/3:0 [120]          
       1.53%  Xephyr:6524 [120] S ==> swapper/0:0 [120]                    
       1.53%  swapper/0:0 [120] R ==> Xephyr:6524 [120]                    
       1.17%  swapper/2:0 [120] R ==> irq/33-iwlwifi:233 [49]              
       1.13%  irq/33-iwlwifi:233 [49] S ==> swapper/2:0 [120]             
  ...

The 'trace_fields' sort key is to show each fields separately.  This
is actually same as using -s 'sched_switch.*' in this case, but the
'trace_fields' sort key also works for more than one events:

  $ perf report -s trace_fields --stdio
  ...
  # Overhead    prev_comm  prev_pid   prev_prio  prev_state     next_comm  next_pid  next_prio
  # ........  ...........  .........  .........  ..........  ............  ........  .........
  #
       3.82%    swapper/0         0         120           0   netctl-auto     18711        120
       3.75%  netctl-auto     18711         120           1     swapper/0         0        120
       2.24%    swapper/1         0         120           0   netctl-auto     18709        120
       2.24%  netctl-auto     18709         120           1     swapper/1         0        120
       1.80%    swapper/2         0         120           0   rcu_preempt         7        120
       1.80%    swapper/2         0         120           0   netctl-auto     18711        120
       1.80%  rcu_preempt         7         120           1     swapper/2         0        120
       1.80%  netctl-auto     18711         120           1     swapper/2         0        120
  ...

If a data file has only tracepoint events, the 'trace' sort key will
be used by default.  However, if user gave --raw-trace option also,
it'll use 'trace_fields' instead.

This is available on 'perf/dynamic-sort-v4' 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 (13):
  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[s]
  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
  perf tools: Add 'trace' sort key
  perf tools: Add --raw-trace option
  perf tools: Support shortcuts for events in dynamic sort keys
  perf tools: Support '<event>.*' dynamic sort key
  perf tools: Skip dynamic fields not defined for current event
  perf tools: Add 'trace_fields' dynamic sort key
  perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events

 tools/lib/traceevent/event-parse.c       | 125 +++----
 tools/lib/traceevent/event-parse.h       |   4 +
 tools/perf/Documentation/perf-report.txt |   3 +
 tools/perf/Documentation/perf-top.txt    |   3 +
 tools/perf/builtin-annotate.c            |   9 +-
 tools/perf/builtin-diff.c                |  13 +-
 tools/perf/builtin-report.c              |   4 +-
 tools/perf/builtin-top.c                 |  16 +-
 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/ui/browsers/hists.c           |   7 +-
 tools/perf/ui/gtk/hists.c                |   4 +-
 tools/perf/ui/hist.c                     |   2 +-
 tools/perf/ui/stdio/hist.c               |   6 +-
 tools/perf/util/hist.c                   |  38 ++-
 tools/perf/util/hist.h                   |  19 +-
 tools/perf/util/sort.c                   | 539 ++++++++++++++++++++++++++++++-
 tools/perf/util/sort.h                   |  10 +-
 tools/perf/util/symbol.h                 |   3 +-
 21 files changed, 700 insertions(+), 133 deletions(-)

-- 
2.6.4


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH 01/13] perf hist: Pass struct sample to __hists__add_entry()
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
@ 2015-12-22 17:06 ` Namhyung Kim
  2016-01-09 16:22   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-22 17:06 ` [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events Namhyung Kim
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

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 e18f1b995ffd..b5b8db0b0338 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


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
  2015-12-22 17:06 ` [PATCH 01/13] perf hist: Pass struct sample to __hists__add_entry() Namhyung Kim
@ 2015-12-22 17:06 ` Namhyung Kim
  2015-12-23 21:43   ` Arnaldo Carvalho de Melo
  2015-12-22 17:07 ` [PATCH 03/13] tools lib traceevent: Factor out and export print_event_field[s] Namhyung Kim
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

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 | 4 ++++
 tools/perf/util/sort.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 039bb91d0a92..c0c92a3daa69 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);
@@ -801,6 +803,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
 			.sym = al->sym,
 		},
 		.parent = iter->parent,
+		.raw_data = sample->raw_data,
+		.raw_size = sample->raw_size,
 	};
 	int i;
 	struct callchain_cursor cursor;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 86f05e7a5566..d29898708dbd 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


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 03/13] tools lib traceevent: Factor out and export print_event_field[s]
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
  2015-12-22 17:06 ` [PATCH 01/13] perf hist: Pass struct sample to __hists__add_entry() Namhyung Kim
  2015-12-22 17:06 ` [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2015-12-23  8:50   ` Wangnan (F)
  2015-12-23 13:08   ` [PATCH v4.1 " Namhyung Kim
  2015-12-22 17:07 ` [PATCH 04/13] perf tools: Pass evlist to setup_sorting() Namhyung Kim
                   ` (10 subsequent siblings)
  13 siblings, 2 replies; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

The print_event_field() and print_event_field() are to print basic
information of a given field or event without the print format.  They'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 | 125 ++++++++++++++++++++-----------------
 tools/lib/traceevent/event-parse.h |   4 ++
 2 files changed, 70 insertions(+), 59 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 68276f35e323..1b43f2b9aebe 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -4735,73 +4735,80 @@ static int is_printable_array(char *p, unsigned int len)
 	return 1;
 }
 
-static void print_event_fields(struct trace_seq *s, void *data,
-			       int size __maybe_unused,
-			       struct event_format *event)
+void print_event_field(struct trace_seq *s, void *data,
+		       struct format_field *field)
 {
-	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;
-			}
+	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 {
-			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 {
+			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%llx", val);
+					trace_seq_printf(s, "0x%x", (int)val);
 				else
-					trace_seq_printf(s, "%llu", val);
+					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);
 		}
+	}
+}
+
+void print_event_fields(struct trace_seq *s, void *data,
+			int size __maybe_unused, struct event_format *event)
+{
+	struct format_field *field;
+
+	field = event->format.fields;
+	while (field) {
+		trace_seq_printf(s, " %s=", field->name);
+		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..600c73277a6f 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -705,6 +705,10 @@ 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 print_event_fields(struct trace_seq *s, void *data,
+			int size __maybe_unused, struct event_format *event);
 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


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 04/13] perf tools: Pass evlist to setup_sorting()
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (2 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 03/13] tools lib traceevent: Factor out and export print_event_field[s] Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-09 16:23   ` [tip:perf/core] perf top: Create the evlist sooner tip-bot for Namhyung Kim
  2016-01-09 16:23   ` [tip:perf/core] perf tools: Pass evlist to setup_sorting() tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 05/13] perf tools: Add dynamic sort key for tracepoint events Namhyung Kim
                   ` (9 subsequent siblings)
  13 siblings, 2 replies; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

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 b5b8db0b0338..cc5c1267c738 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 2a7330b99b82..ea53c816640a 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 9ebd67a42ede..005825942441 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 d29898708dbd..1a00f1eb9d21 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


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 05/13] perf tools: Add dynamic sort key for tracepoint events
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (3 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 04/13] perf tools: Pass evlist to setup_sorting() Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-04 15:04   ` Arnaldo Carvalho de Melo
  2016-01-09 16:23   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 06/13] perf tools: Try to show pretty printed output for dynamic sort keys Namhyung Kim
                   ` (8 subsequent siblings)
  13 siblings, 2 replies; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

The existing sort keys are less useful for tracepoint events in that
they are always sampled at a same location.

For example, report on sched:sched_switch event looks like following

  # 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

In fact, tracepoints have meaningful information in their fields but
there's no way to use in the perf report currently.  The dynamic sort
keys are to overcome this problem.

The sched:sched_switch events have following fields:

  # 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'.

Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 213 insertions(+)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 0c038a27fe5c..763d810cdb38 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1531,6 +1531,216 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
 	return 0;
 }
 
+struct hpp_dynamic_entry {
+	struct perf_hpp_fmt hpp;
+	struct perf_evsel *evsel;
+	struct format_field *field;
+	unsigned dynamic_len;
+};
+
+static int hde_width(struct hpp_dynamic_entry *hde)
+{
+	if (!hde->hpp.len) {
+		int len = hde->dynamic_len;
+		int namelen = strlen(hde->field->name);
+		int fieldlen = hde->field->size;
+
+		if (namelen > len)
+			len = namelen;
+
+		if (!(hde->field->flags & FIELD_IS_STRING)) {
+			/* length for print hex numbers */
+			fieldlen = hde->field->size * 2 + 2;
+		}
+		if (fieldlen > len)
+			len = fieldlen;
+
+		hde->hpp.len = len;
+	}
+	return hde->hpp.len;
+}
+
+static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+			      struct perf_evsel *evsel __maybe_unused)
+{
+	struct hpp_dynamic_entry *hde;
+	size_t len = fmt->user_len;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (!len)
+		len = hde_width(hde);
+
+	return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, hde->field->name);
+}
+
+static int __sort__hde_width(struct perf_hpp_fmt *fmt,
+			     struct perf_hpp *hpp __maybe_unused,
+			     struct perf_evsel *evsel __maybe_unused)
+{
+	struct hpp_dynamic_entry *hde;
+	size_t len = fmt->user_len;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (!len)
+		len = hde_width(hde);
+
+	return len;
+}
+
+static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+			     struct hist_entry *he)
+{
+	struct hpp_dynamic_entry *hde;
+	size_t len = fmt->user_len;
+	struct trace_seq seq;
+	int ret;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (!len)
+		len = hde_width(hde);
+
+	if (hists_to_evsel(he->hists) != hde->evsel)
+		return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, "N/A");
+
+	trace_seq_init(&seq);
+	print_event_field(&seq, he->raw_data, hde->field);
+	ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, seq.buffer);
+	trace_seq_destroy(&seq);
+	return ret;
+}
+
+static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
+			       struct hist_entry *a, struct hist_entry *b)
+{
+	struct hpp_dynamic_entry *hde;
+	struct format_field *field;
+	unsigned offset, size;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (hists_to_evsel(a->hists) != hde->evsel)
+		return 0;
+
+	field = hde->field;
+	if (field->flags & FIELD_IS_DYNAMIC) {
+		unsigned long long dyn;
+
+		pevent_read_number_field(field, a->raw_data, &dyn);
+		offset = dyn & 0xffff;
+		size = (dyn >> 16) & 0xffff;
+
+		/* record max width for output */
+		if (size > hde->dynamic_len)
+			hde->dynamic_len = size;
+	} else {
+		offset = field->offset;
+		size = field->size;
+	}
+
+	return memcmp(a->raw_data + offset, b->raw_data + offset, size);
+}
+
+static struct hpp_dynamic_entry *
+__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
+{
+	struct hpp_dynamic_entry *hde;
+
+	hde = malloc(sizeof(*hde));
+	if (hde == NULL) {
+		pr_debug("Memory allocation failed\n");
+		return NULL;
+	}
+
+	hde->evsel = evsel;
+	hde->field = field;
+	hde->dynamic_len = 0;
+
+	hde->hpp.name = field->name;
+	hde->hpp.header = __sort__hde_header;
+	hde->hpp.width  = __sort__hde_width;
+	hde->hpp.entry  = __sort__hde_entry;
+	hde->hpp.color  = NULL;
+
+	hde->hpp.cmp = __sort__hde_cmp;
+	hde->hpp.collapse = __sort__hde_cmp;
+	hde->hpp.sort = __sort__hde_cmp;
+
+	INIT_LIST_HEAD(&hde->hpp.list);
+	INIT_LIST_HEAD(&hde->hpp.sort_list);
+	hde->hpp.elide = false;
+	hde->hpp.len = 0;
+	hde->hpp.user_len = 0;
+
+	return hde;
+}
+
+static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
+{
+	char *str, *event_name, *field_name;
+	struct perf_evsel *evsel, *pos;
+	struct format_field *field;
+	struct hpp_dynamic_entry *hde;
+	int ret = 0;
+
+	if (evlist == NULL)
+		return -ENOENT;
+
+	str = strdup(tok);
+	if (str == NULL)
+		return -ENOMEM;
+
+	event_name = str;
+	field_name = strchr(str, '.');
+	if (field_name == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+	*field_name++ = '\0';
+
+	evsel = NULL;
+	evlist__for_each(evlist, pos) {
+		if (!strcmp(pos->name, event_name)) {
+			evsel = pos;
+			break;
+		}
+	}
+
+	if (evsel == NULL) {
+		pr_debug("Cannot find event: %s\n", event_name);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+		pr_debug("%s is not a tracepoint event\n", event_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	field = pevent_find_any_field(evsel->tp_format, field_name);
+	if (field == NULL) {
+		pr_debug("Cannot find event field for %s.%s\n",
+		       event_name, field_name);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	hde = __alloc_dynamic_entry(evsel, field);
+	if (hde == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	perf_hpp__register_sort_field(&hde->hpp);
+
+out:
+	free(str);
+	return ret;
+}
+
 static int __sort_dimension__add(struct sort_dimension *sd)
 {
 	if (sd->taken)
@@ -1667,6 +1877,9 @@ static int sort_dimension__add(const char *tok,
 		return 0;
 	}
 
+	if (!add_dynamic_entry(evlist, tok))
+		return 0;
+
 	return -ESRCH;
 }
 
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 06/13] perf tools: Try to show pretty printed output for dynamic sort keys
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (4 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 05/13] perf tools: Add dynamic sort key for tracepoint events Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-04 15:16   ` Arnaldo Carvalho de Melo
  2016-01-09 16:24   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 07/13] perf tools: Add 'trace' sort key Namhyung Kim
                   ` (7 subsequent siblings)
  13 siblings, 2 replies; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

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@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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 c0c92a3daa69..ef1a4a5cc610 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -978,6 +978,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);
 }
 
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 763d810cdb38..91c48f7a7f02 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);
-	print_event_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);
+		print_event_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 1a00f1eb9d21..f6d2a7e3e7f2 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 */
 };
 
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 07/13] perf tools: Add 'trace' sort key
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (5 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 06/13] perf tools: Try to show pretty printed output for dynamic sort keys Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-09 16:24   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 08/13] perf tools: Add --raw-trace option Namhyung Kim
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

The 'trace' sort key is to show tracepoint event output using either
print fmt or plugin.  For example sched_switch event (using plugin) will
show output like below:

  $ perf report -s trace --stdio
  ...
  # Overhead  Trace output
  # ........  ...................................................
  #
       9.48%  swapper/0:0 [120] R ==> transmission-gt:17773 [120]
       9.48%  transmission-gt:17773 [120] S ==> swapper/0:0 [120]
       9.04%  swapper/2:0 [120] R ==> transmission-gt:17773 [120]
       8.92%  transmission-gt:17773 [120] S ==> swapper/2:0 [120]
       5.25%  swapper/0:0 [120] R ==> kworker/0:1H:109 [100]
       5.21%  kworker/0:1H:109 [100] S ==> swapper/0:0 [120]
       1.78%  swapper/3:0 [120] R ==> transmission-gt:17773 [120]
       1.78%  transmission-gt:17773 [120] S ==> swapper/3:0 [120]
       1.53%  Xephyr:6524 [120] S ==> swapper/0:0 [120]
       1.53%  swapper/0:0 [120] R ==> Xephyr:6524 [120]
       1.17%  swapper/2:0 [120] R ==> irq/33-iwlwifi:233 [49]
       1.13%  irq/33-iwlwifi:233 [49] S ==> swapper/2:0 [120]

Note that the 'trace' sort key works only for tracepoint events.  If
it's used to other type of events, just "N/A" will be printed.

Suggested-by: Jiri Olsa <jolsa@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/hist.h |  1 +
 tools/perf/util/sort.c | 76 +++++++++++++++++++++++++++++++++++++++-----------
 tools/perf/util/sort.h |  1 +
 3 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 36439bfad059..15b22c563d30 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,6 +52,7 @@ enum hist_column {
 	HISTC_MEM_IADDR_SYMBOL,
 	HISTC_TRANSACTION,
 	HISTC_CYCLES,
+	HISTC_TRACE,
 	HISTC_NR_COLS, /* Last entry */
 };
 
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 91c48f7a7f02..582f632353bc 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -445,6 +445,65 @@ struct sort_entry sort_socket = {
 	.se_width_idx	= HISTC_SOCKET,
 };
 
+/* --sort trace */
+
+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 int64_t
+sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	struct perf_evsel *evsel;
+
+	evsel = hists_to_evsel(left->hists);
+	if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+		return 0;
+
+	if (left->trace_output == NULL)
+		left->trace_output = get_trace_output(left);
+	if (right->trace_output == NULL)
+		right->trace_output = get_trace_output(right);
+
+	hists__new_col_len(left->hists, HISTC_TRACE, strlen(left->trace_output));
+	hists__new_col_len(right->hists, HISTC_TRACE, strlen(right->trace_output));
+
+	return strcmp(right->trace_output, left->trace_output);
+}
+
+static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
+				    size_t size, unsigned int width)
+{
+	struct perf_evsel *evsel;
+
+	evsel = hists_to_evsel(he->hists);
+	if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+		return scnprintf(bf, size, "%-*.*s", width, width, "N/A");
+
+	if (he->trace_output == NULL)
+		he->trace_output = get_trace_output(he);
+	return repsep_snprintf(bf, size, "%-*.*s", width, width, he->trace_output);
+}
+
+struct sort_entry sort_trace = {
+	.se_header      = "Trace output",
+	.se_cmp	        = sort__trace_cmp,
+	.se_snprintf    = hist_entry__trace_snprintf,
+	.se_width_idx	= HISTC_TRACE,
+};
+
 /* sort keys for branch stacks */
 
 static int64_t
@@ -1314,6 +1373,7 @@ static struct sort_dimension common_sort_dimensions[] = {
 	DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
 	DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
 	DIM(SORT_TRANSACTION, "transaction", sort_transaction),
+	DIM(SORT_TRACE, "trace", sort_trace),
 };
 
 #undef DIM
@@ -1560,22 +1620,6 @@ 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)
 {
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index f6d2a7e3e7f2..6b7590ade229 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -183,6 +183,7 @@ enum sort_type {
 	SORT_LOCAL_WEIGHT,
 	SORT_GLOBAL_WEIGHT,
 	SORT_TRANSACTION,
+	SORT_TRACE,
 
 	/* branch stack specific sort keys */
 	__SORT_BRANCH_STACK,
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 08/13] perf tools: Add --raw-trace option
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (6 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 07/13] perf tools: Add 'trace' sort key Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-09 16:24   ` [tip:perf/core] perf report/top: " tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 09/13] perf tools: Support shortcuts for events in dynamic sort keys Namhyung Kim
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

The --raw-trace option is to prevent pretty printing by event's
print_fmt or plugin.  Besides that, each dynamic sort key now receives
'raw' suffix separated by '/' to apply the raw trace to a specific
field.

  $ perf report -s comm,kmem:kmalloc.gfp_flags
  ...
  # 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

Now

  $ perf report -s comm,kmem:kmalloc.gfp_flags --raw-trace
or
  $ perf report -s comm,kmem:kmalloc.gfp_flags/raw
  ...
  # Overhead  Command   gfp_flags
  # ........  .......  ..........
  #
      99.89%  perf          32848
       0.06%  sleep           208
       0.03%  perf          32976
       0.01%  perf            208

Suggested-by: Jiri Olsa <jolsa@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Documentation/perf-report.txt |  3 +++
 tools/perf/Documentation/perf-top.txt    |  3 +++
 tools/perf/builtin-report.c              |  2 ++
 tools/perf/builtin-top.c                 |  2 ++
 tools/perf/util/sort.c                   | 31 ++++++++++++++++++++++++++++---
 tools/perf/util/symbol.h                 |  3 ++-
 6 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index dab99ed2b339..ae7cd91727f6 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -371,6 +371,9 @@ include::itrace.txt[]
 --socket-filter::
 	Only report the samples on the processor socket that match with this filter
 
+--raw-trace::
+	When displaying traceevent output, do not use print fmt or plugins.
+
 include::callchain-overhead-calculation.txt[]
 
 SEE ALSO
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 556cec09bf50..b0e60e17db38 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -230,6 +230,9 @@ Default is to monitor all CPUS.
 	The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
 	Note that this feature may not be available on all processors.
 
+--raw-trace::
+	When displaying traceevent output, do not use print fmt or plugins.
+
 INTERACTIVE PROMPTING KEYS
 --------------------------
 
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ea53c816640a..f10c663af996 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -788,6 +788,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "Show callgraph from reference event"),
 	OPT_INTEGER(0, "socket-filter", &report.socket_filter,
 		    "only show processor socket that match with this filter"),
+	OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
+		    "Show raw trace event output (do not use print fmt or plugins)"),
 	OPT_END()
 	};
 	struct perf_data_file file = {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 005825942441..bf01cbb0ef23 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1210,6 +1210,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_CALLBACK('j', "branch-filter", &opts->branch_stack,
 		     "branch filter mask", "branch stack filter modes",
 		     parse_branch_stack),
+	OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
+		    "Show raw trace event output (do not use print fmt or plugins)"),
 	OPT_END()
 	};
 	const char * const top_usage[] = {
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 582f632353bc..df9e5989e209 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -459,7 +459,11 @@ static char *get_trace_output(struct hist_entry *he)
 	evsel = hists_to_evsel(he->hists);
 
 	trace_seq_init(&seq);
-	pevent_event_info(&seq, evsel->tp_format, &rec);
+	if (symbol_conf.raw_trace)
+		print_event_fields(&seq, he->raw_data, he->raw_size,
+				   evsel->tp_format);
+	else
+		pevent_event_info(&seq, evsel->tp_format, &rec);
 	return seq.buffer;
 }
 
@@ -1596,6 +1600,7 @@ struct hpp_dynamic_entry {
 	struct perf_evsel *evsel;
 	struct format_field *field;
 	unsigned dynamic_len;
+	bool raw_trace;
 };
 
 static int hde_width(struct hpp_dynamic_entry *hde)
@@ -1628,6 +1633,9 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
 	size_t namelen;
 	bool last = false;
 
+	if (hde->raw_trace)
+		return;
+
 	/* parse pretty print result and update max length */
 	if (!he->trace_output)
 		he->trace_output = get_trace_output(he);
@@ -1708,8 +1716,10 @@ 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;
+	if (hde->raw_trace)
+		goto raw_field;
 
+	field = hde->field;
 	namelen = strlen(field->name);
 	str = he->trace_output;
 
@@ -1738,6 +1748,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 
 	if (str == NULL) {
 		struct trace_seq seq;
+raw_field:
 		trace_seq_init(&seq);
 		print_event_field(&seq, he->raw_data, hde->field);
 		str = seq.buffer;
@@ -1818,10 +1829,11 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
 
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
-	char *str, *event_name, *field_name;
+	char *str, *event_name, *field_name, *raw_opt;
 	struct perf_evsel *evsel, *pos;
 	struct format_field *field;
 	struct hpp_dynamic_entry *hde;
+	bool raw_trace = symbol_conf.raw_trace;
 	int ret = 0;
 
 	if (evlist == NULL)
@@ -1839,6 +1851,18 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	}
 	*field_name++ = '\0';
 
+	raw_opt = strchr(field_name, '/');
+	if (raw_opt) {
+		*raw_opt++ = '\0';
+
+		if (strcmp(raw_opt, "raw")) {
+			pr_err("Unsupported field option %s\n", raw_opt);
+			ret = -EINVAL;
+			goto out;
+		}
+		raw_trace = true;
+	}
+
 	evsel = NULL;
 	evlist__for_each(evlist, pos) {
 		if (!strcmp(pos->name, event_name)) {
@@ -1872,6 +1896,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 		ret = -ENOMEM;
 		goto out;
 	}
+	hde->raw_trace = raw_trace;
 
 	perf_hpp__register_sort_field(&hde->hpp);
 
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 857f707ac12b..ccd1caa40e11 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -109,7 +109,8 @@ struct symbol_conf {
 			branch_callstack,
 			has_filter,
 			show_ref_callgraph,
-			hide_unresolved;
+			hide_unresolved,
+			raw_trace;
 	const char	*vmlinux_name,
 			*kallsyms_name,
 			*source_prefix,
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 09/13] perf tools: Support shortcuts for events in dynamic sort keys
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (7 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 08/13] perf tools: Add --raw-trace option Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-09 16:25   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 10/13] perf tools: Support '<event>.*' dynamic sort key Namhyung Kim
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

The dynamic sort key requires event name but specifying full event name
is rather inconvenient.  This patch adds more ways to identify the event
in a more compact way.

  1. If session has just one event, event name can be omitted.
  2. Events can be accessed by index preceded by a percent sign.
  3. A part of the name can be used, if it's not ambiguous.  The partial
     name should not contain ':' in it.
  4. Full system + event name is still used, it should contain ':'.

So in the below example all does same thing:

  $ perf record -e sched:sched_switch -a sleep 1

  $ perf report -s next_pid,next_comm
  $ perf report -s %1.next_pid,%1.next_comm
  $ perf report -s switch.next_pid,switch.next_comm
  $ perf report -s sched:sched_switch.next_pid,sched:sched_switch_.next_comm

Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 107 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 87 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index df9e5989e209..78496f0555ec 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1827,10 +1827,90 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
 	return hde;
 }
 
+static int parse_field_name(char *str, char **event, char **field, char **opt)
+{
+	char *event_name, *field_name, *opt_name;
+
+	event_name = str;
+	field_name = strchr(str, '.');
+
+	if (field_name) {
+		*field_name++ = '\0';
+	} else {
+		event_name = NULL;
+		field_name = str;
+	}
+
+	opt_name = strchr(field_name, '/');
+	if (opt_name)
+		*opt_name++ = '\0';
+
+	*event = event_name;
+	*field = field_name;
+	*opt   = opt_name;
+
+	return 0;
+}
+
+/* find match evsel using a given event name.  The event name can be:
+ *   1. NULL - only valid for single event session
+ *   2. '%' + event index (e.g. '%1' for first event)
+ *   3. full event name (e.g. sched:sched_switch)
+ *   4. partial event name (should not contain ':')
+ */
+static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
+{
+	struct perf_evsel *evsel = NULL;
+	struct perf_evsel *pos;
+	bool full_name;
+
+	/* case 1 */
+	if (event_name == NULL) {
+		if (evlist->nr_entries != 1) {
+			pr_debug("event name should be given\n");
+			return NULL;
+		}
+
+		return perf_evlist__first(evlist);
+	}
+
+	/* case 2 */
+	if (event_name[0] == '%') {
+		int nr = strtol(event_name+1, NULL, 0);
+
+		if (nr > evlist->nr_entries)
+			return NULL;
+
+		evsel = perf_evlist__first(evlist);
+		while (--nr > 0)
+			evsel = perf_evsel__next(evsel);
+
+		return evsel;
+	}
+
+	full_name = !!strchr(event_name, ':');
+	evlist__for_each(evlist, pos) {
+		/* case 3 */
+		if (full_name && !strcmp(pos->name, event_name))
+			return pos;
+		/* case 4 */
+		if (!full_name && strstr(pos->name, event_name)) {
+			if (evsel) {
+				pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
+					 event_name, evsel->name, pos->name);
+				return NULL;
+			}
+			evsel = pos;
+		}
+	}
+
+	return evsel;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
-	char *str, *event_name, *field_name, *raw_opt;
-	struct perf_evsel *evsel, *pos;
+	char *str, *event_name, *field_name, *opt_name;
+	struct perf_evsel *evsel;
 	struct format_field *field;
 	struct hpp_dynamic_entry *hde;
 	bool raw_trace = symbol_conf.raw_trace;
@@ -1843,34 +1923,21 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	if (str == NULL)
 		return -ENOMEM;
 
-	event_name = str;
-	field_name = strchr(str, '.');
-	if (field_name == NULL) {
+	if (parse_field_name(str, &event_name, &field_name, &opt_name) < 0) {
 		ret = -EINVAL;
 		goto out;
 	}
-	*field_name++ = '\0';
 
-	raw_opt = strchr(field_name, '/');
-	if (raw_opt) {
-		*raw_opt++ = '\0';
-
-		if (strcmp(raw_opt, "raw")) {
-			pr_err("Unsupported field option %s\n", raw_opt);
+	if (opt_name) {
+		if (strcmp(opt_name, "raw")) {
+			pr_debug("unsupported field option %s\n", opt_name);
 			ret = -EINVAL;
 			goto out;
 		}
 		raw_trace = true;
 	}
 
-	evsel = NULL;
-	evlist__for_each(evlist, pos) {
-		if (!strcmp(pos->name, event_name)) {
-			evsel = pos;
-			break;
-		}
-	}
-
+	evsel = find_evsel(evlist, event_name);
 	if (evsel == NULL) {
 		pr_debug("Cannot find event: %s\n", event_name);
 		ret = -ENOENT;
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 10/13] perf tools: Support '<event>.*' dynamic sort key
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (8 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 09/13] perf tools: Support shortcuts for events in dynamic sort keys Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-09 16:25   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 11/13] perf tools: Skip dynamic fields not defined for current event Namhyung Kim
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Support '*' character for field name to add all (non-common) fields as
sort keys easily.

  $ perf report -s 'switch.*' --stdio
  ...
  # Overhead    prev_comm  prev_pid   prev_prio  prev_state     next_comm  next_pid  next_prio
  # ........  ...........  .........  .........  ..........  ............  ........  .........
  #
       3.82%    swapper/0         0         120           0   netctl-auto     18711        120
       3.75%  netctl-auto     18711         120           1     swapper/0         0        120
       2.24%    swapper/1         0         120           0   netctl-auto     18709        120
       2.24%  netctl-auto     18709         120           1     swapper/1         0        120
       1.80%    swapper/2         0         120           0   rcu_preempt         7        120
       1.80%    swapper/2         0         120           0   netctl-auto     18711        120
       1.80%  rcu_preempt         7         120           1     swapper/2         0        120
       1.80%  netctl-auto     18711         120           1     swapper/2         0        120
  ...

Suggested-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 49 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 78496f0555ec..297383e0abc5 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1907,12 +1907,27 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 	return evsel;
 }
 
+static int __dynamic_dimension__add(struct perf_evsel *evsel,
+				    struct format_field *field,
+				    bool raw_trace)
+{
+	struct hpp_dynamic_entry *hde;
+
+	hde = __alloc_dynamic_entry(evsel, field);
+	if (hde == NULL)
+		return -ENOMEM;
+
+	hde->raw_trace = raw_trace;
+
+	perf_hpp__register_sort_field(&hde->hpp);
+	return 0;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
 	char *str, *event_name, *field_name, *opt_name;
 	struct perf_evsel *evsel;
 	struct format_field *field;
-	struct hpp_dynamic_entry *hde;
 	bool raw_trace = symbol_conf.raw_trace;
 	int ret = 0;
 
@@ -1950,22 +1965,26 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 		goto out;
 	}
 
-	field = pevent_find_any_field(evsel->tp_format, field_name);
-	if (field == NULL) {
-		pr_debug("Cannot find event field for %s.%s\n",
-		       event_name, field_name);
-		ret = -ENOENT;
-		goto out;
-	}
+	if (!strcmp(field_name, "*")) {
+		field = evsel->tp_format->format.fields;
 
-	hde = __alloc_dynamic_entry(evsel, field);
-	if (hde == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	hde->raw_trace = raw_trace;
+		while (field) {
+			ret = __dynamic_dimension__add(evsel, field, raw_trace);
+			if (ret < 0)
+				goto out;
 
-	perf_hpp__register_sort_field(&hde->hpp);
+			field = field->next;
+		}
+	} else {
+		field = pevent_find_any_field(evsel->tp_format, field_name);
+		if (field == NULL) {
+			pr_debug("Cannot find event field for %s.%s\n",
+				 event_name, field_name);
+			return -ENOENT;
+		}
+
+		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+	}
 
 out:
 	free(str);
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 11/13] perf tools: Skip dynamic fields not defined for current event
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (9 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 10/13] perf tools: Support '<event>.*' dynamic sort key Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-09 16:25   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-22 17:07 ` [PATCH 12/13] perf tools: Add 'trace_fields' dynamic sort key Namhyung Kim
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

When there're multiple events, each dynamic sort key is defined just for
one event.  In this case other events will always show "N/A" for those
fields.  But they are meaningless and consume precious screen width.

Let's skip those undefined dynamic fields.

  $ perf record -e kmem:kmalloc,kmem:kfree -a sleep 1

  $ perf report -s 'comm,kmalloc.*' --stdio
  # To display the perf.data header info, please use --header/--header-only options.
  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 20K of event 'kmem:kmalloc'
  # Event count (approx.): 20533
  #
  # Overhead  Command           call_site                 ptr  bytes_req  bytes_alloc            gfp_flags
  # ........  .......  ..................  ..................  .........  ...........  ...................
  #
      99.89%  perf       ffffffffa01d4396  0xffff8803ffb79720         96           96    GFP_NOFS|GFP_ZERO
       0.06%  sleep      ffffffff8114e1cd  0xffff8803d228a000       4096         4096           GFP_KERNEL
       0.03%  perf       ffffffff811d6ae6  0xffff8803f7678f00        240          256  GFP_KERNEL|GFP_ZERO
       0.00%  perf       ffffffff812263c1  0xffff880406172380        128          128           GFP_KERNEL
       0.00%  perf       ffffffff812264b9  0xffff8803ffac1600        504          512           GFP_KERNEL
       0.00%  perf       ffffffff81226634  0xffff880401dc5280         28           32           GFP_KERNEL
       0.00%  sleep      ffffffff81226da9  0xffff8803ffac3a00        392          512           GFP_KERNEL

  # Samples: 20K of event 'kmem:kfree'
  # Event count (approx.): 20597
  #
  # Overhead  Command
  # ........  ..............
  #
      99.63%  perf
       0.14%  sleep
       0.11%  irq/36-iwlwifi
       0.11%  kworker/u16:0
       0.01%  Xorg
       0.00%  firefox

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/browsers/hists.c |  7 ++++---
 tools/perf/ui/gtk/hists.c      |  4 ++--
 tools/perf/ui/hist.c           |  2 +-
 tools/perf/ui/stdio/hist.c     |  6 +++---
 tools/perf/util/hist.c         |  2 +-
 tools/perf/util/hist.h         | 14 ++++++++++++--
 tools/perf/util/sort.c         | 20 ++++++++++++++------
 7 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index ec331969b7d7..901d481e6cea 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1041,7 +1041,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 		hist_browser__gotorc(browser, row, 0);
 
 		perf_hpp__for_each_format(fmt) {
-			if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll)
+			if (perf_hpp__should_skip(fmt, entry->hists) ||
+			    column++ < browser->b.horiz_scroll)
 				continue;
 
 			if (current_entry && browser->b.navkeypressed) {
@@ -1144,7 +1145,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
 	}
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt)  || column++ < browser->b.horiz_scroll)
+		if (perf_hpp__should_skip(fmt, hists)  || column++ < browser->b.horiz_scroll)
 			continue;
 
 		ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
@@ -1414,7 +1415,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
 		printed += fprintf(fp, "%c ", folded_sign);
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, he->hists))
 			continue;
 
 		if (!first) {
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 467717276ab6..0f8dcfdfb10f 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -318,7 +318,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 	col_idx = 0;
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		/*
@@ -368,7 +368,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 		col_idx = 0;
 
 		perf_hpp__for_each_format(fmt) {
-			if (perf_hpp__should_skip(fmt))
+			if (perf_hpp__should_skip(fmt, h->hists))
 				continue;
 
 			if (fmt->color)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 5029ba2b55af..8263c0eb9fb5 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -619,7 +619,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
 	struct perf_hpp dummy_hpp;
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		if (first)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 7ebc661be267..387110d50b00 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -385,7 +385,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
 		return 0;
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, he->hists))
 			continue;
 
 		/*
@@ -464,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 	fprintf(fp, "# ");
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		if (!first)
@@ -490,7 +490,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 	perf_hpp__for_each_format(fmt) {
 		unsigned int i;
 
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		if (!first)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index ef1a4a5cc610..767a1a4f048e 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1092,7 +1092,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
 	int64_t cmp = 0;
 
 	perf_hpp__for_each_sort_list(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, a->hists))
 			continue;
 
 		cmp = fmt->sort(fmt, a, b);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 15b22c563d30..cb8f37349972 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -262,10 +262,20 @@ void perf_hpp__append_sort_keys(void);
 
 bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format);
 bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
+bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format);
+bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists);
 
-static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
+static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
+					 struct hists *hists)
 {
-	return format->elide;
+	if (format->elide)
+		return true;
+
+	if (perf_hpp__is_dynamic_entry(format) &&
+	    !perf_hpp__defined_dynamic_entry(format, hists))
+		return true;
+
+	return false;
 }
 
 void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 297383e0abc5..58a84a1c889a 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1697,6 +1697,15 @@ static int __sort__hde_width(struct perf_hpp_fmt *fmt,
 	return len;
 }
 
+bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists)
+{
+	struct hpp_dynamic_entry *hde;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	return hists_to_evsel(hists) == hde->evsel;
+}
+
 static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 			     struct hist_entry *he)
 {
@@ -1713,9 +1722,6 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	if (!len)
 		len = hde_width(hde);
 
-	if (hists_to_evsel(he->hists) != hde->evsel)
-		return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, "N/A");
-
 	if (hde->raw_trace)
 		goto raw_field;
 
@@ -1768,9 +1774,6 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
 
 	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
 
-	if (hists_to_evsel(a->hists) != hde->evsel)
-		return 0;
-
 	field = hde->field;
 	if (field->flags & FIELD_IS_DYNAMIC) {
 		unsigned long long dyn;
@@ -1793,6 +1796,11 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
 	return memcmp(a->raw_data + offset, b->raw_data + offset, size);
 }
 
+bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt)
+{
+	return fmt->cmp == __sort__hde_cmp;
+}
+
 static struct hpp_dynamic_entry *
 __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
 {
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 12/13] perf tools: Add 'trace_fields' dynamic sort key
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (10 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 11/13] perf tools: Skip dynamic fields not defined for current event Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
  2015-12-22 17:07 ` [PATCH 13/13] perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events Namhyung Kim
  2015-12-23  8:46 ` [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Jiri Olsa
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

The 'trace_fields' sort key is similar as 'trace' sort key, but it shows
each fields separately.  Each event will get different columns as their
fields.

  $ perf report -s trace_fields --stdio
  # To display the perf.data header info, please use --header/--header-only options.
  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 20K of event 'kmem:kmalloc'
  # Event count (approx.): 20533
  #
  # Overhead  Command           call_site                 ptr  bytes_req  bytes_alloc            gfp_flags
  # ........  .......  ..................  ..................  .........  ...........  ...................
  #
      99.89%  perf       ffffffffa01d4396  0xffff8803ffb79720         96           96    GFP_NOFS|GFP_ZERO
       0.06%  sleep      ffffffff8114e1cd  0xffff8803d228a000       4096         4096           GFP_KERNEL
       0.03%  perf       ffffffff811d6ae6  0xffff8803f7678f00        240          256  GFP_KERNEL|GFP_ZERO
       0.00%  perf       ffffffff812263c1  0xffff880406172380        128          128           GFP_KERNEL
       0.00%  perf       ffffffff812264b9  0xffff8803ffac1600        504          512           GFP_KERNEL
       0.00%  perf       ffffffff81226634  0xffff880401dc5280         28           32           GFP_KERNEL
       0.00%  sleep      ffffffff81226da9  0xffff8803ffac3a00        392          512           GFP_KERNEL

  # Samples: 20K of event 'kmem:kfree'
  # Event count (approx.): 20597
  #
  # Overhead           call_site                 ptr
  # ........  ..................  ..................
  #
      99.58%    ffffffffa01d85ad  0xffff8803ffb79720
       0.07%    ffffffff81443f5c  0xffff8803f7669400
       0.02%    ffffffff811d5753  0xffff8803f7678f00
       0.01%    ffffffff81443f5c  0xffff8803f766be00
       0.01%    ffffffff8114e359  0xffff8803d228a000
       0.01%    ffffffff81443f5c  0xffff8800d156dc00
       0.01%    ffffffff81443f5c  0xffff8803f7669400
       0.01%    ffffffff8114e359  0xffff8803d228a000
       0.01%    ffffffff8114e359  0xffff8803d228a000
       0.01%    ffffffff8114e359  0xffff8803d228a000

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 44 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 58a84a1c889a..ae995f37e135 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1931,6 +1931,35 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
 	return 0;
 }
 
+static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
+{
+	int ret;
+	struct format_field *field;
+
+	field = evsel->tp_format->format.fields;
+	while (field) {
+		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+		if (ret < 0)
+			return ret;
+
+		field = field->next;
+	}
+	return 0;
+}
+
+static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
+{
+	int ret;
+	struct perf_evsel *evsel;
+
+	evlist__for_each(evlist, evsel) {
+		ret = add_evsel_fields(evsel, raw_trace);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
 	char *str, *event_name, *field_name, *opt_name;
@@ -1960,6 +1989,11 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 		raw_trace = true;
 	}
 
+	if (!strcmp(field_name, "trace_fields")) {
+		ret = add_all_dynamic_fields(evlist ,raw_trace);
+		goto out;
+	}
+
 	evsel = find_evsel(evlist, event_name);
 	if (evsel == NULL) {
 		pr_debug("Cannot find event: %s\n", event_name);
@@ -1974,15 +2008,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	}
 
 	if (!strcmp(field_name, "*")) {
-		field = evsel->tp_format->format.fields;
-
-		while (field) {
-			ret = __dynamic_dimension__add(evsel, field, raw_trace);
-			if (ret < 0)
-				goto out;
-
-			field = field->next;
-		}
+		ret = add_evsel_fields(evsel, raw_trace);
 	} else {
 		field = pevent_find_any_field(evsel->tp_format, field_name);
 		if (field == NULL) {
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH 13/13] perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (11 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 12/13] perf tools: Add 'trace_fields' dynamic sort key Namhyung Kim
@ 2015-12-22 17:07 ` Namhyung Kim
  2016-01-09 16:26   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2015-12-23  8:46 ` [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Jiri Olsa
  13 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-22 17:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

When an evlist contains tracepoint events only, use 'trace' sort key as
default.  If --raw-trace option was given, use 'trace_fields' instead.
This will make users more convenient to see trace result.

Suggested-by: Jiri Olsa <jolsa@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 27 ++++++++++++++++++++++-----
 tools/perf/util/sort.h |  1 +
 2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index ae995f37e135..18927984fe8e 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -15,6 +15,7 @@ const char	default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cy
 const char	default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
 const char	default_top_sort_order[] = "dso,symbol";
 const char	default_diff_sort_order[] = "dso,symbol";
+const char	default_tracepoint_sort_order[] = "trace";
 const char	*sort_order;
 const char	*field_order;
 regex_t		ignore_callees_regex;
@@ -2167,7 +2168,7 @@ static int sort_dimension__add(const char *tok,
 	return -ESRCH;
 }
 
-static const char *get_default_sort_order(void)
+static const char *get_default_sort_order(struct perf_evlist *evlist)
 {
 	const char *default_sort_orders[] = {
 		default_sort_order,
@@ -2175,14 +2176,30 @@ static const char *get_default_sort_order(void)
 		default_mem_sort_order,
 		default_top_sort_order,
 		default_diff_sort_order,
+		default_tracepoint_sort_order,
 	};
+	bool use_trace = true;
+	struct perf_evsel *evsel;
 
 	BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
 
+	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+			use_trace = false;
+			break;
+		}
+	}
+
+	if (use_trace) {
+		sort__mode = SORT_MODE__TRACEPOINT;
+		if (symbol_conf.raw_trace)
+			return "trace_fields";
+	}
+
 	return default_sort_orders[sort__mode];
 }
 
-static int setup_sort_order(void)
+static int setup_sort_order(struct perf_evlist *evlist)
 {
 	char *new_sort_order;
 
@@ -2203,7 +2220,7 @@ static int setup_sort_order(void)
 	 * because it's checked over the rest of the code.
 	 */
 	if (asprintf(&new_sort_order, "%s,%s",
-		     get_default_sort_order(), sort_order + 1) < 0) {
+		     get_default_sort_order(evlist), sort_order + 1) < 0) {
 		error("Not enough memory to set up --sort");
 		return -ENOMEM;
 	}
@@ -2218,7 +2235,7 @@ static int __setup_sorting(struct perf_evlist *evlist)
 	const char *sort_keys;
 	int ret = 0;
 
-	ret = setup_sort_order();
+	ret = setup_sort_order(evlist);
 	if (ret)
 		return ret;
 
@@ -2232,7 +2249,7 @@ static int __setup_sorting(struct perf_evlist *evlist)
 			return 0;
 		}
 
-		sort_keys = get_default_sort_order();
+		sort_keys = get_default_sort_order(evlist);
 	}
 
 	str = strdup(sort_keys);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 6b7590ade229..dec536b6ab3d 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -167,6 +167,7 @@ enum sort_mode {
 	SORT_MODE__MEMORY,
 	SORT_MODE__TOP,
 	SORT_MODE__DIFF,
+	SORT_MODE__TRACEPOINT,
 };
 
 enum sort_type {
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4)
  2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
                   ` (12 preceding siblings ...)
  2015-12-22 17:07 ` [PATCH 13/13] perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events Namhyung Kim
@ 2015-12-23  8:46 ` Jiri Olsa
  2015-12-23 13:10   ` Namhyung Kim
  13 siblings, 1 reply; 57+ messages in thread
From: Jiri Olsa @ 2015-12-23  8:46 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra, LKML,
	David Ahern, Steven Rostedt, Frederic Weisbecker, Andi Kleen,
	Wang Nan

On Wed, Dec 23, 2015 at 02:06:57AM +0900, Namhyung Kim wrote:
> 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.
> 
>  * changes in v4)
>   - support '<event>.*' syntax for dynamic sort key
>   - skip unrelated dynamic fields in the output
>   - add 'trace_fields' sort key  (Jiri)
>   - reuse get_trace_output function  (Jiri)

real beauty now ;-)

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH 03/13] tools lib traceevent: Factor out and export print_event_field[s]
  2015-12-22 17:07 ` [PATCH 03/13] tools lib traceevent: Factor out and export print_event_field[s] Namhyung Kim
@ 2015-12-23  8:50   ` Wangnan (F)
  2015-12-23 13:08   ` [PATCH v4.1 " Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: Wangnan (F) @ 2015-12-23  8:50 UTC (permalink / raw)
  To: Namhyung Kim, Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen



On 2015/12/23 1:07, Namhyung Kim wrote:
> The print_event_field() and print_event_field() are to print basic

Should be

The print_event_field() and print_event_fields() are to print basic ...

lost an 's'.

> information of a given field or event without the print format.  They'll
> be used by dynamic sort keys later.
>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>

Thank you.


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v4.1 03/13] tools lib traceevent: Factor out and export print_event_field[s]
  2015-12-22 17:07 ` [PATCH 03/13] tools lib traceevent: Factor out and export print_event_field[s] Namhyung Kim
  2015-12-23  8:50   ` Wangnan (F)
@ 2015-12-23 13:08   ` Namhyung Kim
  2016-01-04 15:31     ` Steven Rostedt
  2016-01-09 16:22     ` [tip:perf/core] tools lib traceevent: Factor out and export print_event_field[s]() tip-bot for Namhyung Kim
  1 sibling, 2 replies; 57+ messages in thread
From: Namhyung Kim @ 2015-12-23 13:08 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

The print_event_field() and print_event_fields() are to print basic
information of a given field or event without the print format.  They'll
be used by dynamic sort keys later.

Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
Fix typo.  The branch was also updated.

 tools/lib/traceevent/event-parse.c | 125 ++++++++++++++++++++-----------------
 tools/lib/traceevent/event-parse.h |   4 ++
 2 files changed, 70 insertions(+), 59 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 68276f35e323..1b43f2b9aebe 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -4735,73 +4735,80 @@ static int is_printable_array(char *p, unsigned int len)
 	return 1;
 }
 
-static void print_event_fields(struct trace_seq *s, void *data,
-			       int size __maybe_unused,
-			       struct event_format *event)
+void print_event_field(struct trace_seq *s, void *data,
+		       struct format_field *field)
 {
-	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;
-			}
+	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 {
-			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 {
+			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%llx", val);
+					trace_seq_printf(s, "0x%x", (int)val);
 				else
-					trace_seq_printf(s, "%llu", val);
+					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);
 		}
+	}
+}
+
+void print_event_fields(struct trace_seq *s, void *data,
+			int size __maybe_unused, struct event_format *event)
+{
+	struct format_field *field;
+
+	field = event->format.fields;
+	while (field) {
+		trace_seq_printf(s, " %s=", field->name);
+		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..600c73277a6f 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -705,6 +705,10 @@ 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 print_event_fields(struct trace_seq *s, void *data,
+			int size __maybe_unused, struct event_format *event);
 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


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4)
  2015-12-23  8:46 ` [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Jiri Olsa
@ 2015-12-23 13:10   ` Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: Namhyung Kim @ 2015-12-23 13:10 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra, LKML,
	David Ahern, Steven Rostedt, Frederic Weisbecker, Andi Kleen,
	Wang Nan

Hi Jiri,

On Wed, Dec 23, 2015 at 09:46:23AM +0100, Jiri Olsa wrote:
> On Wed, Dec 23, 2015 at 02:06:57AM +0900, Namhyung Kim wrote:
> > 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.
> > 
> >  * changes in v4)
> >   - support '<event>.*' syntax for dynamic sort key
> >   - skip unrelated dynamic fields in the output
> >   - add 'trace_fields' sort key  (Jiri)
> >   - reuse get_trace_output function  (Jiri)
> 
> real beauty now ;-)
> 
> Acked-by: Jiri Olsa <jolsa@kernel.org>

Thanks for your review and feedback!
Namhyung

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events
  2015-12-22 17:06 ` [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events Namhyung Kim
@ 2015-12-23 21:43   ` Arnaldo Carvalho de Melo
  2015-12-24  0:45     ` Namhyung Kim
  2015-12-24  1:05     ` [PATCH v4.1 " Namhyung Kim
  0 siblings, 2 replies; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-23 21:43 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Wed, Dec 23, 2015 at 02:06:59AM +0900, Namhyung Kim escreveu:
> 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 | 4 ++++
>  tools/perf/util/sort.h | 2 ++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
> index 039bb91d0a92..c0c92a3daa69 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,

So, sample->raw_data is just a pointer to perf_event_sample->array, that
may be overwritten, no?

Looking at the other patches.

- Arnaldo

>  	};
>  
>  	return hists__findnew_entry(hists, &entry, al, sample_self);
> @@ -801,6 +803,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
>  			.sym = al->sym,
>  		},
>  		.parent = iter->parent,
> +		.raw_data = sample->raw_data,
> +		.raw_size = sample->raw_size,
>  	};
>  	int i;
>  	struct callchain_cursor cursor;
> diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
> index 86f05e7a5566..d29898708dbd 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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events
  2015-12-23 21:43   ` Arnaldo Carvalho de Melo
@ 2015-12-24  0:45     ` Namhyung Kim
  2015-12-24  1:19       ` Arnaldo Carvalho de Melo
  2015-12-24  1:05     ` [PATCH v4.1 " Namhyung Kim
  1 sibling, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-24  0:45 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Hi Arnaldo,

On Wed, Dec 23, 2015 at 06:43:35PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Wed, Dec 23, 2015 at 02:06:59AM +0900, Namhyung Kim escreveu:
> > 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 | 4 ++++
> >  tools/perf/util/sort.h | 2 ++
> >  2 files changed, 6 insertions(+)
> > 
> > diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
> > index 039bb91d0a92..c0c92a3daa69 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,
> 
> So, sample->raw_data is just a pointer to perf_event_sample->array, that
> may be overwritten, no?

I couldn't find where the array data is overwritten.  The
__perf_session__process_events() mmaps with PROT_READ basically.  But
the mmap can be munmapped on 32 bit systems.  I'll keep a copy then.

> 
> Looking at the other patches.

Thanks,
Namhyung

> 
> - Arnaldo
> 
> >  	};
> >  
> >  	return hists__findnew_entry(hists, &entry, al, sample_self);
> > @@ -801,6 +803,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
> >  			.sym = al->sym,
> >  		},
> >  		.parent = iter->parent,
> > +		.raw_data = sample->raw_data,
> > +		.raw_size = sample->raw_size,
> >  	};
> >  	int i;
> >  	struct callchain_cursor cursor;
> > diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
> > index 86f05e7a5566..d29898708dbd 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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v4.1 02/13] perf hist: Save raw_data/size for tracepoint events
  2015-12-23 21:43   ` Arnaldo Carvalho de Melo
  2015-12-24  0:45     ` Namhyung Kim
@ 2015-12-24  1:05     ` Namhyung Kim
  2015-12-24  1:39       ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-24  1:05 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

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>
---
make a copy of raw_data

 tools/perf/util/hist.c | 27 +++++++++++++++++++++++++++
 tools/perf/util/sort.h |  2 ++
 2 files changed, 29 insertions(+)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 039bb91d0a92..df5567fff986 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -369,6 +369,28 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
 		if (symbol_conf.use_callchain)
 			callchain_init(he->callchain);
 
+		if (he->raw_data) {
+			void *data = malloc(he->raw_size);
+
+			if (data == NULL) {
+				map__put(he->ms.map);
+				if (he->branch_info) {
+					map__put(he->branch_info->from.map);
+					map__put(he->branch_info->to.map);
+					free(he->branch_info);
+				}
+				if (he->mem_info) {
+					map__put(he->mem_info->iaddr.map);
+					map__put(he->mem_info->daddr.map);
+				}
+				free(he->stat_acc);
+				free(he);
+				return NULL;
+			}
+
+			memcpy(data, he->raw_data, he->raw_size);
+			he->raw_data = data;
+		}
 		INIT_LIST_HEAD(&he->pairs.node);
 		thread__get(he->thread);
 	}
@@ -487,6 +509,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);
@@ -801,6 +825,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
 			.sym = al->sym,
 		},
 		.parent = iter->parent,
+		.raw_data = sample->raw_data,
+		.raw_size = sample->raw_size,
 	};
 	int i;
 	struct callchain_cursor cursor;
@@ -974,6 +1000,7 @@ void hist_entry__delete(struct hist_entry *he)
 	if (he->srcfile && he->srcfile[0])
 		free(he->srcfile);
 	free_callchain(he->callchain);
+	free(he->raw_data);
 	free(he);
 }
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 86f05e7a5566..d29898708dbd 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


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events
  2015-12-24  0:45     ` Namhyung Kim
@ 2015-12-24  1:19       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-24  1:19 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Thu, Dec 24, 2015 at 09:45:45AM +0900, Namhyung Kim escreveu:
> Hi Arnaldo,
> 
> On Wed, Dec 23, 2015 at 06:43:35PM -0300, Arnaldo Carvalho de Melo wrote:
> > Em Wed, Dec 23, 2015 at 02:06:59AM +0900, Namhyung Kim escreveu:
> > > 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 | 4 ++++
> > >  tools/perf/util/sort.h | 2 ++
> > >  2 files changed, 6 insertions(+)
> > > 
> > > diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
> > > index 039bb91d0a92..c0c92a3daa69 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,
> > 
> > So, sample->raw_data is just a pointer to perf_event_sample->array, that
> > may be overwritten, no?
> 
> I couldn't find where the array data is overwritten.  The
> __perf_session__process_events() mmaps with PROT_READ basically.  But
> the mmap can be munmapped on 32 bit systems.  I'll keep a copy then.

perf top, aka mmap with overwrite mode? 

I think we should always think first at how to make such new features to
work on 'perf top', where there is no such thing as a "file", but a
_ring_ buffer, where we reuse that buffer when we fill it up, so we
should not keep any pointers to past events, just use what in the
currently being processed.

Haven't looked, do we need to access it after we add the hist, or just
after the perf_sample is parsed?

> > Looking at the other patches.
> 
> Thanks,
> Namhyung
> 
> > 
> > - Arnaldo
> > 
> > >  	};
> > >  
> > >  	return hists__findnew_entry(hists, &entry, al, sample_self);
> > > @@ -801,6 +803,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
> > >  			.sym = al->sym,
> > >  		},
> > >  		.parent = iter->parent,
> > > +		.raw_data = sample->raw_data,
> > > +		.raw_size = sample->raw_size,
> > >  	};
> > >  	int i;
> > >  	struct callchain_cursor cursor;
> > > diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
> > > index 86f05e7a5566..d29898708dbd 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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v4.1 02/13] perf hist: Save raw_data/size for tracepoint events
  2015-12-24  1:05     ` [PATCH v4.1 " Namhyung Kim
@ 2015-12-24  1:39       ` Arnaldo Carvalho de Melo
  2015-12-24  2:16         ` [PATCH v4.2 " Namhyung Kim
  0 siblings, 1 reply; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-24  1:39 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Thu, Dec 24, 2015 at 10:05:34AM +0900, Namhyung Kim escreveu:
> 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>
> ---
> make a copy of raw_data
> 
>  tools/perf/util/hist.c | 27 +++++++++++++++++++++++++++
>  tools/perf/util/sort.h |  2 ++
>  2 files changed, 29 insertions(+)
> 
> diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
> index 039bb91d0a92..df5567fff986 100644
> --- a/tools/perf/util/hist.c
> +++ b/tools/perf/util/hist.c
> @@ -369,6 +369,28 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
>  		if (symbol_conf.use_callchain)
>  			callchain_init(he->callchain);
>  
> +		if (he->raw_data) {
> +			void *data = malloc(he->raw_size);

if this is really needed, please use memdup(), I.e.:

			memdup(he->raw_data, he->raw_size);

> +			if (data == NULL) {
> +				map__put(he->ms.map);
> +				if (he->branch_info) {
> +					map__put(he->branch_info->from.map);
> +					map__put(he->branch_info->to.map);
> +					free(he->branch_info);
> +				}
> +				if (he->mem_info) {
> +					map__put(he->mem_info->iaddr.map);
> +					map__put(he->mem_info->daddr.map);
> +				}
> +				free(he->stat_acc);
> +				free(he);
> +				return NULL;
> +			}
> +
> +			memcpy(data, he->raw_data, he->raw_size);
> +			he->raw_data = data;
> +		}
>  		INIT_LIST_HEAD(&he->pairs.node);
>  		thread__get(he->thread);
>  	}
> @@ -487,6 +509,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);
> @@ -801,6 +825,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
>  			.sym = al->sym,
>  		},
>  		.parent = iter->parent,
> +		.raw_data = sample->raw_data,
> +		.raw_size = sample->raw_size,
>  	};
>  	int i;
>  	struct callchain_cursor cursor;
> @@ -974,6 +1000,7 @@ void hist_entry__delete(struct hist_entry *he)
>  	if (he->srcfile && he->srcfile[0])
>  		free(he->srcfile);
>  	free_callchain(he->callchain);
> +	free(he->raw_data);
>  	free(he);
>  }
>  
> diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
> index 86f05e7a5566..d29898708dbd 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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v4.2 02/13] perf hist: Save raw_data/size for tracepoint events
  2015-12-24  1:39       ` Arnaldo Carvalho de Melo
@ 2015-12-24  2:16         ` Namhyung Kim
  2016-01-09 16:22           ` [tip:perf/core] perf hist: Save raw_data/ size " tip-bot for Namhyung Kim
  0 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2015-12-24  2:16 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

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>
---
Make a copy using memdup()

 tools/perf/util/hist.c | 24 ++++++++++++++++++++++++
 tools/perf/util/sort.h |  2 ++
 2 files changed, 26 insertions(+)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 039bb91d0a92..2dcf38a78f08 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -369,6 +369,25 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
 		if (symbol_conf.use_callchain)
 			callchain_init(he->callchain);
 
+		if (he->raw_data) {
+			he->raw_data = memdup(he->raw_data, he->raw_size);
+
+			if (he->raw_data == NULL) {
+				map__put(he->ms.map);
+				if (he->branch_info) {
+					map__put(he->branch_info->from.map);
+					map__put(he->branch_info->to.map);
+					free(he->branch_info);
+				}
+				if (he->mem_info) {
+					map__put(he->mem_info->iaddr.map);
+					map__put(he->mem_info->daddr.map);
+				}
+				free(he->stat_acc);
+				free(he);
+				return NULL;
+			}
+		}
 		INIT_LIST_HEAD(&he->pairs.node);
 		thread__get(he->thread);
 	}
@@ -487,6 +506,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);
@@ -801,6 +822,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
 			.sym = al->sym,
 		},
 		.parent = iter->parent,
+		.raw_data = sample->raw_data,
+		.raw_size = sample->raw_size,
 	};
 	int i;
 	struct callchain_cursor cursor;
@@ -974,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->raw_data);
 	free(he);
 }
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 86f05e7a5566..d29898708dbd 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


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH 05/13] perf tools: Add dynamic sort key for tracepoint events
  2015-12-22 17:07 ` [PATCH 05/13] perf tools: Add dynamic sort key for tracepoint events Namhyung Kim
@ 2016-01-04 15:04   ` Arnaldo Carvalho de Melo
  2016-01-09 16:23   ` [tip:perf/core] " tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-01-04 15:04 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Wed, Dec 23, 2015 at 02:07:02AM +0900, Namhyung Kim escreveu:
> 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

I think we should add the 'perf report' command line in its output, so
that one can, from the tool output obtain the command line used to
produce it.

Anyway, good stuff, back from vacation/paternity leave, processing the
queue.

- Arnaldo

>   ...
>   # 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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH 06/13] perf tools: Try to show pretty printed output for dynamic sort keys
  2015-12-22 17:07 ` [PATCH 06/13] perf tools: Try to show pretty printed output for dynamic sort keys Namhyung Kim
@ 2016-01-04 15:16   ` Arnaldo Carvalho de Melo
  2016-01-09 16:24   ` [tip:perf/core] " tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-01-04 15:16 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Wed, Dec 23, 2015 at 02:07:03AM +0900, Namhyung Kim escreveu:
> 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@goodmis.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  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 c0c92a3daa69..ef1a4a5cc610 100644
> --- a/tools/perf/util/hist.c
> +++ b/tools/perf/util/hist.c
> @@ -978,6 +978,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);
>  }

This clashed with an updated patch earlier in this this patchkit
("[PATCH v4.1 02/13] perf hist: Save raw_data/size for tracepoint events"),
fixing it.

- Arnaldo

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v4.1 03/13] tools lib traceevent: Factor out and export print_event_field[s]
  2015-12-23 13:08   ` [PATCH v4.1 " Namhyung Kim
@ 2016-01-04 15:31     ` Steven Rostedt
  2016-01-04 18:34       ` Arnaldo Carvalho de Melo
  2016-01-09 16:22     ` [tip:perf/core] tools lib traceevent: Factor out and export print_event_field[s]() tip-bot for Namhyung Kim
  1 sibling, 1 reply; 57+ messages in thread
From: Steven Rostedt @ 2016-01-04 15:31 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra, Jiri Olsa,
	LKML, David Ahern, Frederic Weisbecker, Andi Kleen, Wang Nan

On Wed, 23 Dec 2015 22:08:41 +0900
Namhyung Kim <namhyung@kernel.org> wrote:

> The print_event_field() and print_event_fields() are to print basic
> information of a given field or event without the print format.  They'll
> be used by dynamic sort keys later.

Hi Namhyung,


> diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
> index 6fc83c7edbe9..600c73277a6f 100644
> --- a/tools/lib/traceevent/event-parse.h
> +++ b/tools/lib/traceevent/event-parse.h
> @@ -705,6 +705,10 @@ 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 print_event_fields(struct trace_seq *s, void *data,
> +			int size __maybe_unused, struct event_format *event);

I'm fine with the patch, but can you change the function names to be
less generic, as this will now be part of a library (that I hope will
become something supplied by distros soon).

Like:

pevent_print_field();
 and
pevent_print_fields();

Thanks!

-- Steve

>  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,


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v4.1 03/13] tools lib traceevent: Factor out and export print_event_field[s]
  2016-01-04 15:31     ` Steven Rostedt
@ 2016-01-04 18:34       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-01-04 18:34 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Namhyung Kim, Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML,
	David Ahern, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Mon, Jan 04, 2016 at 10:31:27AM -0500, Steven Rostedt escreveu:
> On Wed, 23 Dec 2015 22:08:41 +0900
> Namhyung Kim <namhyung@kernel.org> wrote:
> 
> > The print_event_field() and print_event_fields() are to print basic
> > information of a given field or event without the print format.  They'll
> > be used by dynamic sort keys later.
> 
> Hi Namhyung,
> 
> 
> > diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
> > index 6fc83c7edbe9..600c73277a6f 100644
> > --- a/tools/lib/traceevent/event-parse.h
> > +++ b/tools/lib/traceevent/event-parse.h
> > @@ -705,6 +705,10 @@ 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 print_event_fields(struct trace_seq *s, void *data,
> > +			int size __maybe_unused, struct event_format *event);
> 
> I'm fine with the patch, but can you change the function names to be
> less generic, as this will now be part of a library (that I hope will
> become something supplied by distros soon).
> 
> Like:
> 
> pevent_print_field();
>  and
> pevent_print_fields();

Sure, I did those changes in my tree as we discussed over IRC, as well
added your Acked-by,

thanks,

- Arnaldo
 
> Thanks!
> 
> -- Steve
> 
> >  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,

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields
@ 2016-01-05 10:58   ` Namhyung Kim
  2016-01-05 10:58     ` [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name Namhyung Kim
                       ` (5 more replies)
  0 siblings, 6 replies; 57+ messages in thread
From: Namhyung Kim @ 2016-01-05 10:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

When the 'trace_fields' sort key is used explicitly for non-tracepoint
events, it'll get segfault since it assumed evsel->tp_format was set.
Skip those events in add_all_dynamic_fields().

Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index e558e87cafaf..59c4c8586d79 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1955,6 +1955,9 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
 	struct perf_evsel *evsel;
 
 	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+			continue;
+
 		ret = add_evsel_fields(evsel, raw_trace);
 		if (ret < 0)
 			return ret;
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name
  2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
@ 2016-01-05 10:58     ` Namhyung Kim
  2016-01-05 14:20       ` Jiri Olsa
  2016-01-09 16:28       ` [tip:perf/core] " tip-bot for Namhyung Kim
  2016-01-05 10:58     ` [PATCH v2 3/5] perf tools: Add document for dynamic sort keys Namhyung Kim
                       ` (4 subsequent siblings)
  5 siblings, 2 replies; 57+ messages in thread
From: Namhyung Kim @ 2016-01-05 10:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

When a perf.data file has multiple events, it's likely to be similar
(tracepoint) events.  In that case, they might have same field name so
add all of them to sort keys instead of bailing out.

In addition, it contains a trivial whitespace fix at callsite of
add_all_dynamic_fields().

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 50 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 59c4c8586d79..a8a958827e39 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1863,10 +1863,9 @@ static int parse_field_name(char *str, char **event, char **field, char **opt)
 }
 
 /* find match evsel using a given event name.  The event name can be:
- *   1. NULL - only valid for single event session
- *   2. '%' + event index (e.g. '%1' for first event)
- *   3. full event name (e.g. sched:sched_switch)
- *   4. partial event name (should not contain ':')
+ *   1. '%' + event index (e.g. '%1' for first event)
+ *   2. full event name (e.g. sched:sched_switch)
+ *   3. partial event name (should not contain ':')
  */
 static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
 {
@@ -1875,16 +1874,6 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 	bool full_name;
 
 	/* case 1 */
-	if (event_name == NULL) {
-		if (evlist->nr_entries != 1) {
-			pr_debug("event name should be given\n");
-			return NULL;
-		}
-
-		return perf_evlist__first(evlist);
-	}
-
-	/* case 2 */
 	if (event_name[0] == '%') {
 		int nr = strtol(event_name+1, NULL, 0);
 
@@ -1900,10 +1889,10 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 
 	full_name = !!strchr(event_name, ':');
 	evlist__for_each(evlist, pos) {
-		/* case 3 */
+		/* case 2 */
 		if (full_name && !strcmp(pos->name, event_name))
 			return pos;
-		/* case 4 */
+		/* case 3 */
 		if (!full_name && strstr(pos->name, event_name)) {
 			if (evsel) {
 				pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
@@ -1965,6 +1954,28 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
 	return 0;
 }
 
+static int add_all_matching_fields(struct perf_evlist *evlist,
+				   char *field_name, bool raw_trace)
+{
+	int ret = -ESRCH;
+	struct perf_evsel *evsel;
+	struct format_field *field;
+
+	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+			continue;
+
+		field = pevent_find_any_field(evsel->tp_format, field_name);
+		if (field == NULL)
+			continue;
+
+		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+		if (ret < 0)
+			break;
+	}
+	return ret;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
 	char *str, *event_name, *field_name, *opt_name;
@@ -1995,7 +2006,12 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	}
 
 	if (!strcmp(field_name, "trace_fields")) {
-		ret = add_all_dynamic_fields(evlist ,raw_trace);
+		ret = add_all_dynamic_fields(evlist, raw_trace);
+		goto out;
+	}
+
+	if (event_name == NULL) {
+		ret = add_all_matching_fields(evlist, field_name, raw_trace);
 		goto out;
 	}
 
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v2 3/5] perf tools: Add document for dynamic sort keys
  2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
  2016-01-05 10:58     ` [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name Namhyung Kim
@ 2016-01-05 10:58     ` Namhyung Kim
  2016-01-09 16:28       ` [tip:perf/core] perf report: Add documentation " tip-bot for Namhyung Kim
  2016-01-05 10:58     ` [PATCH v2 4/5] perf tools: Support dynamic sort keys for -F/--fields Namhyung Kim
                       ` (3 subsequent siblings)
  5 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2016-01-05 10:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Documentation/perf-report.txt | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index ae7cd91727f6..8a301f6afb37 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -117,6 +117,30 @@ OPTIONS
 	And default sort keys are changed to comm, dso_from, symbol_from, dso_to
 	and symbol_to, see '--branch-stack'.
 
+	If the data file has tracepoint event(s), following (dynamic) sort keys
+	are also available:
+	trace, trace_fields, [<event>.]<field>[/raw]
+
+	- trace: pretty printed trace output in a single column
+	- trace_fields: fields in tracepoints in separate columns
+	- <field name>: optional event and field name for a specific field
+
+	The last form consists of event and field names.  If event name is
+	omitted, it searches all events for matching field name.  The matched
+	field will be shown only for the event has the field.  The event name
+	supports substring match so user doesn't need to specify full subsystem
+	and event name everytime.  For example, 'sched:sched_switch' event can
+	be shortened to 'switch' as long as it's not ambiguous.  Also event can
+	be specified by its index (starting from 1) preceded by the '%'.
+	So '%1' is the first event, '%2' is the second, and so on.
+
+	The field name can have '/raw' suffix which disables pretty printing
+	and shows raw field value like hex numbers.  The --raw-trace option
+	has the same effect for all dynamic sort keys.
+
+	The default sort keys are changed to 'trace' if all events in the data
+	file are tracepoint.
+
 -F::
 --fields=::
 	Specify output field - multiple keys can be specified in CSV format.
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v2 4/5] perf tools: Support dynamic sort keys for -F/--fields
  2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
  2016-01-05 10:58     ` [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name Namhyung Kim
  2016-01-05 10:58     ` [PATCH v2 3/5] perf tools: Add document for dynamic sort keys Namhyung Kim
@ 2016-01-05 10:58     ` Namhyung Kim
  2016-01-05 22:16       ` Arnaldo Carvalho de Melo
  2016-01-05 10:58     ` [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields Namhyung Kim
                       ` (2 subsequent siblings)
  5 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2016-01-05 10:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Now dynamic sort keys are supported for tracepoint events, add it to
output fields too.

Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/sort.c | 51 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 33 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index a8a958827e39..07312ceed6eb 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1908,7 +1908,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 
 static int __dynamic_dimension__add(struct perf_evsel *evsel,
 				    struct format_field *field,
-				    bool raw_trace)
+				    bool raw_trace, bool is_sort_key)
 {
 	struct hpp_dynamic_entry *hde;
 
@@ -1918,18 +1918,24 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
 
 	hde->raw_trace = raw_trace;
 
-	perf_hpp__register_sort_field(&hde->hpp);
+	if (is_sort_key)
+		perf_hpp__register_sort_field(&hde->hpp);
+	else
+		perf_hpp__column_register(&hde->hpp);
+
 	return 0;
 }
 
-static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
+static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace,
+			    bool is_sort_key)
 {
 	int ret;
 	struct format_field *field;
 
 	field = evsel->tp_format->format.fields;
 	while (field) {
-		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+		ret = __dynamic_dimension__add(evsel, field, raw_trace,
+					       is_sort_key);
 		if (ret < 0)
 			return ret;
 
@@ -1938,7 +1944,8 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
 	return 0;
 }
 
-static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
+static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
+				  bool is_sort_key)
 {
 	int ret;
 	struct perf_evsel *evsel;
@@ -1947,7 +1954,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
 		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
 			continue;
 
-		ret = add_evsel_fields(evsel, raw_trace);
+		ret = add_evsel_fields(evsel, raw_trace, is_sort_key);
 		if (ret < 0)
 			return ret;
 	}
@@ -1955,7 +1962,8 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
 }
 
 static int add_all_matching_fields(struct perf_evlist *evlist,
-				   char *field_name, bool raw_trace)
+				   char *field_name, bool raw_trace,
+				   bool is_sort_key)
 {
 	int ret = -ESRCH;
 	struct perf_evsel *evsel;
@@ -1969,14 +1977,16 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
 		if (field == NULL)
 			continue;
 
-		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+		ret = __dynamic_dimension__add(evsel, field, raw_trace,
+					       is_sort_key);
 		if (ret < 0)
 			break;
 	}
 	return ret;
 }
 
-static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
+static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
+			     bool is_sort_key)
 {
 	char *str, *event_name, *field_name, *opt_name;
 	struct perf_evsel *evsel;
@@ -2006,12 +2016,13 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	}
 
 	if (!strcmp(field_name, "trace_fields")) {
-		ret = add_all_dynamic_fields(evlist, raw_trace);
+		ret = add_all_dynamic_fields(evlist, raw_trace, is_sort_key);
 		goto out;
 	}
 
 	if (event_name == NULL) {
-		ret = add_all_matching_fields(evlist, field_name, raw_trace);
+		ret = add_all_matching_fields(evlist, field_name, raw_trace,
+					      is_sort_key);
 		goto out;
 	}
 
@@ -2029,7 +2040,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	}
 
 	if (!strcmp(field_name, "*")) {
-		ret = add_evsel_fields(evsel, raw_trace);
+		ret = add_evsel_fields(evsel, raw_trace, is_sort_key);
 	} else {
 		field = pevent_find_any_field(evsel->tp_format, field_name);
 		if (field == NULL) {
@@ -2038,7 +2049,8 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 			return -ENOENT;
 		}
 
-		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+		ret = __dynamic_dimension__add(evsel, field, raw_trace,
+					       is_sort_key);
 	}
 
 out:
@@ -2182,7 +2194,7 @@ static int sort_dimension__add(const char *tok,
 		return 0;
 	}
 
-	if (!add_dynamic_entry(evlist, tok))
+	if (!add_dynamic_entry(evlist, tok, true))
 		return 0;
 
 	return -ESRCH;
@@ -2387,7 +2399,7 @@ void sort__setup_elide(FILE *output)
 	}
 }
 
-static int output_field_add(char *tok)
+static int output_field_add(struct perf_evlist *evlist, char *tok)
 {
 	unsigned int i;
 
@@ -2427,6 +2439,9 @@ static int output_field_add(char *tok)
 		return __sort_dimension__add_output(sd);
 	}
 
+	if (!add_dynamic_entry(evlist, tok, false))
+		return 0;
+
 	return -ESRCH;
 }
 
@@ -2452,7 +2467,7 @@ bool is_strict_order(const char *order)
 	return order && (*order != '+');
 }
 
-static int __setup_output_field(void)
+static int __setup_output_field(struct perf_evlist *evlist)
 {
 	char *tmp, *tok, *str, *strp;
 	int ret = -EINVAL;
@@ -2476,7 +2491,7 @@ static int __setup_output_field(void)
 
 	for (tok = strtok_r(strp, ", ", &tmp);
 			tok; tok = strtok_r(NULL, ", ", &tmp)) {
-		ret = output_field_add(tok);
+		ret = output_field_add(evlist, tok);
 		if (ret == -EINVAL) {
 			error("Invalid --fields key: `%s'", tok);
 			break;
@@ -2513,7 +2528,7 @@ int setup_sorting(struct perf_evlist *evlist)
 	if (sort__mode != SORT_MODE__DIFF)
 		perf_hpp__init();
 
-	err = __setup_output_field();
+	err = __setup_output_field(evlist);
 	if (err < 0)
 		return err;
 
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields
  2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
                       ` (2 preceding siblings ...)
  2016-01-05 10:58     ` [PATCH v2 4/5] perf tools: Support dynamic sort keys for -F/--fields Namhyung Kim
@ 2016-01-05 10:58     ` Namhyung Kim
  2016-01-05 22:23       ` Arnaldo Carvalho de Melo
  2016-01-05 21:50     ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Arnaldo Carvalho de Melo
  2016-01-09 16:26     ` [tip:perf/core] perf tools: Add 'trace_fields' dynamic sort key tip-bot for Namhyung Kim
  5 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2016-01-05 10:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

To use dynamic sort keys, it might be good to add an option to see the
list of field names.

  $ perf evlist -T -i perf.data.sched
  sched:sched_switch: trace_fields=prev_comm,prev_pid,prev_prio,prev_state,next_comm,next_pid,next_prio
  sched:sched_stat_wait: trace_fields=comm,pid,delay
  sched:sched_stat_sleep: trace_fields=comm,pid,delay
  sched:sched_stat_iowait: trace_fields=comm,pid,delay
  sched:sched_stat_runtime: trace_fields=comm,pid,runtime,vruntime
  sched:sched_process_fork: trace_fields=parent_comm,parent_pid,child_comm,child_pid
  sched:sched_wakeup: trace_fields=comm,pid,prio,success,target_cpu
  sched:sched_wakeup_new: trace_fields=comm,pid,prio,success,target_cpu
  sched:sched_migrate_task: trace_fields=comm,pid,prio,orig_cpu,dest_cpu

Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Documentation/perf-evlist.txt |  4 ++++
 tools/perf/builtin-evlist.c              |  1 +
 tools/perf/util/evsel.c                  | 23 +++++++++++++++++++++++
 tools/perf/util/evsel.h                  |  1 +
 4 files changed, 29 insertions(+)

diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
index 1ceb3700ffbb..b0d99c276cf5 100644
--- a/tools/perf/Documentation/perf-evlist.txt
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -32,6 +32,10 @@ OPTIONS
 --group::
 	Show event group information.
 
+-T::
+--trace::
+	Show tracepoint field names.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-list[1],
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 08a7d36a2cf8..2820bb2d8cf8 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -49,6 +49,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_BOOLEAN('g', "group", &details.event_group,
 		    "Show event group information"),
 	OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
+	OPT_BOOLEAN('T', "trace", &details.trace, "Show tracepoint fields"),
 	OPT_END()
 	};
 	const char * const evlist_usage[] = {
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 544e4400de13..174d0029e038 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2298,6 +2298,29 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
 		printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
 					 term, (u64)evsel->attr.sample_freq);
 	}
+
+	if (details->trace) {
+		struct format_field *field;
+
+		if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+			printed += comma_fprintf(fp, &first, " (not a tracepoint)");
+			goto out;
+		}
+
+		field = evsel->tp_format->format.fields;
+		if (field == NULL) {
+			printed += comma_fprintf(fp, &first, " (no trace field)");
+			goto out;
+		}
+
+		printed += comma_fprintf(fp, &first, " trace_fields=%s", field->name);
+
+		field = field->next;
+		while (field) {
+			printed += comma_fprintf(fp, &first, "%s", field->name);
+			field = field->next;
+		}
+	}
 out:
 	fputc('\n', fp);
 	return ++printed;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 5ded1fc0341e..9b36dd584d4a 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -369,6 +369,7 @@ struct perf_attr_details {
 	bool verbose;
 	bool event_group;
 	bool force;
+	bool trace;
 };
 
 int perf_evsel__fprintf(struct perf_evsel *evsel,
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name
  2016-01-05 10:58     ` [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name Namhyung Kim
@ 2016-01-05 14:20       ` Jiri Olsa
  2016-01-09 16:28       ` [tip:perf/core] " tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: Jiri Olsa @ 2016-01-05 14:20 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra, Jiri Olsa,
	LKML, David Ahern, Steven Rostedt, Frederic Weisbecker,
	Andi Kleen, Wang Nan

On Tue, Jan 05, 2016 at 07:58:35PM +0900, Namhyung Kim wrote:
> When a perf.data file has multiple events, it's likely to be similar
> (tracepoint) events.  In that case, they might have same field name so
> add all of them to sort keys instead of bailing out.
> 
> In addition, it contains a trivial whitespace fix at callsite of
> add_all_dynamic_fields().
> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields
  2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
                       ` (3 preceding siblings ...)
  2016-01-05 10:58     ` [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields Namhyung Kim
@ 2016-01-05 21:50     ` Arnaldo Carvalho de Melo
  2016-01-05 23:39       ` Namhyung Kim
  2016-01-09 16:26     ` [tip:perf/core] perf tools: Add 'trace_fields' dynamic sort key tip-bot for Namhyung Kim
  5 siblings, 1 reply; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-01-05 21:50 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Tue, Jan 05, 2016 at 07:58:34PM +0900, Namhyung Kim escreveu:
> When the 'trace_fields' sort key is used explicitly for non-tracepoint
> events, it'll get segfault since it assumed evsel->tp_format was set.
> Skip those events in add_all_dynamic_fields().
> 
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>

Merged with the patch introducing this problem, that I hadn't sent to
Ingo,

- Arnaldo

> ---
>  tools/perf/util/sort.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> index e558e87cafaf..59c4c8586d79 100644
> --- a/tools/perf/util/sort.c
> +++ b/tools/perf/util/sort.c
> @@ -1955,6 +1955,9 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
>  	struct perf_evsel *evsel;
>  
>  	evlist__for_each(evlist, evsel) {
> +		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
> +			continue;
> +
>  		ret = add_evsel_fields(evsel, raw_trace);
>  		if (ret < 0)
>  			return ret;
> -- 
> 2.6.4

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 4/5] perf tools: Support dynamic sort keys for -F/--fields
  2016-01-05 10:58     ` [PATCH v2 4/5] perf tools: Support dynamic sort keys for -F/--fields Namhyung Kim
@ 2016-01-05 22:16       ` Arnaldo Carvalho de Melo
  2016-01-05 23:57         ` Namhyung Kim
  0 siblings, 1 reply; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-01-05 22:16 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Tue, Jan 05, 2016 at 07:58:37PM +0900, Namhyung Kim escreveu:
> Now dynamic sort keys are supported for tracepoint events, add it to
> output fields too.

Must be the end of the day, but:

  [root@zoo ~]# perf report -h -F -s

   Usage: perf report [<options>]

    -F, --fields <key[,keys...]>
                          output field(s): overhead, period, sample plus all of sort keys
    -s, --sort <key[,key2...]>
                          sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ... Please refer the man page for the complete list.

  [root@zoo ~]#

So, with this file, for instance:

  [root@zoo ~]# perf evlist -v
  sched:sched_switch: type: 2, size: 112, config: 0x10b, { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|PERIOD|RAW, disabled: 1, inherit: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
  [root@zoo ~]#

I thought that these would be equivalent:

  [root@zoo ~]# perf report -s prev_comm,next_comm | head -20 | tail -15
  # Samples: 27K of event 'sched:sched_switch'
  # Event count (approx.): 27997
  #
  # Overhead         prev_comm         next_comm
  # ........  ................  ................
  #
    10.97%           firefox         swapper/0
    10.97%         swapper/0           firefox
    10.23%          Xorg.bin         swapper/2
    10.23%         swapper/2          Xorg.bin
    10.20%           firefox         swapper/3
    10.20%         swapper/3           firefox
     5.75%         swapper/1          Xorg.bin
     5.74%          Xorg.bin         swapper/1
     3.93%          Xorg.bin         swapper/0
  [root@zoo ~]#

  [root@zoo ~]# perf report -s prev_comm,next_comm -F overhead | head -20 | tail -15
  # Samples: 27K of event 'sched:sched_switch'
  # Event count (approx.): 27997
  #
  # Overhead         prev_comm         next_comm
  # ........  ................  ................
  #
     0.05%             xchat         swapper/1
     0.11%             xchat         swapper/0
     0.01%        watchdog/3         swapper/3
     0.01%        watchdog/2         swapper/2
     0.01%        watchdog/1         swapper/1
     0.01%        watchdog/0         swapper/0
     0.01%             virsh         swapper/2
     0.08%               tor         swapper/3
     0.02%               tor         swapper/1
  [root@zoo ~]#

What am I doing wrong or didn't understood about those options?

- Arnaldo
 
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/util/sort.c | 51 ++++++++++++++++++++++++++++++++------------------
>  1 file changed, 33 insertions(+), 18 deletions(-)
> 
> diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> index a8a958827e39..07312ceed6eb 100644
> --- a/tools/perf/util/sort.c
> +++ b/tools/perf/util/sort.c
> @@ -1908,7 +1908,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
>  
>  static int __dynamic_dimension__add(struct perf_evsel *evsel,
>  				    struct format_field *field,
> -				    bool raw_trace)
> +				    bool raw_trace, bool is_sort_key)
>  {
>  	struct hpp_dynamic_entry *hde;
>  
> @@ -1918,18 +1918,24 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
>  
>  	hde->raw_trace = raw_trace;
>  
> -	perf_hpp__register_sort_field(&hde->hpp);
> +	if (is_sort_key)
> +		perf_hpp__register_sort_field(&hde->hpp);
> +	else
> +		perf_hpp__column_register(&hde->hpp);
> +
>  	return 0;
>  }
>  
> -static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
> +static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace,
> +			    bool is_sort_key)
>  {
>  	int ret;
>  	struct format_field *field;
>  
>  	field = evsel->tp_format->format.fields;
>  	while (field) {
> -		ret = __dynamic_dimension__add(evsel, field, raw_trace);
> +		ret = __dynamic_dimension__add(evsel, field, raw_trace,
> +					       is_sort_key);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -1938,7 +1944,8 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
>  	return 0;
>  }
>  
> -static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
> +static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
> +				  bool is_sort_key)
>  {
>  	int ret;
>  	struct perf_evsel *evsel;
> @@ -1947,7 +1954,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
>  		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
>  			continue;
>  
> -		ret = add_evsel_fields(evsel, raw_trace);
> +		ret = add_evsel_fields(evsel, raw_trace, is_sort_key);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -1955,7 +1962,8 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
>  }
>  
>  static int add_all_matching_fields(struct perf_evlist *evlist,
> -				   char *field_name, bool raw_trace)
> +				   char *field_name, bool raw_trace,
> +				   bool is_sort_key)
>  {
>  	int ret = -ESRCH;
>  	struct perf_evsel *evsel;
> @@ -1969,14 +1977,16 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
>  		if (field == NULL)
>  			continue;
>  
> -		ret = __dynamic_dimension__add(evsel, field, raw_trace);
> +		ret = __dynamic_dimension__add(evsel, field, raw_trace,
> +					       is_sort_key);
>  		if (ret < 0)
>  			break;
>  	}
>  	return ret;
>  }
>  
> -static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
> +static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
> +			     bool is_sort_key)
>  {
>  	char *str, *event_name, *field_name, *opt_name;
>  	struct perf_evsel *evsel;
> @@ -2006,12 +2016,13 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
>  	}
>  
>  	if (!strcmp(field_name, "trace_fields")) {
> -		ret = add_all_dynamic_fields(evlist, raw_trace);
> +		ret = add_all_dynamic_fields(evlist, raw_trace, is_sort_key);
>  		goto out;
>  	}
>  
>  	if (event_name == NULL) {
> -		ret = add_all_matching_fields(evlist, field_name, raw_trace);
> +		ret = add_all_matching_fields(evlist, field_name, raw_trace,
> +					      is_sort_key);
>  		goto out;
>  	}
>  
> @@ -2029,7 +2040,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
>  	}
>  
>  	if (!strcmp(field_name, "*")) {
> -		ret = add_evsel_fields(evsel, raw_trace);
> +		ret = add_evsel_fields(evsel, raw_trace, is_sort_key);
>  	} else {
>  		field = pevent_find_any_field(evsel->tp_format, field_name);
>  		if (field == NULL) {
> @@ -2038,7 +2049,8 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
>  			return -ENOENT;
>  		}
>  
> -		ret = __dynamic_dimension__add(evsel, field, raw_trace);
> +		ret = __dynamic_dimension__add(evsel, field, raw_trace,
> +					       is_sort_key);
>  	}
>  
>  out:
> @@ -2182,7 +2194,7 @@ static int sort_dimension__add(const char *tok,
>  		return 0;
>  	}
>  
> -	if (!add_dynamic_entry(evlist, tok))
> +	if (!add_dynamic_entry(evlist, tok, true))
>  		return 0;
>  
>  	return -ESRCH;
> @@ -2387,7 +2399,7 @@ void sort__setup_elide(FILE *output)
>  	}
>  }
>  
> -static int output_field_add(char *tok)
> +static int output_field_add(struct perf_evlist *evlist, char *tok)
>  {
>  	unsigned int i;
>  
> @@ -2427,6 +2439,9 @@ static int output_field_add(char *tok)
>  		return __sort_dimension__add_output(sd);
>  	}
>  
> +	if (!add_dynamic_entry(evlist, tok, false))
> +		return 0;
> +
>  	return -ESRCH;
>  }
>  
> @@ -2452,7 +2467,7 @@ bool is_strict_order(const char *order)
>  	return order && (*order != '+');
>  }
>  
> -static int __setup_output_field(void)
> +static int __setup_output_field(struct perf_evlist *evlist)
>  {
>  	char *tmp, *tok, *str, *strp;
>  	int ret = -EINVAL;
> @@ -2476,7 +2491,7 @@ static int __setup_output_field(void)
>  
>  	for (tok = strtok_r(strp, ", ", &tmp);
>  			tok; tok = strtok_r(NULL, ", ", &tmp)) {
> -		ret = output_field_add(tok);
> +		ret = output_field_add(evlist, tok);
>  		if (ret == -EINVAL) {
>  			error("Invalid --fields key: `%s'", tok);
>  			break;
> @@ -2513,7 +2528,7 @@ int setup_sorting(struct perf_evlist *evlist)
>  	if (sort__mode != SORT_MODE__DIFF)
>  		perf_hpp__init();
>  
> -	err = __setup_output_field();
> +	err = __setup_output_field(evlist);
>  	if (err < 0)
>  		return err;
>  
> -- 
> 2.6.4

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields
  2016-01-05 10:58     ` [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields Namhyung Kim
@ 2016-01-05 22:23       ` Arnaldo Carvalho de Melo
  2016-01-06  0:00         ` Namhyung Kim
  0 siblings, 1 reply; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-01-05 22:23 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Tue, Jan 05, 2016 at 07:58:38PM +0900, Namhyung Kim escreveu:
> To use dynamic sort keys, it might be good to add an option to see the
> list of field names.
> 
>   $ perf evlist -T -i perf.data.sched

Humm, I think here we should just use --trace_fields, like what appears
in the output for each line below, and also as is the case for the '-s
trace_fields' case, ok?

With:

  $ . ~/git/linux/tools/perf/perf-completion.sh 
  [acme@zoo linux]$ perf evlist --
  --force    --freq     --group    --input    --verbose  
  [acme@zoo linux]$ perf evlist --

We can autocomplete it from --t<TAB> anyway :)

Unsure about '-T', perhaps this is so specialized, that can remain with
just the long option?

Perhaps we can add a tip, when we run:

  perf evlist

And there are tracepoint events, something like:

  perf evlist -v
  sched:sched_switch ...
  # Tip use 'perf evlist --trace_fields' to show fields for events such
  # as "sched:sched_switch"

- Arnaldo

>   sched:sched_switch: trace_fields=prev_comm,prev_pid,prev_prio,prev_state,next_comm,next_pid,next_prio
>   sched:sched_stat_wait: trace_fields=comm,pid,delay
>   sched:sched_stat_sleep: trace_fields=comm,pid,delay
>   sched:sched_stat_iowait: trace_fields=comm,pid,delay
>   sched:sched_stat_runtime: trace_fields=comm,pid,runtime,vruntime
>   sched:sched_process_fork: trace_fields=parent_comm,parent_pid,child_comm,child_pid
>   sched:sched_wakeup: trace_fields=comm,pid,prio,success,target_cpu
>   sched:sched_wakeup_new: trace_fields=comm,pid,prio,success,target_cpu
>   sched:sched_migrate_task: trace_fields=comm,pid,prio,orig_cpu,dest_cpu
> 
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/Documentation/perf-evlist.txt |  4 ++++
>  tools/perf/builtin-evlist.c              |  1 +
>  tools/perf/util/evsel.c                  | 23 +++++++++++++++++++++++
>  tools/perf/util/evsel.h                  |  1 +
>  4 files changed, 29 insertions(+)
> 
> diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
> index 1ceb3700ffbb..b0d99c276cf5 100644
> --- a/tools/perf/Documentation/perf-evlist.txt
> +++ b/tools/perf/Documentation/perf-evlist.txt
> @@ -32,6 +32,10 @@ OPTIONS
>  --group::
>  	Show event group information.
>  
> +-T::
> +--trace::
> +	Show tracepoint field names.
> +
>  SEE ALSO
>  --------
>  linkperf:perf-record[1], linkperf:perf-list[1],
> diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
> index 08a7d36a2cf8..2820bb2d8cf8 100644
> --- a/tools/perf/builtin-evlist.c
> +++ b/tools/perf/builtin-evlist.c
> @@ -49,6 +49,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
>  	OPT_BOOLEAN('g', "group", &details.event_group,
>  		    "Show event group information"),
>  	OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
> +	OPT_BOOLEAN('T', "trace", &details.trace, "Show tracepoint fields"),
>  	OPT_END()
>  	};
>  	const char * const evlist_usage[] = {
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 544e4400de13..174d0029e038 100644
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
> @@ -2298,6 +2298,29 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
>  		printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
>  					 term, (u64)evsel->attr.sample_freq);
>  	}
> +
> +	if (details->trace) {
> +		struct format_field *field;
> +
> +		if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
> +			printed += comma_fprintf(fp, &first, " (not a tracepoint)");
> +			goto out;
> +		}
> +
> +		field = evsel->tp_format->format.fields;
> +		if (field == NULL) {
> +			printed += comma_fprintf(fp, &first, " (no trace field)");
> +			goto out;
> +		}
> +
> +		printed += comma_fprintf(fp, &first, " trace_fields=%s", field->name);
> +
> +		field = field->next;
> +		while (field) {
> +			printed += comma_fprintf(fp, &first, "%s", field->name);
> +			field = field->next;
> +		}
> +	}
>  out:
>  	fputc('\n', fp);
>  	return ++printed;
> diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> index 5ded1fc0341e..9b36dd584d4a 100644
> --- a/tools/perf/util/evsel.h
> +++ b/tools/perf/util/evsel.h
> @@ -369,6 +369,7 @@ struct perf_attr_details {
>  	bool verbose;
>  	bool event_group;
>  	bool force;
> +	bool trace;
>  };
>  
>  int perf_evsel__fprintf(struct perf_evsel *evsel,
> -- 
> 2.6.4

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields
  2016-01-05 21:50     ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Arnaldo Carvalho de Melo
@ 2016-01-05 23:39       ` Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: Namhyung Kim @ 2016-01-05 23:39 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

On Tue, Jan 05, 2016 at 06:50:02PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 05, 2016 at 07:58:34PM +0900, Namhyung Kim escreveu:
> > When the 'trace_fields' sort key is used explicitly for non-tracepoint
> > events, it'll get segfault since it assumed evsel->tp_format was set.
> > Skip those events in add_all_dynamic_fields().
> > 
> > Acked-by: Jiri Olsa <jolsa@kernel.org>
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> 
> Merged with the patch introducing this problem, that I hadn't sent to
> Ingo,

Thanks for doing that!
Namhyung


> 
> > ---
> >  tools/perf/util/sort.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> > index e558e87cafaf..59c4c8586d79 100644
> > --- a/tools/perf/util/sort.c
> > +++ b/tools/perf/util/sort.c
> > @@ -1955,6 +1955,9 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
> >  	struct perf_evsel *evsel;
> >  
> >  	evlist__for_each(evlist, evsel) {
> > +		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
> > +			continue;
> > +
> >  		ret = add_evsel_fields(evsel, raw_trace);
> >  		if (ret < 0)
> >  			return ret;
> > -- 
> > 2.6.4

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 4/5] perf tools: Support dynamic sort keys for -F/--fields
  2016-01-05 22:16       ` Arnaldo Carvalho de Melo
@ 2016-01-05 23:57         ` Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: Namhyung Kim @ 2016-01-05 23:57 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

On Tue, Jan 05, 2016 at 07:16:43PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 05, 2016 at 07:58:37PM +0900, Namhyung Kim escreveu:
> > Now dynamic sort keys are supported for tracepoint events, add it to
> > output fields too.
> 
> Must be the end of the day, but:
> 
>   [root@zoo ~]# perf report -h -F -s
> 
>    Usage: perf report [<options>]
> 
>     -F, --fields <key[,keys...]>
>                           output field(s): overhead, period, sample plus all of sort keys
>     -s, --sort <key[,key2...]>
>                           sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ... Please refer the man page for the complete list.
> 
>   [root@zoo ~]#
> 
> So, with this file, for instance:
> 
>   [root@zoo ~]# perf evlist -v
>   sched:sched_switch: type: 2, size: 112, config: 0x10b, { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|PERIOD|RAW, disabled: 1, inherit: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
>   [root@zoo ~]#
> 
> I thought that these would be equivalent:
> 
>   [root@zoo ~]# perf report -s prev_comm,next_comm | head -20 | tail -15
>   # Samples: 27K of event 'sched:sched_switch'
>   # Event count (approx.): 27997
>   #
>   # Overhead         prev_comm         next_comm
>   # ........  ................  ................
>   #
>     10.97%           firefox         swapper/0
>     10.97%         swapper/0           firefox
>     10.23%          Xorg.bin         swapper/2
>     10.23%         swapper/2          Xorg.bin
>     10.20%           firefox         swapper/3
>     10.20%         swapper/3           firefox
>      5.75%         swapper/1          Xorg.bin
>      5.74%          Xorg.bin         swapper/1
>      3.93%          Xorg.bin         swapper/0
>   [root@zoo ~]#
> 
>   [root@zoo ~]# perf report -s prev_comm,next_comm -F overhead | head -20 | tail -15
>   # Samples: 27K of event 'sched:sched_switch'
>   # Event count (approx.): 27997
>   #
>   # Overhead         prev_comm         next_comm
>   # ........  ................  ................
>   #
>      0.05%             xchat         swapper/1
>      0.11%             xchat         swapper/0
>      0.01%        watchdog/3         swapper/3
>      0.01%        watchdog/2         swapper/2
>      0.01%        watchdog/1         swapper/1
>      0.01%        watchdog/0         swapper/0
>      0.01%             virsh         swapper/2
>      0.08%               tor         swapper/3
>      0.02%               tor         swapper/1
>   [root@zoo ~]#
> 
> What am I doing wrong or didn't understood about those options?

Yes, this is subtle.  The --sort option didn't really sort data but
just aggregate it.  By adding -F/--fields option, the aggregation and
sorting can be separated.  Behavior of the -s/--sort option is kept if
it's not used with -F/--fields (for backward compatibility).  However
if it used with -F/--fields, it has the original meaning of sorting.

IOW, 'perf report -s prev_comm,next_comm' is actually same as
     'perf report -F overhead,prev_comm,next_comm -s overhead'.

You run 'perf report -F overhead -s prev_com,next_comm', so it sorts
the data using alphabetical order of prev_comm and then next_comm (But
it should be reversed, will fix).

Please see the description of the original patch posting.

  https://lkml.org/lkml/2014/5/19/84


Thanks,
Namhyung


> 
> - Arnaldo
>  
> > Acked-by: Jiri Olsa <jolsa@kernel.org>
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > ---
> >  tools/perf/util/sort.c | 51 ++++++++++++++++++++++++++++++++------------------
> >  1 file changed, 33 insertions(+), 18 deletions(-)
> > 
> > diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> > index a8a958827e39..07312ceed6eb 100644
> > --- a/tools/perf/util/sort.c
> > +++ b/tools/perf/util/sort.c
> > @@ -1908,7 +1908,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
> >  
> >  static int __dynamic_dimension__add(struct perf_evsel *evsel,
> >  				    struct format_field *field,
> > -				    bool raw_trace)
> > +				    bool raw_trace, bool is_sort_key)
> >  {
> >  	struct hpp_dynamic_entry *hde;
> >  
> > @@ -1918,18 +1918,24 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
> >  
> >  	hde->raw_trace = raw_trace;
> >  
> > -	perf_hpp__register_sort_field(&hde->hpp);
> > +	if (is_sort_key)
> > +		perf_hpp__register_sort_field(&hde->hpp);
> > +	else
> > +		perf_hpp__column_register(&hde->hpp);
> > +
> >  	return 0;
> >  }
> >  
> > -static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
> > +static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace,
> > +			    bool is_sort_key)
> >  {
> >  	int ret;
> >  	struct format_field *field;
> >  
> >  	field = evsel->tp_format->format.fields;
> >  	while (field) {
> > -		ret = __dynamic_dimension__add(evsel, field, raw_trace);
> > +		ret = __dynamic_dimension__add(evsel, field, raw_trace,
> > +					       is_sort_key);
> >  		if (ret < 0)
> >  			return ret;
> >  
> > @@ -1938,7 +1944,8 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
> >  	return 0;
> >  }
> >  
> > -static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
> > +static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
> > +				  bool is_sort_key)
> >  {
> >  	int ret;
> >  	struct perf_evsel *evsel;
> > @@ -1947,7 +1954,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
> >  		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
> >  			continue;
> >  
> > -		ret = add_evsel_fields(evsel, raw_trace);
> > +		ret = add_evsel_fields(evsel, raw_trace, is_sort_key);
> >  		if (ret < 0)
> >  			return ret;
> >  	}
> > @@ -1955,7 +1962,8 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
> >  }
> >  
> >  static int add_all_matching_fields(struct perf_evlist *evlist,
> > -				   char *field_name, bool raw_trace)
> > +				   char *field_name, bool raw_trace,
> > +				   bool is_sort_key)
> >  {
> >  	int ret = -ESRCH;
> >  	struct perf_evsel *evsel;
> > @@ -1969,14 +1977,16 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
> >  		if (field == NULL)
> >  			continue;
> >  
> > -		ret = __dynamic_dimension__add(evsel, field, raw_trace);
> > +		ret = __dynamic_dimension__add(evsel, field, raw_trace,
> > +					       is_sort_key);
> >  		if (ret < 0)
> >  			break;
> >  	}
> >  	return ret;
> >  }
> >  
> > -static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
> > +static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
> > +			     bool is_sort_key)
> >  {
> >  	char *str, *event_name, *field_name, *opt_name;
> >  	struct perf_evsel *evsel;
> > @@ -2006,12 +2016,13 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
> >  	}
> >  
> >  	if (!strcmp(field_name, "trace_fields")) {
> > -		ret = add_all_dynamic_fields(evlist, raw_trace);
> > +		ret = add_all_dynamic_fields(evlist, raw_trace, is_sort_key);
> >  		goto out;
> >  	}
> >  
> >  	if (event_name == NULL) {
> > -		ret = add_all_matching_fields(evlist, field_name, raw_trace);
> > +		ret = add_all_matching_fields(evlist, field_name, raw_trace,
> > +					      is_sort_key);
> >  		goto out;
> >  	}
> >  
> > @@ -2029,7 +2040,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
> >  	}
> >  
> >  	if (!strcmp(field_name, "*")) {
> > -		ret = add_evsel_fields(evsel, raw_trace);
> > +		ret = add_evsel_fields(evsel, raw_trace, is_sort_key);
> >  	} else {
> >  		field = pevent_find_any_field(evsel->tp_format, field_name);
> >  		if (field == NULL) {
> > @@ -2038,7 +2049,8 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
> >  			return -ENOENT;
> >  		}
> >  
> > -		ret = __dynamic_dimension__add(evsel, field, raw_trace);
> > +		ret = __dynamic_dimension__add(evsel, field, raw_trace,
> > +					       is_sort_key);
> >  	}
> >  
> >  out:
> > @@ -2182,7 +2194,7 @@ static int sort_dimension__add(const char *tok,
> >  		return 0;
> >  	}
> >  
> > -	if (!add_dynamic_entry(evlist, tok))
> > +	if (!add_dynamic_entry(evlist, tok, true))
> >  		return 0;
> >  
> >  	return -ESRCH;
> > @@ -2387,7 +2399,7 @@ void sort__setup_elide(FILE *output)
> >  	}
> >  }
> >  
> > -static int output_field_add(char *tok)
> > +static int output_field_add(struct perf_evlist *evlist, char *tok)
> >  {
> >  	unsigned int i;
> >  
> > @@ -2427,6 +2439,9 @@ static int output_field_add(char *tok)
> >  		return __sort_dimension__add_output(sd);
> >  	}
> >  
> > +	if (!add_dynamic_entry(evlist, tok, false))
> > +		return 0;
> > +
> >  	return -ESRCH;
> >  }
> >  
> > @@ -2452,7 +2467,7 @@ bool is_strict_order(const char *order)
> >  	return order && (*order != '+');
> >  }
> >  
> > -static int __setup_output_field(void)
> > +static int __setup_output_field(struct perf_evlist *evlist)
> >  {
> >  	char *tmp, *tok, *str, *strp;
> >  	int ret = -EINVAL;
> > @@ -2476,7 +2491,7 @@ static int __setup_output_field(void)
> >  
> >  	for (tok = strtok_r(strp, ", ", &tmp);
> >  			tok; tok = strtok_r(NULL, ", ", &tmp)) {
> > -		ret = output_field_add(tok);
> > +		ret = output_field_add(evlist, tok);
> >  		if (ret == -EINVAL) {
> >  			error("Invalid --fields key: `%s'", tok);
> >  			break;
> > @@ -2513,7 +2528,7 @@ int setup_sorting(struct perf_evlist *evlist)
> >  	if (sort__mode != SORT_MODE__DIFF)
> >  		perf_hpp__init();
> >  
> > -	err = __setup_output_field();
> > +	err = __setup_output_field(evlist);
> >  	if (err < 0)
> >  		return err;
> >  
> > -- 
> > 2.6.4

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields
  2016-01-05 22:23       ` Arnaldo Carvalho de Melo
@ 2016-01-06  0:00         ` Namhyung Kim
  2016-01-06  1:52           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 57+ messages in thread
From: Namhyung Kim @ 2016-01-06  0:00 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

On Tue, Jan 05, 2016 at 07:23:33PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 05, 2016 at 07:58:38PM +0900, Namhyung Kim escreveu:
> > To use dynamic sort keys, it might be good to add an option to see the
> > list of field names.
> > 
> >   $ perf evlist -T -i perf.data.sched
> 
> Humm, I think here we should just use --trace_fields, like what appears
> in the output for each line below, and also as is the case for the '-s
> trace_fields' case, ok?

OK

> 
> With:
> 
>   $ . ~/git/linux/tools/perf/perf-completion.sh 
>   [acme@zoo linux]$ perf evlist --
>   --force    --freq     --group    --input    --verbose  
>   [acme@zoo linux]$ perf evlist --
> 
> We can autocomplete it from --t<TAB> anyway :)
> 
> Unsure about '-T', perhaps this is so specialized, that can remain with
> just the long option?

OK

> 
> Perhaps we can add a tip, when we run:
> 
>   perf evlist
> 
> And there are tracepoint events, something like:
> 
>   perf evlist -v
>   sched:sched_switch ...
>   # Tip use 'perf evlist --trace_fields' to show fields for events such
>   # as "sched:sched_switch"

OK, it'd display this only the evlist has tracepoints.  How about this oneliner?

  # Tip: use 'perf evlist --trace_fields' to show fields for tracepoint events

Thanks,
Namhyung


> 
> - Arnaldo
> 
> >   sched:sched_switch: trace_fields=prev_comm,prev_pid,prev_prio,prev_state,next_comm,next_pid,next_prio
> >   sched:sched_stat_wait: trace_fields=comm,pid,delay
> >   sched:sched_stat_sleep: trace_fields=comm,pid,delay
> >   sched:sched_stat_iowait: trace_fields=comm,pid,delay
> >   sched:sched_stat_runtime: trace_fields=comm,pid,runtime,vruntime
> >   sched:sched_process_fork: trace_fields=parent_comm,parent_pid,child_comm,child_pid
> >   sched:sched_wakeup: trace_fields=comm,pid,prio,success,target_cpu
> >   sched:sched_wakeup_new: trace_fields=comm,pid,prio,success,target_cpu
> >   sched:sched_migrate_task: trace_fields=comm,pid,prio,orig_cpu,dest_cpu
> > 
> > Acked-by: Jiri Olsa <jolsa@kernel.org>
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > ---
> >  tools/perf/Documentation/perf-evlist.txt |  4 ++++
> >  tools/perf/builtin-evlist.c              |  1 +
> >  tools/perf/util/evsel.c                  | 23 +++++++++++++++++++++++
> >  tools/perf/util/evsel.h                  |  1 +
> >  4 files changed, 29 insertions(+)
> > 
> > diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
> > index 1ceb3700ffbb..b0d99c276cf5 100644
> > --- a/tools/perf/Documentation/perf-evlist.txt
> > +++ b/tools/perf/Documentation/perf-evlist.txt
> > @@ -32,6 +32,10 @@ OPTIONS
> >  --group::
> >  	Show event group information.
> >  
> > +-T::
> > +--trace::
> > +	Show tracepoint field names.
> > +
> >  SEE ALSO
> >  --------
> >  linkperf:perf-record[1], linkperf:perf-list[1],
> > diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
> > index 08a7d36a2cf8..2820bb2d8cf8 100644
> > --- a/tools/perf/builtin-evlist.c
> > +++ b/tools/perf/builtin-evlist.c
> > @@ -49,6 +49,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
> >  	OPT_BOOLEAN('g', "group", &details.event_group,
> >  		    "Show event group information"),
> >  	OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
> > +	OPT_BOOLEAN('T', "trace", &details.trace, "Show tracepoint fields"),
> >  	OPT_END()
> >  	};
> >  	const char * const evlist_usage[] = {
> > diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> > index 544e4400de13..174d0029e038 100644
> > --- a/tools/perf/util/evsel.c
> > +++ b/tools/perf/util/evsel.c
> > @@ -2298,6 +2298,29 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
> >  		printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
> >  					 term, (u64)evsel->attr.sample_freq);
> >  	}
> > +
> > +	if (details->trace) {
> > +		struct format_field *field;
> > +
> > +		if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
> > +			printed += comma_fprintf(fp, &first, " (not a tracepoint)");
> > +			goto out;
> > +		}
> > +
> > +		field = evsel->tp_format->format.fields;
> > +		if (field == NULL) {
> > +			printed += comma_fprintf(fp, &first, " (no trace field)");
> > +			goto out;
> > +		}
> > +
> > +		printed += comma_fprintf(fp, &first, " trace_fields=%s", field->name);
> > +
> > +		field = field->next;
> > +		while (field) {
> > +			printed += comma_fprintf(fp, &first, "%s", field->name);
> > +			field = field->next;
> > +		}
> > +	}
> >  out:
> >  	fputc('\n', fp);
> >  	return ++printed;
> > diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> > index 5ded1fc0341e..9b36dd584d4a 100644
> > --- a/tools/perf/util/evsel.h
> > +++ b/tools/perf/util/evsel.h
> > @@ -369,6 +369,7 @@ struct perf_attr_details {
> >  	bool verbose;
> >  	bool event_group;
> >  	bool force;
> > +	bool trace;
> >  };
> >  
> >  int perf_evsel__fprintf(struct perf_evsel *evsel,
> > -- 
> > 2.6.4

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields
  2016-01-06  0:00         ` Namhyung Kim
@ 2016-01-06  1:52           ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 57+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-01-06  1:52 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, David Ahern,
	Steven Rostedt, Frederic Weisbecker, Andi Kleen, Wang Nan

Em Wed, Jan 06, 2016 at 09:00:31AM +0900, Namhyung Kim escreveu:
> On Tue, Jan 05, 2016 at 07:23:33PM -0300, Arnaldo Carvalho de Melo wrote:
> > Em Tue, Jan 05, 2016 at 07:58:38PM +0900, Namhyung Kim escreveu:
> > > To use dynamic sort keys, it might be good to add an option to see the
> > > list of field names.
> > > 
> > >   $ perf evlist -T -i perf.data.sched
> > 
> > Humm, I think here we should just use --trace_fields, like what appears
> > in the output for each line below, and also as is the case for the '-s
> > trace_fields' case, ok?
> 
> OK
> 
> > 
> > With:
> > 
> >   $ . ~/git/linux/tools/perf/perf-completion.sh 
> >   [acme@zoo linux]$ perf evlist --
> >   --force    --freq     --group    --input    --verbose  
> >   [acme@zoo linux]$ perf evlist --
> > 
> > We can autocomplete it from --t<TAB> anyway :)
> > 
> > Unsure about '-T', perhaps this is so specialized, that can remain with
> > just the long option?
> 
> OK
> 
> > 
> > Perhaps we can add a tip, when we run:
> > 
> >   perf evlist
> > 
> > And there are tracepoint events, something like:
> > 
> >   perf evlist -v
> >   sched:sched_switch ...
> >   # Tip use 'perf evlist --trace_fields' to show fields for events such
> >   # as "sched:sched_switch"
> 
> OK, it'd display this only the evlist has tracepoints.  How about this oneliner?
> 
>   # Tip: use 'perf evlist --trace_fields' to show fields for tracepoint events

Sure, I tried using the name of the existing event, "sched:sched_switch"
in this case, to get even closer to what to pass to --trace_fields :-)
 
> Thanks,
> Namhyung
> 
> 
> > 
> > - Arnaldo
> > 
> > >   sched:sched_switch: trace_fields=prev_comm,prev_pid,prev_prio,prev_state,next_comm,next_pid,next_prio
> > >   sched:sched_stat_wait: trace_fields=comm,pid,delay
> > >   sched:sched_stat_sleep: trace_fields=comm,pid,delay
> > >   sched:sched_stat_iowait: trace_fields=comm,pid,delay
> > >   sched:sched_stat_runtime: trace_fields=comm,pid,runtime,vruntime
> > >   sched:sched_process_fork: trace_fields=parent_comm,parent_pid,child_comm,child_pid
> > >   sched:sched_wakeup: trace_fields=comm,pid,prio,success,target_cpu
> > >   sched:sched_wakeup_new: trace_fields=comm,pid,prio,success,target_cpu
> > >   sched:sched_migrate_task: trace_fields=comm,pid,prio,orig_cpu,dest_cpu
> > > 
> > > Acked-by: Jiri Olsa <jolsa@kernel.org>
> > > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > > ---
> > >  tools/perf/Documentation/perf-evlist.txt |  4 ++++
> > >  tools/perf/builtin-evlist.c              |  1 +
> > >  tools/perf/util/evsel.c                  | 23 +++++++++++++++++++++++
> > >  tools/perf/util/evsel.h                  |  1 +
> > >  4 files changed, 29 insertions(+)
> > > 
> > > diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
> > > index 1ceb3700ffbb..b0d99c276cf5 100644
> > > --- a/tools/perf/Documentation/perf-evlist.txt
> > > +++ b/tools/perf/Documentation/perf-evlist.txt
> > > @@ -32,6 +32,10 @@ OPTIONS
> > >  --group::
> > >  	Show event group information.
> > >  
> > > +-T::
> > > +--trace::
> > > +	Show tracepoint field names.
> > > +
> > >  SEE ALSO
> > >  --------
> > >  linkperf:perf-record[1], linkperf:perf-list[1],
> > > diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
> > > index 08a7d36a2cf8..2820bb2d8cf8 100644
> > > --- a/tools/perf/builtin-evlist.c
> > > +++ b/tools/perf/builtin-evlist.c
> > > @@ -49,6 +49,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
> > >  	OPT_BOOLEAN('g', "group", &details.event_group,
> > >  		    "Show event group information"),
> > >  	OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
> > > +	OPT_BOOLEAN('T', "trace", &details.trace, "Show tracepoint fields"),
> > >  	OPT_END()
> > >  	};
> > >  	const char * const evlist_usage[] = {
> > > diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> > > index 544e4400de13..174d0029e038 100644
> > > --- a/tools/perf/util/evsel.c
> > > +++ b/tools/perf/util/evsel.c
> > > @@ -2298,6 +2298,29 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
> > >  		printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
> > >  					 term, (u64)evsel->attr.sample_freq);
> > >  	}
> > > +
> > > +	if (details->trace) {
> > > +		struct format_field *field;
> > > +
> > > +		if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
> > > +			printed += comma_fprintf(fp, &first, " (not a tracepoint)");
> > > +			goto out;
> > > +		}
> > > +
> > > +		field = evsel->tp_format->format.fields;
> > > +		if (field == NULL) {
> > > +			printed += comma_fprintf(fp, &first, " (no trace field)");
> > > +			goto out;
> > > +		}
> > > +
> > > +		printed += comma_fprintf(fp, &first, " trace_fields=%s", field->name);
> > > +
> > > +		field = field->next;
> > > +		while (field) {
> > > +			printed += comma_fprintf(fp, &first, "%s", field->name);
> > > +			field = field->next;
> > > +		}
> > > +	}
> > >  out:
> > >  	fputc('\n', fp);
> > >  	return ++printed;
> > > diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> > > index 5ded1fc0341e..9b36dd584d4a 100644
> > > --- a/tools/perf/util/evsel.h
> > > +++ b/tools/perf/util/evsel.h
> > > @@ -369,6 +369,7 @@ struct perf_attr_details {
> > >  	bool verbose;
> > >  	bool event_group;
> > >  	bool force;
> > > +	bool trace;
> > >  };
> > >  
> > >  int perf_evsel__fprintf(struct perf_evsel *evsel,
> > > -- 
> > > 2.6.4

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf hist: Pass struct sample to __hists__add_entry()
  2015-12-22 17:06 ` [PATCH 01/13] perf hist: Pass struct sample to __hists__add_entry() Namhyung Kim
@ 2016-01-09 16:22   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, acme, hpa, andi, tglx, fweisbec, namhyung, rostedt,
	dsahern, jolsa, mingo, linux-kernel, wangnan0

Commit-ID:  fd36f3dd79331b9610664b867ff205465bf9ce68
Gitweb:     http://git.kernel.org/tip/fd36f3dd79331b9610664b867ff205465bf9ce68
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:06:58 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:10 -0300

perf hist: Pass struct sample to __hists__add_entry()

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>
Acked-by: Jiri Olsa <jolsa@kernel.org>
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-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 e18f1b9..b5b8db0 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 0b180a8..69f5b1fe 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 6243e2b..9eac98d 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 56e97f5..039bb91 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 a48a207..36439bf 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);

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf hist: Save raw_data/ size for tracepoint events
  2015-12-24  2:16         ` [PATCH v4.2 " Namhyung Kim
@ 2016-01-09 16:22           ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, dsahern, wangnan0, namhyung, mingo, hpa, rostedt, andi,
	linux-kernel, tglx, acme, jolsa, fweisbec

Commit-ID:  723928340c9d28d92dcaff8b8fbc9100a1cf9429
Gitweb:     http://git.kernel.org/tip/723928340c9d28d92dcaff8b8fbc9100a1cf9429
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Thu, 24 Dec 2015 11:16:17 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:10 -0300

perf hist: Save raw_data/size for tracepoint events

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>
Acked-by: Jiri Olsa <jolsa@kernel.org>
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/1450923377-18641-1-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/hist.c | 24 ++++++++++++++++++++++++
 tools/perf/util/sort.h |  2 ++
 2 files changed, 26 insertions(+)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 039bb91..2dcf38a 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -369,6 +369,25 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
 		if (symbol_conf.use_callchain)
 			callchain_init(he->callchain);
 
+		if (he->raw_data) {
+			he->raw_data = memdup(he->raw_data, he->raw_size);
+
+			if (he->raw_data == NULL) {
+				map__put(he->ms.map);
+				if (he->branch_info) {
+					map__put(he->branch_info->from.map);
+					map__put(he->branch_info->to.map);
+					free(he->branch_info);
+				}
+				if (he->mem_info) {
+					map__put(he->mem_info->iaddr.map);
+					map__put(he->mem_info->daddr.map);
+				}
+				free(he->stat_acc);
+				free(he);
+				return NULL;
+			}
+		}
 		INIT_LIST_HEAD(&he->pairs.node);
 		thread__get(he->thread);
 	}
@@ -487,6 +506,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);
@@ -801,6 +822,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
 			.sym = al->sym,
 		},
 		.parent = iter->parent,
+		.raw_data = sample->raw_data,
+		.raw_size = sample->raw_size,
 	};
 	int i;
 	struct callchain_cursor cursor;
@@ -974,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->raw_data);
 	free(he);
 }
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 86f05e7..d298987 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 */
 };
 

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] tools lib traceevent: Factor out and export print_event_field[s]()
  2015-12-23 13:08   ` [PATCH v4.1 " Namhyung Kim
  2016-01-04 15:31     ` Steven Rostedt
@ 2016-01-09 16:22     ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, dsahern, wangnan0, hpa, andi, namhyung, mingo,
	linux-kernel, fweisbec, rostedt, jolsa, peterz, tglx

Commit-ID:  be45d40efec96558c489579bbf93465e90b10abe
Gitweb:     http://git.kernel.org/tip/be45d40efec96558c489579bbf93465e90b10abe
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 22:08:41 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:11 -0300

tools lib traceevent: Factor out and export print_event_field[s]()

The print_event_field() and print_event_fields() functions print basic
information of a given field or event without the print format.  They'll
be used by dynamic sort keys later.

Committer note:

Rename it to pevent_print_field[s]() to get proper namespacing, as
discussed with Steven Rostedt.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
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: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1450876121-22494-1-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/traceevent/event-parse.c | 129 +++++++++++++++++++------------------
 tools/lib/traceevent/event-parse.h |   4 ++
 2 files changed, 72 insertions(+), 61 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 68276f3..ea69ce3 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -4735,73 +4735,80 @@ static int is_printable_array(char *p, unsigned int len)
 	return 1;
 }
 
-static void print_event_fields(struct trace_seq *s, void *data,
-			       int size __maybe_unused,
-			       struct event_format *event)
+void pevent_print_field(struct trace_seq *s, void *data,
+			struct format_field *field)
 {
-	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;
-			}
+	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 {
-			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 {
+			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%llx", val);
+					trace_seq_printf(s, "0x%x", (int)val);
 				else
-					trace_seq_printf(s, "%llu", val);
+					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);
 		}
+	}
+}
+
+void pevent_print_fields(struct trace_seq *s, void *data,
+			 int size __maybe_unused, struct event_format *event)
+{
+	struct format_field *field;
+
+	field = event->format.fields;
+	while (field) {
+		trace_seq_printf(s, " %s=", field->name);
+		pevent_print_field(s, data, field);
 		field = field->next;
 	}
 }
@@ -4827,7 +4834,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
 
 	if (event->flags & EVENT_FL_FAILED) {
 		trace_seq_printf(s, "[FAILED TO PARSE]");
-		print_event_fields(s, data, size, event);
+		pevent_print_fields(s, data, size, event);
 		return;
 	}
 
@@ -5301,7 +5308,7 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
 	int print_pretty = 1;
 
 	if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
-		print_event_fields(s, record->data, record->size, event);
+		pevent_print_fields(s, record->data, record->size, event);
 	else {
 
 		if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 6fc83c7..706d9bc 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -705,6 +705,10 @@ 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 pevent_print_field(struct trace_seq *s, void *data,
+			struct format_field *field);
+void pevent_print_fields(struct trace_seq *s, void *data,
+			 int size __maybe_unused, struct event_format *event);
 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,

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf top: Create the evlist sooner
  2015-12-22 17:07 ` [PATCH 04/13] perf tools: Pass evlist to setup_sorting() Namhyung Kim
@ 2016-01-09 16:23   ` tip-bot for Namhyung Kim
  2016-01-09 16:23   ` [tip:perf/core] perf tools: Pass evlist to setup_sorting() tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, linux-kernel, fweisbec, tglx, hpa, namhyung, acme,
	rostedt, peterz, jolsa, andi, dsahern, wangnan0

Commit-ID:  54f8f40384ab940e15585afde5c278c8e7726214
Gitweb:     http://git.kernel.org/tip/54f8f40384ab940e15585afde5c278c8e7726214
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:01 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:11 -0300

perf top: Create the evlist sooner

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, so we need to pass the evlist
to the sort routines, create it sooner so that the next patch can do
that.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
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-5-git-send-email-namhyung@kernel.org
[ Split from the patch passing the evlist to the sort routines ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-top.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 9ebd67a..4e913d8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1231,6 +1231,12 @@ 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;
@@ -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)

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Pass evlist to setup_sorting()
  2015-12-22 17:07 ` [PATCH 04/13] perf tools: Pass evlist to setup_sorting() Namhyung Kim
  2016-01-09 16:23   ` [tip:perf/core] perf top: Create the evlist sooner tip-bot for Namhyung Kim
@ 2016-01-09 16:23   ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rostedt, acme, jolsa, peterz, tglx, wangnan0, namhyung, dsahern,
	hpa, andi, mingo, linux-kernel, fweisbec

Commit-ID:  40184c46a3055a97e2efa69da6f17c05bff4b776
Gitweb:     http://git.kernel.org/tip/40184c46a3055a97e2efa69da6f17c05bff4b776
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:01 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:11 -0300

perf tools: Pass evlist to setup_sorting()

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>
Acked-by: Jiri Olsa <jolsa@kernel.org>
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-5-git-send-email-namhyung@kernel.org
[ Moving the evlist creation earlier in top was split to a previous patch ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c     |  2 +-
 tools/perf/builtin-diff.c         |  2 +-
 tools/perf/builtin-report.c       |  2 +-
 tools/perf/builtin-top.c          |  2 +-
 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, 27 insertions(+), 23 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index b5b8db0..cc5c126 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 69f5b1fe..8706383 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 2a7330b..ea53c81 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 4e913d8..0058259 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1241,7 +1241,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 	/* 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)
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 8292948..e360892 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 ccb5b49..2a784be 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 9eac98d..c764d69 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 248beec..ebe6cd4 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 2d8ccd4..0c038a2 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 d298987..1a00f1e 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);
 

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Add dynamic sort key for tracepoint events
  2015-12-22 17:07 ` [PATCH 05/13] perf tools: Add dynamic sort key for tracepoint events Namhyung Kim
  2016-01-04 15:04   ` Arnaldo Carvalho de Melo
@ 2016-01-09 16:23   ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: wangnan0, namhyung, hpa, linux-kernel, rostedt, dsahern, jolsa,
	andi, peterz, acme, mingo, fweisbec, tglx

Commit-ID:  c7c2a5e40f17ab3b14716d4f08d03792a9b683e7
Gitweb:     http://git.kernel.org/tip/c7c2a5e40f17ab3b14716d4f08d03792a9b683e7
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:02 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:11 -0300

perf tools: Add dynamic sort key for tracepoint events

The existing sort keys are less useful for tracepoint events in that
they are always sampled at the same place, the function where the
tracepoint is located.

For example, a 'perf report' on sched:sched_switch event looks like the
following:

  # 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

In fact, tracepoints have meaningful information in their fields but
there's no way to use in 'perf report' currently.  The dynamic sort keys
are introduced in this patc to overcome this limitation.

The sched:sched_switch events have following fields:

  # 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 output 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'.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo 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-6-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/sort.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 213 insertions(+)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 0c038a2..cc659ba 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1531,6 +1531,216 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
 	return 0;
 }
 
+struct hpp_dynamic_entry {
+	struct perf_hpp_fmt hpp;
+	struct perf_evsel *evsel;
+	struct format_field *field;
+	unsigned dynamic_len;
+};
+
+static int hde_width(struct hpp_dynamic_entry *hde)
+{
+	if (!hde->hpp.len) {
+		int len = hde->dynamic_len;
+		int namelen = strlen(hde->field->name);
+		int fieldlen = hde->field->size;
+
+		if (namelen > len)
+			len = namelen;
+
+		if (!(hde->field->flags & FIELD_IS_STRING)) {
+			/* length for print hex numbers */
+			fieldlen = hde->field->size * 2 + 2;
+		}
+		if (fieldlen > len)
+			len = fieldlen;
+
+		hde->hpp.len = len;
+	}
+	return hde->hpp.len;
+}
+
+static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+			      struct perf_evsel *evsel __maybe_unused)
+{
+	struct hpp_dynamic_entry *hde;
+	size_t len = fmt->user_len;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (!len)
+		len = hde_width(hde);
+
+	return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, hde->field->name);
+}
+
+static int __sort__hde_width(struct perf_hpp_fmt *fmt,
+			     struct perf_hpp *hpp __maybe_unused,
+			     struct perf_evsel *evsel __maybe_unused)
+{
+	struct hpp_dynamic_entry *hde;
+	size_t len = fmt->user_len;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (!len)
+		len = hde_width(hde);
+
+	return len;
+}
+
+static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+			     struct hist_entry *he)
+{
+	struct hpp_dynamic_entry *hde;
+	size_t len = fmt->user_len;
+	struct trace_seq seq;
+	int ret;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (!len)
+		len = hde_width(hde);
+
+	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);
+	return ret;
+}
+
+static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
+			       struct hist_entry *a, struct hist_entry *b)
+{
+	struct hpp_dynamic_entry *hde;
+	struct format_field *field;
+	unsigned offset, size;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	if (hists_to_evsel(a->hists) != hde->evsel)
+		return 0;
+
+	field = hde->field;
+	if (field->flags & FIELD_IS_DYNAMIC) {
+		unsigned long long dyn;
+
+		pevent_read_number_field(field, a->raw_data, &dyn);
+		offset = dyn & 0xffff;
+		size = (dyn >> 16) & 0xffff;
+
+		/* record max width for output */
+		if (size > hde->dynamic_len)
+			hde->dynamic_len = size;
+	} else {
+		offset = field->offset;
+		size = field->size;
+	}
+
+	return memcmp(a->raw_data + offset, b->raw_data + offset, size);
+}
+
+static struct hpp_dynamic_entry *
+__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
+{
+	struct hpp_dynamic_entry *hde;
+
+	hde = malloc(sizeof(*hde));
+	if (hde == NULL) {
+		pr_debug("Memory allocation failed\n");
+		return NULL;
+	}
+
+	hde->evsel = evsel;
+	hde->field = field;
+	hde->dynamic_len = 0;
+
+	hde->hpp.name = field->name;
+	hde->hpp.header = __sort__hde_header;
+	hde->hpp.width  = __sort__hde_width;
+	hde->hpp.entry  = __sort__hde_entry;
+	hde->hpp.color  = NULL;
+
+	hde->hpp.cmp = __sort__hde_cmp;
+	hde->hpp.collapse = __sort__hde_cmp;
+	hde->hpp.sort = __sort__hde_cmp;
+
+	INIT_LIST_HEAD(&hde->hpp.list);
+	INIT_LIST_HEAD(&hde->hpp.sort_list);
+	hde->hpp.elide = false;
+	hde->hpp.len = 0;
+	hde->hpp.user_len = 0;
+
+	return hde;
+}
+
+static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
+{
+	char *str, *event_name, *field_name;
+	struct perf_evsel *evsel, *pos;
+	struct format_field *field;
+	struct hpp_dynamic_entry *hde;
+	int ret = 0;
+
+	if (evlist == NULL)
+		return -ENOENT;
+
+	str = strdup(tok);
+	if (str == NULL)
+		return -ENOMEM;
+
+	event_name = str;
+	field_name = strchr(str, '.');
+	if (field_name == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+	*field_name++ = '\0';
+
+	evsel = NULL;
+	evlist__for_each(evlist, pos) {
+		if (!strcmp(pos->name, event_name)) {
+			evsel = pos;
+			break;
+		}
+	}
+
+	if (evsel == NULL) {
+		pr_debug("Cannot find event: %s\n", event_name);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+		pr_debug("%s is not a tracepoint event\n", event_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	field = pevent_find_any_field(evsel->tp_format, field_name);
+	if (field == NULL) {
+		pr_debug("Cannot find event field for %s.%s\n",
+		       event_name, field_name);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	hde = __alloc_dynamic_entry(evsel, field);
+	if (hde == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	perf_hpp__register_sort_field(&hde->hpp);
+
+out:
+	free(str);
+	return ret;
+}
+
 static int __sort_dimension__add(struct sort_dimension *sd)
 {
 	if (sd->taken)
@@ -1667,6 +1877,9 @@ static int sort_dimension__add(const char *tok,
 		return 0;
 	}
 
+	if (!add_dynamic_entry(evlist, tok))
+		return 0;
+
 	return -ESRCH;
 }
 

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Try to show pretty printed output for dynamic sort keys
  2015-12-22 17:07 ` [PATCH 06/13] perf tools: Try to show pretty printed output for dynamic sort keys Namhyung Kim
  2016-01-04 15:16   ` Arnaldo Carvalho de Melo
@ 2016-01-09 16:24   ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:24 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rostedt, fweisbec, hpa, wangnan0, linux-kernel, acme, andi, tglx,
	dsahern, peterz, jolsa, namhyung, mingo

Commit-ID:  60517d28fbd91629686dcf9a39aef4e068a3d5f6
Gitweb:     http://git.kernel.org/tip/60517d28fbd91629686dcf9a39aef4e068a3d5f6
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:03 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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 <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo 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: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 */
 };
 

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Add 'trace' sort key
  2015-12-22 17:07 ` [PATCH 07/13] perf tools: Add 'trace' sort key Namhyung Kim
@ 2016-01-09 16:24   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:24 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: fweisbec, acme, andi, peterz, linux-kernel, wangnan0, hpa,
	rostedt, namhyung, tglx, jolsa, mingo, dsahern

Commit-ID:  a34bb6a08d6020bde0475bc901793771858a1112
Gitweb:     http://git.kernel.org/tip/a34bb6a08d6020bde0475bc901793771858a1112
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:04 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:12 -0300

perf tools: Add 'trace' sort key

The 'trace' sort key is to show tracepoint event output using either
print fmt or plugin.  For example sched_switch event (using plugin) will
show output like below:

  # perf record -e sched:sched_switch -a usleep 10
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.197 MB perf.data (69 samples) ]
  #

  $ perf report -s trace --stdio
  ...
  # Overhead  Trace output
  # ........  ...................................................
  #
       9.48%  swapper/0:0 [120] R ==> transmission-gt:17773 [120]
       9.48%  transmission-gt:17773 [120] S ==> swapper/0:0 [120]
       9.04%  swapper/2:0 [120] R ==> transmission-gt:17773 [120]
       8.92%  transmission-gt:17773 [120] S ==> swapper/2:0 [120]
       5.25%  swapper/0:0 [120] R ==> kworker/0:1H:109 [100]
       5.21%  kworker/0:1H:109 [100] S ==> swapper/0:0 [120]
       1.78%  swapper/3:0 [120] R ==> transmission-gt:17773 [120]
       1.78%  transmission-gt:17773 [120] S ==> swapper/3:0 [120]
       1.53%  Xephyr:6524 [120] S ==> swapper/0:0 [120]
       1.53%  swapper/0:0 [120] R ==> Xephyr:6524 [120]
       1.17%  swapper/2:0 [120] R ==> irq/33-iwlwifi:233 [49]
       1.13%  irq/33-iwlwifi:233 [49] S ==> swapper/2:0 [120]

Note that the 'trace' sort key works only for tracepoint events.  If
it's used to other type of events, just "N/A" will be printed.

Suggested-and-acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo 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: Jiri Olsa <jolsa@redhat.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-8-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/hist.h |  1 +
 tools/perf/util/sort.c | 76 +++++++++++++++++++++++++++++++++++++++-----------
 tools/perf/util/sort.h |  1 +
 3 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 36439bf..15b22c5 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,6 +52,7 @@ enum hist_column {
 	HISTC_MEM_IADDR_SYMBOL,
 	HISTC_TRANSACTION,
 	HISTC_CYCLES,
+	HISTC_TRACE,
 	HISTC_NR_COLS, /* Last entry */
 };
 
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 22d28c7..db8476a 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -445,6 +445,65 @@ struct sort_entry sort_socket = {
 	.se_width_idx	= HISTC_SOCKET,
 };
 
+/* --sort trace */
+
+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 int64_t
+sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	struct perf_evsel *evsel;
+
+	evsel = hists_to_evsel(left->hists);
+	if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+		return 0;
+
+	if (left->trace_output == NULL)
+		left->trace_output = get_trace_output(left);
+	if (right->trace_output == NULL)
+		right->trace_output = get_trace_output(right);
+
+	hists__new_col_len(left->hists, HISTC_TRACE, strlen(left->trace_output));
+	hists__new_col_len(right->hists, HISTC_TRACE, strlen(right->trace_output));
+
+	return strcmp(right->trace_output, left->trace_output);
+}
+
+static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
+				    size_t size, unsigned int width)
+{
+	struct perf_evsel *evsel;
+
+	evsel = hists_to_evsel(he->hists);
+	if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+		return scnprintf(bf, size, "%-*.*s", width, width, "N/A");
+
+	if (he->trace_output == NULL)
+		he->trace_output = get_trace_output(he);
+	return repsep_snprintf(bf, size, "%-*.*s", width, width, he->trace_output);
+}
+
+struct sort_entry sort_trace = {
+	.se_header      = "Trace output",
+	.se_cmp	        = sort__trace_cmp,
+	.se_snprintf    = hist_entry__trace_snprintf,
+	.se_width_idx	= HISTC_TRACE,
+};
+
 /* sort keys for branch stacks */
 
 static int64_t
@@ -1314,6 +1373,7 @@ static struct sort_dimension common_sort_dimensions[] = {
 	DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
 	DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
 	DIM(SORT_TRANSACTION, "transaction", sort_transaction),
+	DIM(SORT_TRACE, "trace", sort_trace),
 };
 
 #undef DIM
@@ -1560,22 +1620,6 @@ 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)
 {
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index f6d2a7e..6b7590a 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -183,6 +183,7 @@ enum sort_type {
 	SORT_LOCAL_WEIGHT,
 	SORT_GLOBAL_WEIGHT,
 	SORT_TRANSACTION,
+	SORT_TRACE,
 
 	/* branch stack specific sort keys */
 	__SORT_BRANCH_STACK,

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf report/top: Add --raw-trace option
  2015-12-22 17:07 ` [PATCH 08/13] perf tools: Add --raw-trace option Namhyung Kim
@ 2016-01-09 16:24   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:24 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi, linux-kernel, hpa, mingo, peterz, tglx, fweisbec, dsahern,
	rostedt, namhyung, acme, jolsa, wangnan0

Commit-ID:  053a3989e12fdf3be45c00ec1cb0ce09fba0ee4a
Gitweb:     http://git.kernel.org/tip/053a3989e12fdf3be45c00ec1cb0ce09fba0ee4a
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:05 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:12 -0300

perf report/top: Add --raw-trace option

The --raw-trace option allows disabling pretty printing by the event's
print_fmt or plugin.  Besides that, each dynamic sort key now can
receive a 'raw' suffix separated by '/' to ask for the raw trace of a
specific field.

  $ perf report -s comm,kmem:kmalloc.gfp_flags
  ...
  # 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

Now

  $ perf report -s comm,kmem:kmalloc.gfp_flags --raw-trace
or
  $ perf report -s comm,kmem:kmalloc.gfp_flags/raw
  ...
  # Overhead  Command   gfp_flags
  # ........  .......  ..........
  #
      99.89%  perf          32848
       0.06%  sleep           208
       0.03%  perf          32976
       0.01%  perf            208

Suggested-and-Acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo 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: Jiri Olsa <jolsa@redhat.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-9-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-report.txt |  3 +++
 tools/perf/Documentation/perf-top.txt    |  3 +++
 tools/perf/builtin-report.c              |  2 ++
 tools/perf/builtin-top.c                 |  2 ++
 tools/perf/util/sort.c                   | 32 +++++++++++++++++++++++++++++---
 tools/perf/util/symbol.h                 |  3 ++-
 6 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index dab99ed..ae7cd91 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -371,6 +371,9 @@ include::itrace.txt[]
 --socket-filter::
 	Only report the samples on the processor socket that match with this filter
 
+--raw-trace::
+	When displaying traceevent output, do not use print fmt or plugins.
+
 include::callchain-overhead-calculation.txt[]
 
 SEE ALSO
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 556cec0..b0e60e1 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -230,6 +230,9 @@ Default is to monitor all CPUS.
 	The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
 	Note that this feature may not be available on all processors.
 
+--raw-trace::
+	When displaying traceevent output, do not use print fmt or plugins.
+
 INTERACTIVE PROMPTING KEYS
 --------------------------
 
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ea53c81..f10c663 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -788,6 +788,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "Show callgraph from reference event"),
 	OPT_INTEGER(0, "socket-filter", &report.socket_filter,
 		    "only show processor socket that match with this filter"),
+	OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
+		    "Show raw trace event output (do not use print fmt or plugins)"),
 	OPT_END()
 	};
 	struct perf_data_file file = {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 0058259..bf01cbb 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1210,6 +1210,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_CALLBACK('j', "branch-filter", &opts->branch_stack,
 		     "branch filter mask", "branch stack filter modes",
 		     parse_branch_stack),
+	OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
+		    "Show raw trace event output (do not use print fmt or plugins)"),
 	OPT_END()
 	};
 	const char * const top_usage[] = {
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index db8476a..3477685 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -459,7 +459,12 @@ static char *get_trace_output(struct hist_entry *he)
 	evsel = hists_to_evsel(he->hists);
 
 	trace_seq_init(&seq);
-	pevent_event_info(&seq, evsel->tp_format, &rec);
+	if (symbol_conf.raw_trace) {
+		pevent_print_fields(&seq, he->raw_data, he->raw_size,
+				    evsel->tp_format);
+	} else {
+		pevent_event_info(&seq, evsel->tp_format, &rec);
+	}
 	return seq.buffer;
 }
 
@@ -1596,6 +1601,7 @@ struct hpp_dynamic_entry {
 	struct perf_evsel *evsel;
 	struct format_field *field;
 	unsigned dynamic_len;
+	bool raw_trace;
 };
 
 static int hde_width(struct hpp_dynamic_entry *hde)
@@ -1628,6 +1634,9 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
 	size_t namelen;
 	bool last = false;
 
+	if (hde->raw_trace)
+		return;
+
 	/* parse pretty print result and update max length */
 	if (!he->trace_output)
 		he->trace_output = get_trace_output(he);
@@ -1708,8 +1717,10 @@ 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;
+	if (hde->raw_trace)
+		goto raw_field;
 
+	field = hde->field;
 	namelen = strlen(field->name);
 	str = he->trace_output;
 
@@ -1738,6 +1749,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 
 	if (str == NULL) {
 		struct trace_seq seq;
+raw_field:
 		trace_seq_init(&seq);
 		pevent_print_field(&seq, he->raw_data, hde->field);
 		str = seq.buffer;
@@ -1818,10 +1830,11 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
 
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
-	char *str, *event_name, *field_name;
+	char *str, *event_name, *field_name, *raw_opt;
 	struct perf_evsel *evsel, *pos;
 	struct format_field *field;
 	struct hpp_dynamic_entry *hde;
+	bool raw_trace = symbol_conf.raw_trace;
 	int ret = 0;
 
 	if (evlist == NULL)
@@ -1839,6 +1852,18 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	}
 	*field_name++ = '\0';
 
+	raw_opt = strchr(field_name, '/');
+	if (raw_opt) {
+		*raw_opt++ = '\0';
+
+		if (strcmp(raw_opt, "raw")) {
+			pr_err("Unsupported field option %s\n", raw_opt);
+			ret = -EINVAL;
+			goto out;
+		}
+		raw_trace = true;
+	}
+
 	evsel = NULL;
 	evlist__for_each(evlist, pos) {
 		if (!strcmp(pos->name, event_name)) {
@@ -1872,6 +1897,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 		ret = -ENOMEM;
 		goto out;
 	}
+	hde->raw_trace = raw_trace;
 
 	perf_hpp__register_sort_field(&hde->hpp);
 
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 857f707..ccd1caa 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -109,7 +109,8 @@ struct symbol_conf {
 			branch_callstack,
 			has_filter,
 			show_ref_callgraph,
-			hide_unresolved;
+			hide_unresolved,
+			raw_trace;
 	const char	*vmlinux_name,
 			*kallsyms_name,
 			*source_prefix,

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Support shortcuts for events in dynamic sort keys
  2015-12-22 17:07 ` [PATCH 09/13] perf tools: Support shortcuts for events in dynamic sort keys Namhyung Kim
@ 2016-01-09 16:25   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rostedt, fweisbec, peterz, mingo, namhyung, jolsa, wangnan0,
	andi, acme, tglx, hpa, linux-kernel, dsahern

Commit-ID:  5d0cff93bb7aa85349230d4e29902b2648640c53
Gitweb:     http://git.kernel.org/tip/5d0cff93bb7aa85349230d4e29902b2648640c53
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:06 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:12 -0300

perf tools: Support shortcuts for events in dynamic sort keys

The dynamic sort key requires event name but specifying full event name
is rather inconvenient.  This patch adds more ways to identify the event
in a more compact way.

  1. If session has just one event, event name can be omitted.
  2. Events can be accessed by index preceded by a percent sign.
  3. A part of the name can be used, if it's not ambiguous.  The partial
     name should not contain ':' in it.
  4. Full system + event name is still used, it should contain ':'.

So in the below example all does same thing:

  $ perf record -e sched:sched_switch -a sleep 1

  $ perf report -s next_pid,next_comm
  $ perf report -s %1.next_pid,%1.next_comm
  $ perf report -s switch.next_pid,switch.next_comm
  $ perf report -s sched:sched_switch.next_pid,sched:sched_switch.next_comm

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo 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-10-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/sort.c | 107 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 87 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 3477685..f3a98c2 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1828,10 +1828,90 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
 	return hde;
 }
 
+static int parse_field_name(char *str, char **event, char **field, char **opt)
+{
+	char *event_name, *field_name, *opt_name;
+
+	event_name = str;
+	field_name = strchr(str, '.');
+
+	if (field_name) {
+		*field_name++ = '\0';
+	} else {
+		event_name = NULL;
+		field_name = str;
+	}
+
+	opt_name = strchr(field_name, '/');
+	if (opt_name)
+		*opt_name++ = '\0';
+
+	*event = event_name;
+	*field = field_name;
+	*opt   = opt_name;
+
+	return 0;
+}
+
+/* find match evsel using a given event name.  The event name can be:
+ *   1. NULL - only valid for single event session
+ *   2. '%' + event index (e.g. '%1' for first event)
+ *   3. full event name (e.g. sched:sched_switch)
+ *   4. partial event name (should not contain ':')
+ */
+static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
+{
+	struct perf_evsel *evsel = NULL;
+	struct perf_evsel *pos;
+	bool full_name;
+
+	/* case 1 */
+	if (event_name == NULL) {
+		if (evlist->nr_entries != 1) {
+			pr_debug("event name should be given\n");
+			return NULL;
+		}
+
+		return perf_evlist__first(evlist);
+	}
+
+	/* case 2 */
+	if (event_name[0] == '%') {
+		int nr = strtol(event_name+1, NULL, 0);
+
+		if (nr > evlist->nr_entries)
+			return NULL;
+
+		evsel = perf_evlist__first(evlist);
+		while (--nr > 0)
+			evsel = perf_evsel__next(evsel);
+
+		return evsel;
+	}
+
+	full_name = !!strchr(event_name, ':');
+	evlist__for_each(evlist, pos) {
+		/* case 3 */
+		if (full_name && !strcmp(pos->name, event_name))
+			return pos;
+		/* case 4 */
+		if (!full_name && strstr(pos->name, event_name)) {
+			if (evsel) {
+				pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
+					 event_name, evsel->name, pos->name);
+				return NULL;
+			}
+			evsel = pos;
+		}
+	}
+
+	return evsel;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
-	char *str, *event_name, *field_name, *raw_opt;
-	struct perf_evsel *evsel, *pos;
+	char *str, *event_name, *field_name, *opt_name;
+	struct perf_evsel *evsel;
 	struct format_field *field;
 	struct hpp_dynamic_entry *hde;
 	bool raw_trace = symbol_conf.raw_trace;
@@ -1844,34 +1924,21 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	if (str == NULL)
 		return -ENOMEM;
 
-	event_name = str;
-	field_name = strchr(str, '.');
-	if (field_name == NULL) {
+	if (parse_field_name(str, &event_name, &field_name, &opt_name) < 0) {
 		ret = -EINVAL;
 		goto out;
 	}
-	*field_name++ = '\0';
 
-	raw_opt = strchr(field_name, '/');
-	if (raw_opt) {
-		*raw_opt++ = '\0';
-
-		if (strcmp(raw_opt, "raw")) {
-			pr_err("Unsupported field option %s\n", raw_opt);
+	if (opt_name) {
+		if (strcmp(opt_name, "raw")) {
+			pr_debug("unsupported field option %s\n", opt_name);
 			ret = -EINVAL;
 			goto out;
 		}
 		raw_trace = true;
 	}
 
-	evsel = NULL;
-	evlist__for_each(evlist, pos) {
-		if (!strcmp(pos->name, event_name)) {
-			evsel = pos;
-			break;
-		}
-	}
-
+	evsel = find_evsel(evlist, event_name);
 	if (evsel == NULL) {
 		pr_debug("Cannot find event: %s\n", event_name);
 		ret = -ENOENT;

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Support '<event>.*' dynamic sort key
  2015-12-22 17:07 ` [PATCH 10/13] perf tools: Support '<event>.*' dynamic sort key Namhyung Kim
@ 2016-01-09 16:25   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, wangnan0, andi, rostedt, hpa, acme, jolsa, tglx,
	fweisbec, peterz, mingo, namhyung, dsahern

Commit-ID:  3b099bf5898ac1bf44d822f0bc15a7517e6fa117
Gitweb:     http://git.kernel.org/tip/3b099bf5898ac1bf44d822f0bc15a7517e6fa117
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:07 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:12 -0300

perf tools: Support '<event>.*' dynamic sort key

Support '*' character for field name to add all (non-common) fields as
sort keys easily.

  $ perf report -s 'switch.*' --stdio
  ...
  # Overhead    prev_comm  prev_pid   prev_prio  prev_state     next_comm  next_pid  next_prio
  # ........  ...........  .........  .........  ..........  ............  ........  .........
  #
       3.82%    swapper/0         0         120           0   netctl-auto     18711        120
       3.75%  netctl-auto     18711         120           1     swapper/0         0        120
       2.24%    swapper/1         0         120           0   netctl-auto     18709        120
       2.24%  netctl-auto     18709         120           1     swapper/1         0        120
       1.80%    swapper/2         0         120           0   rcu_preempt         7        120
       1.80%    swapper/2         0         120           0   netctl-auto     18711        120
       1.80%  rcu_preempt         7         120           1     swapper/2         0        120
       1.80%  netctl-auto     18711         120           1     swapper/2         0        120
  ...

Suggested-and-acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo 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-11-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/sort.c | 49 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index f3a98c2..f6aef15 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1908,12 +1908,27 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 	return evsel;
 }
 
+static int __dynamic_dimension__add(struct perf_evsel *evsel,
+				    struct format_field *field,
+				    bool raw_trace)
+{
+	struct hpp_dynamic_entry *hde;
+
+	hde = __alloc_dynamic_entry(evsel, field);
+	if (hde == NULL)
+		return -ENOMEM;
+
+	hde->raw_trace = raw_trace;
+
+	perf_hpp__register_sort_field(&hde->hpp);
+	return 0;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
 	char *str, *event_name, *field_name, *opt_name;
 	struct perf_evsel *evsel;
 	struct format_field *field;
-	struct hpp_dynamic_entry *hde;
 	bool raw_trace = symbol_conf.raw_trace;
 	int ret = 0;
 
@@ -1951,22 +1966,26 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 		goto out;
 	}
 
-	field = pevent_find_any_field(evsel->tp_format, field_name);
-	if (field == NULL) {
-		pr_debug("Cannot find event field for %s.%s\n",
-		       event_name, field_name);
-		ret = -ENOENT;
-		goto out;
-	}
+	if (!strcmp(field_name, "*")) {
+		field = evsel->tp_format->format.fields;
 
-	hde = __alloc_dynamic_entry(evsel, field);
-	if (hde == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	hde->raw_trace = raw_trace;
+		while (field) {
+			ret = __dynamic_dimension__add(evsel, field, raw_trace);
+			if (ret < 0)
+				goto out;
 
-	perf_hpp__register_sort_field(&hde->hpp);
+			field = field->next;
+		}
+	} else {
+		field = pevent_find_any_field(evsel->tp_format, field_name);
+		if (field == NULL) {
+			pr_debug("Cannot find event field for %s.%s\n",
+				 event_name, field_name);
+			return -ENOENT;
+		}
+
+		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+	}
 
 out:
 	free(str);

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Skip dynamic fields not defined for current event
  2015-12-22 17:07 ` [PATCH 11/13] perf tools: Skip dynamic fields not defined for current event Namhyung Kim
@ 2016-01-09 16:25   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rostedt, linux-kernel, andi, namhyung, wangnan0, acme, dsahern,
	fweisbec, jolsa, mingo, hpa, tglx, peterz

Commit-ID:  361459f163fa1ec7ff4700ec876c3b7ff5f36cc6
Gitweb:     http://git.kernel.org/tip/361459f163fa1ec7ff4700ec876c3b7ff5f36cc6
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:08 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:12 -0300

perf tools: Skip dynamic fields not defined for current event

When there are multiple events, each dynamic sort key is defined just
for one event.  In this case other events will always show "N/A" for
those fields.  But they are meaningless and consume precious screen
width.

Let's skip those undefined dynamic fields.

  $ perf record -e kmem:kmalloc,kmem:kfree -a sleep 1

  $ perf report -s 'comm,kmalloc.*' --stdio
  # To display the perf.data header info, please use --header/--header-only options.
  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 20K of event 'kmem:kmalloc'
  # Event count (approx.): 20533
  #
  # Overhead  Command           call_site                 ptr  bytes_req  bytes_alloc            gfp_flags
  # ........  .......  ..................  ..................  .........  ...........  ...................
  #
      99.89%  perf       ffffffffa01d4396  0xffff8803ffb79720         96           96    GFP_NOFS|GFP_ZERO
       0.06%  sleep      ffffffff8114e1cd  0xffff8803d228a000       4096         4096           GFP_KERNEL
       0.03%  perf       ffffffff811d6ae6  0xffff8803f7678f00        240          256  GFP_KERNEL|GFP_ZERO
       0.00%  perf       ffffffff812263c1  0xffff880406172380        128          128           GFP_KERNEL
       0.00%  perf       ffffffff812264b9  0xffff8803ffac1600        504          512           GFP_KERNEL
       0.00%  perf       ffffffff81226634  0xffff880401dc5280         28           32           GFP_KERNEL
       0.00%  sleep      ffffffff81226da9  0xffff8803ffac3a00        392          512           GFP_KERNEL

  # Samples: 20K of event 'kmem:kfree'
  # Event count (approx.): 20597
  #
  # Overhead  Command
  # ........  ..............
  #
      99.63%  perf
       0.14%  sleep
       0.11%  irq/36-iwlwifi
       0.11%  kworker/u16:0
       0.01%  Xorg
       0.00%  firefox

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo 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-12-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/ui/browsers/hists.c |  7 ++++---
 tools/perf/ui/gtk/hists.c      |  4 ++--
 tools/perf/ui/hist.c           |  2 +-
 tools/perf/ui/stdio/hist.c     |  6 +++---
 tools/perf/util/hist.c         |  2 +-
 tools/perf/util/hist.h         | 14 ++++++++++++--
 tools/perf/util/sort.c         | 20 ++++++++++++++------
 7 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index ec33196..901d481 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1041,7 +1041,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 		hist_browser__gotorc(browser, row, 0);
 
 		perf_hpp__for_each_format(fmt) {
-			if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll)
+			if (perf_hpp__should_skip(fmt, entry->hists) ||
+			    column++ < browser->b.horiz_scroll)
 				continue;
 
 			if (current_entry && browser->b.navkeypressed) {
@@ -1144,7 +1145,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
 	}
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt)  || column++ < browser->b.horiz_scroll)
+		if (perf_hpp__should_skip(fmt, hists)  || column++ < browser->b.horiz_scroll)
 			continue;
 
 		ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
@@ -1414,7 +1415,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
 		printed += fprintf(fp, "%c ", folded_sign);
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, he->hists))
 			continue;
 
 		if (!first) {
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 4677172..0f8dcfd 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -318,7 +318,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 	col_idx = 0;
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		/*
@@ -368,7 +368,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 		col_idx = 0;
 
 		perf_hpp__for_each_format(fmt) {
-			if (perf_hpp__should_skip(fmt))
+			if (perf_hpp__should_skip(fmt, h->hists))
 				continue;
 
 			if (fmt->color)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 5029ba2..8263c0e 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -619,7 +619,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
 	struct perf_hpp dummy_hpp;
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		if (first)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 7ebc661..387110d 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -385,7 +385,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
 		return 0;
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, he->hists))
 			continue;
 
 		/*
@@ -464,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 	fprintf(fp, "# ");
 
 	perf_hpp__for_each_format(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		if (!first)
@@ -490,7 +490,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 	perf_hpp__for_each_format(fmt) {
 		unsigned int i;
 
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, hists))
 			continue;
 
 		if (!first)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index fdb97e1..afc9b8f 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1112,7 +1112,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
 	int64_t cmp = 0;
 
 	perf_hpp__for_each_sort_list(fmt) {
-		if (perf_hpp__should_skip(fmt))
+		if (perf_hpp__should_skip(fmt, a->hists))
 			continue;
 
 		cmp = fmt->sort(fmt, a, b);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 15b22c5..cb8f373 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -262,10 +262,20 @@ void perf_hpp__append_sort_keys(void);
 
 bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format);
 bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
+bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format);
+bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists);
 
-static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
+static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
+					 struct hists *hists)
 {
-	return format->elide;
+	if (format->elide)
+		return true;
+
+	if (perf_hpp__is_dynamic_entry(format) &&
+	    !perf_hpp__defined_dynamic_entry(format, hists))
+		return true;
+
+	return false;
 }
 
 void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index f6aef15..fd56223 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1698,6 +1698,15 @@ static int __sort__hde_width(struct perf_hpp_fmt *fmt,
 	return len;
 }
 
+bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists)
+{
+	struct hpp_dynamic_entry *hde;
+
+	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+
+	return hists_to_evsel(hists) == hde->evsel;
+}
+
 static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 			     struct hist_entry *he)
 {
@@ -1714,9 +1723,6 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	if (!len)
 		len = hde_width(hde);
 
-	if (hists_to_evsel(he->hists) != hde->evsel)
-		return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, "N/A");
-
 	if (hde->raw_trace)
 		goto raw_field;
 
@@ -1769,9 +1775,6 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
 
 	hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
 
-	if (hists_to_evsel(a->hists) != hde->evsel)
-		return 0;
-
 	field = hde->field;
 	if (field->flags & FIELD_IS_DYNAMIC) {
 		unsigned long long dyn;
@@ -1794,6 +1797,11 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
 	return memcmp(a->raw_data + offset, b->raw_data + offset, size);
 }
 
+bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt)
+{
+	return fmt->cmp == __sort__hde_cmp;
+}
+
 static struct hpp_dynamic_entry *
 __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
 {

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Add 'trace_fields' dynamic sort key
  2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
                       ` (4 preceding siblings ...)
  2016-01-05 21:50     ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Arnaldo Carvalho de Melo
@ 2016-01-09 16:26     ` tip-bot for Namhyung Kim
  5 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, jolsa, mingo, linux-kernel, hpa, fweisbec, rostedt, andi,
	peterz, dsahern, namhyung, acme, wangnan0

Commit-ID:  2e422fd1e4b0a1c0ca11d360be2147c87911dd1a
Gitweb:     http://git.kernel.org/tip/2e422fd1e4b0a1c0ca11d360be2147c87911dd1a
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:09 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:13 -0300

perf tools: Add 'trace_fields' dynamic sort key

The 'trace_fields' sort key is similar as 'trace' sort key, but it shows
each fields separately.  Each event will get different columns as their
fields.

  $ perf report -s trace_fields --stdio
  # To display the perf.data header info, please use --header/--header-only options.
  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 20K of event 'kmem:kmalloc'
  # Event count (approx.): 20533
  #
  # Overhead  Command           call_site                 ptr  bytes_req  bytes_alloc            gfp_flags
  # ........  .......  ..................  ..................  .........  ...........  ...................
  #
      99.89%  perf       ffffffffa01d4396  0xffff8803ffb79720         96           96    GFP_NOFS|GFP_ZERO
       0.06%  sleep      ffffffff8114e1cd  0xffff8803d228a000       4096         4096           GFP_KERNEL
       0.03%  perf       ffffffff811d6ae6  0xffff8803f7678f00        240          256  GFP_KERNEL|GFP_ZERO
       0.00%  perf       ffffffff812263c1  0xffff880406172380        128          128           GFP_KERNEL
       0.00%  perf       ffffffff812264b9  0xffff8803ffac1600        504          512           GFP_KERNEL
       0.00%  perf       ffffffff81226634  0xffff880401dc5280         28           32           GFP_KERNEL
       0.00%  sleep      ffffffff81226da9  0xffff8803ffac3a00        392          512           GFP_KERNEL

  # Samples: 20K of event 'kmem:kfree'
  # Event count (approx.): 20597
  #
  # Overhead           call_site                 ptr
  # ........  ..................  ..................
  #
      99.58%    ffffffffa01d85ad  0xffff8803ffb79720
       0.07%    ffffffff81443f5c  0xffff8803f7669400
       0.02%    ffffffff811d5753  0xffff8803f7678f00
       0.01%    ffffffff81443f5c  0xffff8803f766be00
       0.01%    ffffffff8114e359  0xffff8803d228a000
       0.01%    ffffffff81443f5c  0xffff8800d156dc00
       0.01%    ffffffff81443f5c  0xffff8803f7669400
       0.01%    ffffffff8114e359  0xffff8803d228a000
       0.01%    ffffffff8114e359  0xffff8803d228a000
       0.01%    ffffffff8114e359  0xffff8803d228a000

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo 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-13-git-send-email-namhyung@kernel.org
[ Combined with "perf tools: Fix segfault when using -s trace_fields" ]
Link: http://lkml.kernel.org/r/1451991518-25673-1-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/sort.c | 47 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index fd56223..79aa71d 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1932,6 +1932,38 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
 	return 0;
 }
 
+static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
+{
+	int ret;
+	struct format_field *field;
+
+	field = evsel->tp_format->format.fields;
+	while (field) {
+		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+		if (ret < 0)
+			return ret;
+
+		field = field->next;
+	}
+	return 0;
+}
+
+static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
+{
+	int ret;
+	struct perf_evsel *evsel;
+
+	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+			continue;
+
+		ret = add_evsel_fields(evsel, raw_trace);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
 	char *str, *event_name, *field_name, *opt_name;
@@ -1961,6 +1993,11 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 		raw_trace = true;
 	}
 
+	if (!strcmp(field_name, "trace_fields")) {
+		ret = add_all_dynamic_fields(evlist, raw_trace);
+		goto out;
+	}
+
 	evsel = find_evsel(evlist, event_name);
 	if (evsel == NULL) {
 		pr_debug("Cannot find event: %s\n", event_name);
@@ -1975,15 +2012,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	}
 
 	if (!strcmp(field_name, "*")) {
-		field = evsel->tp_format->format.fields;
-
-		while (field) {
-			ret = __dynamic_dimension__add(evsel, field, raw_trace);
-			if (ret < 0)
-				goto out;
-
-			field = field->next;
-		}
+		ret = add_evsel_fields(evsel, raw_trace);
 	} else {
 		field = pevent_find_any_field(evsel->tp_format, field_name);
 		if (field == NULL) {

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events
  2015-12-22 17:07 ` [PATCH 13/13] perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events Namhyung Kim
@ 2016-01-09 16:26   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, wangnan0, dsahern, linux-kernel, andi, rostedt, peterz,
	tglx, mingo, fweisbec, acme, namhyung, hpa

Commit-ID:  d49dadea78624353d1df660efb49f187bd5c5971
Gitweb:     http://git.kernel.org/tip/d49dadea78624353d1df660efb49f187bd5c5971
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed, 23 Dec 2015 02:07:10 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:13 -0300

perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events

When an evlist contains tracepoint events only, use 'trace' sort key as
default.  If --raw-trace option was given, use 'trace_fields' instead.
This will make users more convenient to see trace result.

Suggested-and-Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo 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-14-git-send-email-namhyung@kernel.org
[ Check evlist in get_default_sort_order() fixing a segfault in 'perf test hists' reported by Jiri Olsa ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/sort.c | 30 +++++++++++++++++++++++++-----
 tools/perf/util/sort.h |  1 +
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 79aa71d..4b4b1c5 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -15,6 +15,7 @@ const char	default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cy
 const char	default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
 const char	default_top_sort_order[] = "dso,symbol";
 const char	default_diff_sort_order[] = "dso,symbol";
+const char	default_tracepoint_sort_order[] = "trace";
 const char	*sort_order;
 const char	*field_order;
 regex_t		ignore_callees_regex;
@@ -2171,7 +2172,7 @@ static int sort_dimension__add(const char *tok,
 	return -ESRCH;
 }
 
-static const char *get_default_sort_order(void)
+static const char *get_default_sort_order(struct perf_evlist *evlist)
 {
 	const char *default_sort_orders[] = {
 		default_sort_order,
@@ -2179,14 +2180,33 @@ static const char *get_default_sort_order(void)
 		default_mem_sort_order,
 		default_top_sort_order,
 		default_diff_sort_order,
+		default_tracepoint_sort_order,
 	};
+	bool use_trace = true;
+	struct perf_evsel *evsel;
 
 	BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
 
+	if (evlist == NULL)
+		goto out_no_evlist;
+
+	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+			use_trace = false;
+			break;
+		}
+	}
+
+	if (use_trace) {
+		sort__mode = SORT_MODE__TRACEPOINT;
+		if (symbol_conf.raw_trace)
+			return "trace_fields";
+	}
+out_no_evlist:
 	return default_sort_orders[sort__mode];
 }
 
-static int setup_sort_order(void)
+static int setup_sort_order(struct perf_evlist *evlist)
 {
 	char *new_sort_order;
 
@@ -2207,7 +2227,7 @@ static int setup_sort_order(void)
 	 * because it's checked over the rest of the code.
 	 */
 	if (asprintf(&new_sort_order, "%s,%s",
-		     get_default_sort_order(), sort_order + 1) < 0) {
+		     get_default_sort_order(evlist), sort_order + 1) < 0) {
 		error("Not enough memory to set up --sort");
 		return -ENOMEM;
 	}
@@ -2222,7 +2242,7 @@ static int __setup_sorting(struct perf_evlist *evlist)
 	const char *sort_keys;
 	int ret = 0;
 
-	ret = setup_sort_order();
+	ret = setup_sort_order(evlist);
 	if (ret)
 		return ret;
 
@@ -2236,7 +2256,7 @@ static int __setup_sorting(struct perf_evlist *evlist)
 			return 0;
 		}
 
-		sort_keys = get_default_sort_order();
+		sort_keys = get_default_sort_order(evlist);
 	}
 
 	str = strdup(sort_keys);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 6b7590a..dec536b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -167,6 +167,7 @@ enum sort_mode {
 	SORT_MODE__MEMORY,
 	SORT_MODE__TOP,
 	SORT_MODE__DIFF,
+	SORT_MODE__TRACEPOINT,
 };
 
 enum sort_type {

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf tools: Add all matching dynamic sort keys for field name
  2016-01-05 10:58     ` [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name Namhyung Kim
  2016-01-05 14:20       ` Jiri Olsa
@ 2016-01-09 16:28       ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, jolsa, hpa, tglx, linux-kernel, namhyung, andi, wangnan0,
	mingo, dsahern, rostedt, fweisbec, acme

Commit-ID:  9735be24ec086fbccee321471cc21dedefa956a6
Gitweb:     http://git.kernel.org/tip/9735be24ec086fbccee321471cc21dedefa956a6
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 5 Jan 2016 19:58:35 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:14 -0300

perf tools: Add all matching dynamic sort keys for field name

When a perf.data file has multiple events, it's likely to be similar
(tracepoint) events.  In that case, they might have same field name so
add all of them to sort keys instead of bailing out.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
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/1451991518-25673-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/sort.c | 48 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 4b4b1c5..04e2a5c 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1863,10 +1863,9 @@ static int parse_field_name(char *str, char **event, char **field, char **opt)
 }
 
 /* find match evsel using a given event name.  The event name can be:
- *   1. NULL - only valid for single event session
- *   2. '%' + event index (e.g. '%1' for first event)
- *   3. full event name (e.g. sched:sched_switch)
- *   4. partial event name (should not contain ':')
+ *   1. '%' + event index (e.g. '%1' for first event)
+ *   2. full event name (e.g. sched:sched_switch)
+ *   3. partial event name (should not contain ':')
  */
 static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
 {
@@ -1875,16 +1874,6 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 	bool full_name;
 
 	/* case 1 */
-	if (event_name == NULL) {
-		if (evlist->nr_entries != 1) {
-			pr_debug("event name should be given\n");
-			return NULL;
-		}
-
-		return perf_evlist__first(evlist);
-	}
-
-	/* case 2 */
 	if (event_name[0] == '%') {
 		int nr = strtol(event_name+1, NULL, 0);
 
@@ -1900,10 +1889,10 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 
 	full_name = !!strchr(event_name, ':');
 	evlist__for_each(evlist, pos) {
-		/* case 3 */
+		/* case 2 */
 		if (full_name && !strcmp(pos->name, event_name))
 			return pos;
-		/* case 4 */
+		/* case 3 */
 		if (!full_name && strstr(pos->name, event_name)) {
 			if (evsel) {
 				pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
@@ -1965,6 +1954,28 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
 	return 0;
 }
 
+static int add_all_matching_fields(struct perf_evlist *evlist,
+				   char *field_name, bool raw_trace)
+{
+	int ret = -ESRCH;
+	struct perf_evsel *evsel;
+	struct format_field *field;
+
+	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+			continue;
+
+		field = pevent_find_any_field(evsel->tp_format, field_name);
+		if (field == NULL)
+			continue;
+
+		ret = __dynamic_dimension__add(evsel, field, raw_trace);
+		if (ret < 0)
+			break;
+	}
+	return ret;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
 	char *str, *event_name, *field_name, *opt_name;
@@ -1999,6 +2010,11 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 		goto out;
 	}
 
+	if (event_name == NULL) {
+		ret = add_all_matching_fields(evlist, field_name, raw_trace);
+		goto out;
+	}
+
 	evsel = find_evsel(evlist, event_name);
 	if (evsel == NULL) {
 		pr_debug("Cannot find event: %s\n", event_name);

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip:perf/core] perf report: Add documentation for dynamic sort keys
  2016-01-05 10:58     ` [PATCH v2 3/5] perf tools: Add document for dynamic sort keys Namhyung Kim
@ 2016-01-09 16:28       ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot for Namhyung Kim @ 2016-01-09 16:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, rostedt, jolsa, hpa, dsahern, linux-kernel, tglx, peterz,
	fweisbec, namhyung, mingo, wangnan0, andi

Commit-ID:  4c96bee03247c6eab27287fa66457a231b9fab79
Gitweb:     http://git.kernel.org/tip/4c96bee03247c6eab27287fa66457a231b9fab79
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 5 Jan 2016 19:58:36 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 6 Jan 2016 20:11:14 -0300

perf report: Add documentation for dynamic sort keys

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
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/1451991518-25673-3-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-report.txt | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index ae7cd91..8a301f6 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -117,6 +117,30 @@ OPTIONS
 	And default sort keys are changed to comm, dso_from, symbol_from, dso_to
 	and symbol_to, see '--branch-stack'.
 
+	If the data file has tracepoint event(s), following (dynamic) sort keys
+	are also available:
+	trace, trace_fields, [<event>.]<field>[/raw]
+
+	- trace: pretty printed trace output in a single column
+	- trace_fields: fields in tracepoints in separate columns
+	- <field name>: optional event and field name for a specific field
+
+	The last form consists of event and field names.  If event name is
+	omitted, it searches all events for matching field name.  The matched
+	field will be shown only for the event has the field.  The event name
+	supports substring match so user doesn't need to specify full subsystem
+	and event name everytime.  For example, 'sched:sched_switch' event can
+	be shortened to 'switch' as long as it's not ambiguous.  Also event can
+	be specified by its index (starting from 1) preceded by the '%'.
+	So '%1' is the first event, '%2' is the second, and so on.
+
+	The field name can have '/raw' suffix which disables pretty printing
+	and shows raw field value like hex numbers.  The --raw-trace option
+	has the same effect for all dynamic sort keys.
+
+	The default sort keys are changed to 'trace' if all events in the data
+	file are tracepoint.
+
 -F::
 --fields=::
 	Specify output field - multiple keys can be specified in CSV format.

^ permalink raw reply related	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2016-01-09 16:29 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-22 17:06 [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Namhyung Kim
2015-12-22 17:06 ` [PATCH 01/13] perf hist: Pass struct sample to __hists__add_entry() Namhyung Kim
2016-01-09 16:22   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-22 17:06 ` [PATCH 02/13] perf hist: Save raw_data/size for tracepoint events Namhyung Kim
2015-12-23 21:43   ` Arnaldo Carvalho de Melo
2015-12-24  0:45     ` Namhyung Kim
2015-12-24  1:19       ` Arnaldo Carvalho de Melo
2015-12-24  1:05     ` [PATCH v4.1 " Namhyung Kim
2015-12-24  1:39       ` Arnaldo Carvalho de Melo
2015-12-24  2:16         ` [PATCH v4.2 " Namhyung Kim
2016-01-09 16:22           ` [tip:perf/core] perf hist: Save raw_data/ size " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 03/13] tools lib traceevent: Factor out and export print_event_field[s] Namhyung Kim
2015-12-23  8:50   ` Wangnan (F)
2015-12-23 13:08   ` [PATCH v4.1 " Namhyung Kim
2016-01-04 15:31     ` Steven Rostedt
2016-01-04 18:34       ` Arnaldo Carvalho de Melo
2016-01-09 16:22     ` [tip:perf/core] tools lib traceevent: Factor out and export print_event_field[s]() tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 04/13] perf tools: Pass evlist to setup_sorting() Namhyung Kim
2016-01-09 16:23   ` [tip:perf/core] perf top: Create the evlist sooner tip-bot for Namhyung Kim
2016-01-09 16:23   ` [tip:perf/core] perf tools: Pass evlist to setup_sorting() tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 05/13] perf tools: Add dynamic sort key for tracepoint events Namhyung Kim
2016-01-04 15:04   ` Arnaldo Carvalho de Melo
2016-01-09 16:23   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 06/13] perf tools: Try to show pretty printed output for dynamic sort keys Namhyung Kim
2016-01-04 15:16   ` Arnaldo Carvalho de Melo
2016-01-09 16:24   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 07/13] perf tools: Add 'trace' sort key Namhyung Kim
2016-01-09 16:24   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 08/13] perf tools: Add --raw-trace option Namhyung Kim
2016-01-09 16:24   ` [tip:perf/core] perf report/top: " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 09/13] perf tools: Support shortcuts for events in dynamic sort keys Namhyung Kim
2016-01-09 16:25   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 10/13] perf tools: Support '<event>.*' dynamic sort key Namhyung Kim
2016-01-09 16:25   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 11/13] perf tools: Skip dynamic fields not defined for current event Namhyung Kim
2016-01-09 16:25   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 12/13] perf tools: Add 'trace_fields' dynamic sort key Namhyung Kim
2016-01-05 10:58   ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Namhyung Kim
2016-01-05 10:58     ` [PATCH v2 2/5] perf tools: Add all matching dynamic sort keys for field name Namhyung Kim
2016-01-05 14:20       ` Jiri Olsa
2016-01-09 16:28       ` [tip:perf/core] " tip-bot for Namhyung Kim
2016-01-05 10:58     ` [PATCH v2 3/5] perf tools: Add document for dynamic sort keys Namhyung Kim
2016-01-09 16:28       ` [tip:perf/core] perf report: Add documentation " tip-bot for Namhyung Kim
2016-01-05 10:58     ` [PATCH v2 4/5] perf tools: Support dynamic sort keys for -F/--fields Namhyung Kim
2016-01-05 22:16       ` Arnaldo Carvalho de Melo
2016-01-05 23:57         ` Namhyung Kim
2016-01-05 10:58     ` [PATCH v2 5/5] perf evlist: Add -T/--trace option to show trace fields Namhyung Kim
2016-01-05 22:23       ` Arnaldo Carvalho de Melo
2016-01-06  0:00         ` Namhyung Kim
2016-01-06  1:52           ` Arnaldo Carvalho de Melo
2016-01-05 21:50     ` [PATCH v2 1/5] perf tools: Fix segfault when using -s trace_fields Arnaldo Carvalho de Melo
2016-01-05 23:39       ` Namhyung Kim
2016-01-09 16:26     ` [tip:perf/core] perf tools: Add 'trace_fields' dynamic sort key tip-bot for Namhyung Kim
2015-12-22 17:07 ` [PATCH 13/13] perf tools: Make 'trace' or 'trace_fields' sort key default for tracepoint events Namhyung Kim
2016-01-09 16:26   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-23  8:46 ` [PATCHSET 00/10] perf tools: Support dynamic sort keys for tracepoints (v4) Jiri Olsa
2015-12-23 13:10   ` Namhyung Kim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.