linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv3 00/56] perf stat: Add scripting support
@ 2015-10-06 19:54 Jiri Olsa
  2015-10-06 19:54 ` [PATCH 01/56] perf tools: Add thread_map event Jiri Olsa
                   ` (56 more replies)
  0 siblings, 57 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Andi Kleen, Ulrich Drepper, Will Deacon, Stephane Eranian,
	Don Zickus, lkml, David Ahern, Ingo Molnar, Namhyung Kim,
	Peter Zijlstra, Liang, Kan

hi,
sending another version of stat scripting.

v3 changes:
  - added attr update event to handle unit,scale,name for event
    it fixed the uncore_imc_1/cas_count_read/ record/report
  - perf report -D now displays stat related events
  - some minor and changelog fixes

v2 changes:
  - rebased to latest Arnaldo's perf/core
  - patches 1 to 11 already merged in
  - added --per-core/--per-socket/-A options for perf stat report
    command to allow custom aggregation in stat report, please
    check new examples below
  - couple changelogs changes

The initial attempt defined its own formula lang and allowed
triggering user's script on the end of the stat command:
  http://marc.info/?l=linux-kernel&m=136742146322273&w=2

This patchset abandons the idea of new formula language
and rather adds support to:
  - store stat data into perf.data file
  - add python support to process stat events

Basically it allows to store stat data into perf.data and
post process it with python scripts in a similar way we
do for sampling data.

The stat data are stored in new stat, stat-round, stat-config user events.
  stat        - stored for each read syscall of the counter
  stat round  - stored for each interval or end of the command invocation
  stat config - stores all the config information needed to process data
                so report tool could restore the same output as record

The python script can now define 'stat__<eventname>_<modifier>' functions
to get stat events data and 'stat__interval' to get stat-round data.

See CPI script example in scripts/python/stat-cpi.py.

Also available in:
  git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
  perf/stat_script

thanks,
jirka


Examples:

- To record data for command stat workload:

  $ perf stat record kill
  ...

   Performance counter stats for 'kill':

            0.372007      task-clock (msec)         #    0.613 CPUs utilized          
                   3      context-switches          #    0.008 M/sec                  
                   0      cpu-migrations            #    0.000 K/sec                  
                  62      page-faults               #    0.167 M/sec                  
           1,129,973      cycles                    #    3.038 GHz                    
     <not supported>      stalled-cycles-frontend  
     <not supported>      stalled-cycles-backend   
             813,313      instructions              #    0.72  insns per cycle        
             166,161      branches                  #  446.661 M/sec                  
               8,747      branch-misses             #    5.26% of all branches        

         0.000607287 seconds time elapsed

- To report perf stat data:

  $ perf stat report

   Performance counter stats for '/home/jolsa/bin/perf stat record kill':

            0.372007      task-clock (msec)         #      inf CPUs utilized          
                   3      context-switches          #    0.008 M/sec                  
                   0      cpu-migrations            #    0.000 K/sec                  
                  62      page-faults               #    0.167 M/sec                  
           1,129,973      cycles                    #    3.038 GHz                    
     <not supported>      stalled-cycles-frontend  
     <not supported>      stalled-cycles-backend   
             813,313      instructions              #    0.72  insns per cycle        
             166,161      branches                  #  446.661 M/sec                  
               8,747      branch-misses             #    5.26% of all branches        

         0.000000000 seconds time elapsed

- To store system-wide period stat data:

  $ perf stat -e cycles:u,instructions:u -a -I 1000 record
  #           time             counts unit events
       1.000265471        462,311,482      cycles:u                   (100.00%)
       1.000265471        590,037,440      instructions:u           
       2.000483453        722,532,336      cycles:u                   (100.00%)
       2.000483453        848,678,197      instructions:u           
       3.000759876         75,990,880      cycles:u                   (100.00%)
       3.000759876         86,187,813      instructions:u           
  ^C     3.213960893         85,329,533      cycles:u                   (100.00%)
       3.213960893        135,954,296      instructions:u           

- To report perf stat data:

  $ perf stat report
  #           time             counts unit events
       1.000265471        462,311,482      cycles:u                   (100.00%)
       1.000265471        590,037,440      instructions:u           
       2.000483453        722,532,336      cycles:u                   (100.00%)
       2.000483453        848,678,197      instructions:u           
       3.000759876         75,990,880      cycles:u                   (100.00%)
       3.000759876         86,187,813      instructions:u           
       3.213960893         85,329,533      cycles:u                   (100.00%)
       3.213960893        135,954,296      instructions:u           

- To run stat-cpi.py script over perf.data:

  $ perf script -s scripts/python/stat-cpi.py 
         1.000265: cpu -1, thread -1 -> cpi 0.783529 (462311482/590037440)
         2.000483: cpu -1, thread -1 -> cpi 0.851362 (722532336/848678197)
         3.000760: cpu -1, thread -1 -> cpi 0.881689 (75990880/86187813)
         3.213961: cpu -1, thread -1 -> cpi 0.627634 (85329533/135954296)

- To pipe data from stat to stat-cpi script:

  $ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf script -s scripts/python/stat-cpi.py 
         1.000192: cpu 0, thread -1 -> cpi 0.739535 (23921908/32347236)
         2.000376: cpu 0, thread -1 -> cpi 1.663482 (2519340/1514498)
         3.000621: cpu 0, thread -1 -> cpi 1.396308 (16162767/11575362)
         4.000700: cpu 0, thread -1 -> cpi 1.092246 (20077258/18381624)
         5.000867: cpu 0, thread -1 -> cpi 0.473816 (45157586/95306156)
         6.001034: cpu 0, thread -1 -> cpi 0.532792 (43701668/82023818)
         7.001195: cpu 0, thread -1 -> cpi 1.122059 (29890042/26638561)

- Raw script stat data output:

  $ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf --no-pager script
  CPU   THREAD             VAL             ENA             RUN            TIME EVENT
    0       -1        12302059      1000811347      1000810712      1000198821 cycles:u
    0       -1         2565362      1000823218      1000823218      1000198821 instructions:u
    0       -1        14453353      1000812704      1000812704      2000382283 cycles:u
    0       -1         4600932      1000799342      1000799342      2000382283 instructions:u
    0       -1        15245106      1000774425      1000774425      3000538255 cycles:u
    0       -1         2624324      1000769310      1000769310      3000538255 instructions:u

- To display different aggregation in report:

  $ perf stat -e cycles -a -I 1000 record sleep 3 
  #           time             counts unit events
       1.000223609        703,427,617      cycles                   
       2.000443651        609,975,307      cycles                   
       3.000569616        668,479,597      cycles                   
       3.000735323          1,155,816      cycles                 

  $ perf stat report
  #           time             counts unit events
       1.000223609        703,427,617      cycles                   
       2.000443651        609,975,307      cycles                   
       3.000569616        668,479,597      cycles                   
       3.000735323          1,155,816      cycles                   

  $ perf stat report --per-core
  #           time core         cpus             counts unit events
       1.000223609 S0-C0           2        327,612,412      cycles                   
       1.000223609 S0-C1           2        375,815,205      cycles                   
       2.000443651 S0-C0           2        287,462,177      cycles                   
       2.000443651 S0-C1           2        322,513,130      cycles                   
       3.000569616 S0-C0           2        271,571,908      cycles                   
       3.000569616 S0-C1           2        396,907,689      cycles                   
       3.000735323 S0-C0           2            694,977      cycles                   
       3.000735323 S0-C1           2            460,839      cycles                   

  $ perf stat report --per-socket
  #           time socket cpus             counts unit events
       1.000223609 S0        4        703,427,617      cycles                   
       2.000443651 S0        4        609,975,307      cycles                   
       3.000569616 S0        4        668,479,597      cycles                   
       3.000735323 S0        4          1,155,816      cycles                   

  $ perf stat report -A
  #           time CPU                counts unit events
       1.000223609 CPU0           205,431,505      cycles                   
       1.000223609 CPU1           122,180,907      cycles                   
       1.000223609 CPU2           176,649,682      cycles                   
       1.000223609 CPU3           199,165,523      cycles                   
       2.000443651 CPU0           148,447,922      cycles                   
       2.000443651 CPU1           139,014,255      cycles                   
       2.000443651 CPU2           204,436,559      cycles                   
       2.000443651 CPU3           118,076,571      cycles                   
       3.000569616 CPU0           149,788,954      cycles                   
       3.000569616 CPU1           121,782,954      cycles                   
       3.000569616 CPU2           247,277,700      cycles                   
       3.000569616 CPU3           149,629,989      cycles                   
       3.000735323 CPU0               269,675      cycles                   
       3.000735323 CPU1               425,302      cycles                   
       3.000735323 CPU2               364,169      cycles                   
       3.000735323 CPU3                96,670      cycles                   


Cc: Andi Kleen <andi@firstfloor.org>
Cc: Ulrich Drepper <drepper@gmail.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Don Zickus <dzickus@redhat.com>
---
Jiri Olsa (56):
      perf tools: Add thread_map event
      perf tools: Add thread_map event sythesize function
      perf tools: Add thread_map__new_event function
      perf tools: Add perf_event__fprintf_thread_map function
      perf tools: Add cpu_map event
      perf tools: Add cpu_map event synthesize function
      perf tools: Add cpu_map__new_event function
      perf tools: Add perf_event__fprintf_cpu_map function
      perf tools: Add stat config event
      perf tools: Add stat config event synthesize function
      perf tools: Add stat config event read function
      perf tools: Add stat event
      perf tools: Add stat event synthesize function
      perf tools: Add stat event read function
      perf tools: Add stat round event
      perf tools: Add stat round event synthesize function
      perf tools: Add stat events fprintf functions
      perf tools: Add attr_update event
      perf tools: Add attr_update event unit type
      perf tools: Add attr_update event scale type
      perf tools: Add attr_update event name type
      perf tools: Add perf_event__fprintf_attr_update function
      perf report: Display newly added events in raw dump
      perf tools: Introduce stat feature
      perf tools: Move id_offset out of struct perf_evsel union
      perf stat: Rename perf_stat struct into perf_stat_evsel
      perf stat: Add AGGR_UNSET mode
      perf stat record: Add record command
      perf stat record: Initialize record features
      perf stat record: Synthesize stat record data
      perf stat record: Store events IDs in perf data file
      perf stat record: Add pipe support for record command
      perf stat record: Write stat events on record
      perf stat record: Write stat round events on record
      perf stat record: Do not allow record with multiple runs mode
      perf stat record: Synthesize attr update events
      perf tools: Add cpu_map__empty_new interface
      perf tools: Make cpu_map__build_map global
      perf tools: Add data arg to cpu_map__build_map callback
      perf stat report: Cache aggregated map entries in extra cpumap
      perf stat report: Add report command
      perf stat report: Process cpu/threads maps
      perf stat report: Process stat config event
      perf stat report: Add support to initialize aggr_map from file
      perf stat report: Process stat and stat round events
      perf stat report: Process attr update events
      perf stat report: Move csv_sep initialization before report command
      perf stat report: Allow to override aggr_mode
      perf script: Check output fields only for samples
      perf script: Process cpu/threads maps
      perf script: Process stat config event
      perf script: Add process_stat/process_stat_interval scripting interface
      perf script: Add stat default handlers
      perf script: Display stat events by default
      perf script: Add python support for stat events
      perf script: Add stat-cpi.py script

 tools/perf/Documentation/perf-stat.txt             |  34 ++
 tools/perf/builtin-record.c                        |   2 +
 tools/perf/builtin-script.c                        | 144 ++++-
 tools/perf/builtin-stat.c                          | 636 ++++++++++++++++++++-
 tools/perf/scripts/python/stat-cpi.py              |  74 +++
 tools/perf/tests/Build                             |   3 +
 tools/perf/tests/attr_update.c                     |  82 +++
 tools/perf/tests/builtin-test.c                    |  25 +
 tools/perf/tests/cpumap.c                          |  39 ++
 tools/perf/tests/stat.c                            | 111 ++++
 tools/perf/tests/tests.h                           |   7 +
 tools/perf/tests/thread-map.c                      |  43 ++
 tools/perf/tests/topology.c                        |   4 +-
 tools/perf/util/cpumap.c                           |  61 +-
 tools/perf/util/cpumap.h                           |  11 +-
 tools/perf/util/event.c                            | 205 +++++++
 tools/perf/util/event.h                            | 122 +++-
 tools/perf/util/evlist.c                           |   6 +-
 tools/perf/util/evlist.h                           |   3 +
 tools/perf/util/evsel.h                            |   2 +-
 tools/perf/util/header.c                           | 146 +++++
 tools/perf/util/header.h                           |  14 +
 .../util/scripting-engines/trace-event-python.c    | 114 +++-
 tools/perf/util/session.c                          | 163 ++++++
 tools/perf/util/stat.c                             |  75 ++-
 tools/perf/util/stat.h                             |  13 +-
 tools/perf/util/thread_map.c                       |  27 +
 tools/perf/util/thread_map.h                       |   3 +
 tools/perf/util/tool.h                             |   8 +-
 tools/perf/util/trace-event.h                      |   4 +
 30 files changed, 2132 insertions(+), 49 deletions(-)
 create mode 100644 tools/perf/scripts/python/stat-cpi.py
 create mode 100644 tools/perf/tests/attr_update.c
 create mode 100644 tools/perf/tests/cpumap.c
 create mode 100644 tools/perf/tests/stat.c

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

* [PATCH 01/56] perf tools: Add thread_map event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 02/56] perf tools: Add thread_map event sythesize function Jiri Olsa
                   ` (55 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding thread_map event to pass/store thread maps
as data in pipe/perf.data.

Storing thread ID along with the standard comm[16]
thread name string.

Link: http://lkml.kernel.org/n/tip-2l07qyf3buhnt83q4ezqz5sj@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 13 +++++++++++++
 tools/perf/util/session.c | 26 ++++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8b10621b415c..771545a27b9b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -37,6 +37,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE_INFO]		= "AUXTRACE_INFO",
 	[PERF_RECORD_AUXTRACE]			= "AUXTRACE",
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
+	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index a0dbcbd4f6d8..f075f9ed0051 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -226,6 +226,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE_INFO		= 70,
 	PERF_RECORD_AUXTRACE			= 71,
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
+	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -356,6 +357,17 @@ struct context_switch_event {
 	u32 next_prev_tid;
 };
 
+struct thread_map_data_event {
+	u64	pid;
+	char	comm[16];
+};
+
+struct thread_map_event {
+	struct perf_event_header	header;
+	u64				nr;
+	struct thread_map_data_event	data[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -378,6 +390,7 @@ union perf_event {
 	struct aux_event		aux;
 	struct itrace_start_event	itrace_start;
 	struct context_switch_event	context_switch;
+	struct thread_map_event		thread_map;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 428149bc64d2..ec1ecd31003b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -296,6 +296,16 @@ int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+
+static
+int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
+				  union perf_event *event __maybe_unused,
+				  struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -346,6 +356,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->auxtrace = process_event_auxtrace_stub;
 	if (tool->auxtrace_error == NULL)
 		tool->auxtrace_error = process_event_auxtrace_error_stub;
+	if (tool->thread_map == NULL)
+		tool->thread_map = process_event_thread_map_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -616,6 +628,17 @@ static void perf_event__auxtrace_error_swap(union perf_event *event,
 	event->auxtrace_error.ip   = bswap_64(event->auxtrace_error.ip);
 }
 
+static void perf_event__thread_map_swap(union perf_event *event,
+					bool sample_id_all __maybe_unused)
+{
+	unsigned i;
+
+	event->thread_map.nr = bswap_64(event->thread_map.nr);
+
+	for (i = 0; i < event->thread_map.nr; i++)
+		event->thread_map.data[i].pid = bswap_64(event->thread_map.data[i].pid);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -643,6 +666,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE_INFO]	  = perf_event__auxtrace_info_swap,
 	[PERF_RECORD_AUXTRACE]		  = perf_event__auxtrace_swap,
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
+	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1179,6 +1203,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 	case PERF_RECORD_AUXTRACE_ERROR:
 		perf_session__auxtrace_error_inc(session, event);
 		return tool->auxtrace_error(tool, event, session);
+	case PERF_RECORD_THREAD_MAP:
+		return tool->thread_map(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index cab8cc24831b..1af4774960c3 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -55,7 +55,8 @@ struct perf_tool {
 	event_op2	build_id,
 			id_index,
 			auxtrace_info,
-			auxtrace_error;
+			auxtrace_error,
+			thread_map;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 02/56] perf tools: Add thread_map event sythesize function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
  2015-10-06 19:54 ` [PATCH 01/56] perf tools: Add thread_map event Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 03/56] perf tools: Add thread_map__new_event function Jiri Olsa
                   ` (54 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introduce perf_event__synthesize_thread_map2 function to
synthesize struct thread_map.

The perf_event__synthesize_thread_map is already taken
for synthesizing complete threads data (comm/mmap/fork).

Link: http://lkml.kernel.org/n/tip-cykuf1v8qb6li8q6w6tbm05w@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/builtin-test.c |  5 +++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/tests/thread-map.c   | 29 +++++++++++++++++++++++++++++
 tools/perf/util/event.c         | 36 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  4 ++++
 5 files changed, 75 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 66f72d3d6677..9bbe1c39740e 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -158,6 +158,7 @@ static struct test generic_tests[] = {
 		.func = test__thread_map,
 	},
 	{
+
 		.desc = "Test LLVM searching and compiling",
 		.func = test__llvm,
 	},
@@ -166,6 +167,10 @@ static struct test generic_tests[] = {
 		.func = test_session_topology,
 	},
 	{
+		.desc = "Test thread map synthesize",
+		.func = test__thread_map_synthesize,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index c80486969f83..2e280a5cd579 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -67,6 +67,7 @@ int test__kmod_path__parse(void);
 int test__thread_map(void);
 int test__llvm(void);
 int test_session_topology(void);
+int test__thread_map_synthesize(void);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index 138a0e3431fa..0facd9fa3458 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -40,3 +40,32 @@ int test__thread_map(void)
 	thread_map__put(map);
 	return 0;
 }
+
+static int process_event(struct perf_tool *tool __maybe_unused,
+			 union perf_event *event,
+			 struct perf_sample *sample __maybe_unused,
+			 struct machine *machine __maybe_unused)
+{
+	struct thread_map_event *map = &event->thread_map;
+
+	TEST_ASSERT_VAL("wrong nr",   map->nr == 1);
+	TEST_ASSERT_VAL("wrong pid",  map->data[0].pid == (u64) getpid());
+	TEST_ASSERT_VAL("wrong comm", !strcmp(map->data[0].comm, "perf"));
+	return 0;
+}
+
+int test__thread_map_synthesize(void)
+{
+	struct thread_map *threads;
+
+	/* test map on current pid */
+	threads = thread_map__new_by_pid(getpid());
+	TEST_ASSERT_VAL("failed to alloc map", threads);
+
+	thread_map__read_comms(threads);
+
+	TEST_ASSERT_VAL("failed to synthesize map",
+		!perf_event__synthesize_thread_map2(NULL, threads, process_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 771545a27b9b..10e852201955 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -700,6 +700,42 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_thread_map2(struct perf_tool *tool,
+				      struct thread_map *threads,
+				      perf_event__handler_t process,
+				      struct machine *machine)
+{
+	union perf_event *event;
+	int i, err, size;
+
+	size  = sizeof(event->thread_map);
+	size +=	threads->nr * sizeof(event->thread_map.data[0]);
+
+	event = zalloc(size);
+	if (!event)
+		return -ENOMEM;
+
+	event->header.type = PERF_RECORD_THREAD_MAP;
+	event->header.size = size;
+	event->thread_map.nr = threads->nr;
+
+	for (i = 0; i < threads->nr; i++) {
+		struct thread_map_data_event *data = &event->thread_map.data[i];
+		char *comm = thread_map__comm(threads, i);
+
+		if (!comm)
+			comm = (char *) "";
+
+		data->pid = thread_map__pid(threads, i);
+		strncpy((char *) &data->comm, comm, sizeof(data->comm));
+	}
+
+	err = process(tool, event, NULL, machine);
+
+	free(event);
+	return err;
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index f075f9ed0051..3ef69fef4497 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -408,6 +408,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 				      perf_event__handler_t process,
 				      struct machine *machine, bool mmap_data,
 				      unsigned int proc_map_timeout);
+int perf_event__synthesize_thread_map2(struct perf_tool *tool,
+				      struct thread_map *threads,
+				      perf_event__handler_t process,
+				      struct machine *machine);
 int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine, bool mmap_data,
-- 
2.4.3


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

* [PATCH 03/56] perf tools: Add thread_map__new_event function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
  2015-10-06 19:54 ` [PATCH 01/56] perf tools: Add thread_map event Jiri Olsa
  2015-10-06 19:54 ` [PATCH 02/56] perf tools: Add thread_map event sythesize function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 04/56] perf tools: Add perf_event__fprintf_thread_map function Jiri Olsa
                   ` (53 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introducing thread_map__new_event function to create
struct thread_map object from thread_map event.

Link: http://lkml.kernel.org/n/tip-0gu5uv3g51p4mzul93bhh2yh@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/thread-map.c | 14 ++++++++++++++
 tools/perf/util/thread_map.c  | 27 +++++++++++++++++++++++++++
 tools/perf/util/thread_map.h  |  3 +++
 3 files changed, 44 insertions(+)

diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index 0facd9fa3458..da7b047d3ada 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -47,10 +47,24 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
 	struct thread_map_event *map = &event->thread_map;
+	struct thread_map *threads;
 
 	TEST_ASSERT_VAL("wrong nr",   map->nr == 1);
 	TEST_ASSERT_VAL("wrong pid",  map->data[0].pid == (u64) getpid());
 	TEST_ASSERT_VAL("wrong comm", !strcmp(map->data[0].comm, "perf"));
+
+	threads = thread_map__new_event(&event->thread_map);
+	TEST_ASSERT_VAL("failed to alloc map", threads);
+
+	TEST_ASSERT_VAL("wrong nr", threads->nr == 1);
+	TEST_ASSERT_VAL("wrong pid",
+			thread_map__pid(threads, 0) == getpid());
+	TEST_ASSERT_VAL("wrong comm",
+			thread_map__comm(threads, 0) &&
+			!strcmp(thread_map__comm(threads, 0), "perf"));
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&threads->refcnt) == 1);
+	thread_map__put(threads);
 	return 0;
 }
 
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 6ec3c5ca438f..04b8dc368cbb 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -13,6 +13,7 @@
 #include "thread_map.h"
 #include "util.h"
 #include "debug.h"
+#include "event.h"
 
 /* Skip "." and ".." directories */
 static int filter(const struct dirent *dir)
@@ -408,3 +409,29 @@ void thread_map__read_comms(struct thread_map *threads)
 	for (i = 0; i < threads->nr; ++i)
 		comm_init(threads, i);
 }
+
+static void thread_map__copy_event(struct thread_map *threads,
+				   struct thread_map_event *event)
+{
+	unsigned i;
+
+	threads->nr = (int) event->nr;
+
+	for (i = 0; i < event->nr; i++) {
+		thread_map__set_pid(threads, i, (pid_t) event->data[i].pid);
+		threads->map[i].comm = strndup(event->data[i].comm, 16);
+	}
+
+	atomic_set(&threads->refcnt, 1);
+}
+
+struct thread_map *thread_map__new_event(struct thread_map_event *event)
+{
+	struct thread_map *threads;
+
+	threads = thread_map__alloc(event->nr);
+	if (threads)
+		thread_map__copy_event(threads, event);
+
+	return threads;
+}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index af679d8a50f8..85e4c7c4fbde 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -16,11 +16,14 @@ struct thread_map {
 	struct thread_map_data map[];
 };
 
+struct thread_map_event;
+
 struct thread_map *thread_map__new_dummy(void);
 struct thread_map *thread_map__new_by_pid(pid_t pid);
 struct thread_map *thread_map__new_by_tid(pid_t tid);
 struct thread_map *thread_map__new_by_uid(uid_t uid);
 struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
+struct thread_map *thread_map__new_event(struct thread_map_event *event);
 
 struct thread_map *thread_map__get(struct thread_map *map);
 void thread_map__put(struct thread_map *map);
-- 
2.4.3


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

* [PATCH 04/56] perf tools: Add perf_event__fprintf_thread_map function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (2 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 03/56] perf tools: Add thread_map__new_event function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 05/56] perf tools: Add cpu_map event Jiri Olsa
                   ` (52 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

To display thread_map event for raw dump.

Link: http://lkml.kernel.org/n/tip-q60h5rhe4mmyvzkjst64ewhk@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c | 16 ++++++++++++++++
 tools/perf/util/event.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 10e852201955..ec2965b139a4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -820,6 +820,22 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
 		       event->mmap2.filename);
 }
 
+size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
+{
+	struct thread_map *threads = thread_map__new_event(&event->thread_map);
+	size_t ret;
+
+	ret = fprintf(fp, " nr: ");
+
+	if (threads)
+		ret += thread_map__fprintf(threads, fp);
+	else
+		ret += fprintf(fp, "failed to get threads from event\n");
+
+	thread_map__put(threads);
+	return ret;
+}
+
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
 			     struct perf_sample *sample,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 3ef69fef4497..75157f3b16fb 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -516,6 +516,7 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
 u64 kallsyms__get_function_start(const char *kallsyms_filename,
-- 
2.4.3


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

* [PATCH 05/56] perf tools: Add cpu_map event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (3 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 04/56] perf tools: Add perf_event__fprintf_thread_map function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 06/56] perf tools: Add cpu_map event synthesize function Jiri Olsa
                   ` (51 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding cpu_map event to pass/store cpu maps
as data in pipe/perf.data.

Link: http://lkml.kernel.org/n/tip-tomgwwohnuxvvalwu4znaa2o@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   |  8 ++++++++
 tools/perf/util/session.c | 25 +++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index ec2965b139a4..c05f4b036069 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -38,6 +38,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE]			= "AUXTRACE",
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
+	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 75157f3b16fb..84104cfaab87 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE			= 71,
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
 	PERF_RECORD_THREAD_MAP			= 73,
+	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -368,6 +369,12 @@ struct thread_map_event {
 	struct thread_map_data_event	data[];
 };
 
+struct cpu_map_event {
+	struct perf_event_header	header;
+	u64				nr;
+	u64				cpu[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -391,6 +398,7 @@ union perf_event {
 	struct itrace_start_event	itrace_start;
 	struct context_switch_event	context_switch;
 	struct thread_map_event		thread_map;
+	struct cpu_map_event		cpu_map;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ec1ecd31003b..735ecf84f977 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -306,6 +306,15 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static
+int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
+			       union perf_event *event __maybe_unused,
+			       struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -358,6 +367,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->auxtrace_error = process_event_auxtrace_error_stub;
 	if (tool->thread_map == NULL)
 		tool->thread_map = process_event_thread_map_stub;
+	if (tool->cpu_map == NULL)
+		tool->cpu_map = process_event_cpu_map_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -639,6 +650,17 @@ static void perf_event__thread_map_swap(union perf_event *event,
 		event->thread_map.data[i].pid = bswap_64(event->thread_map.data[i].pid);
 }
 
+static void perf_event__cpu_map_swap(union perf_event *event,
+				     bool sample_id_all __maybe_unused)
+{
+	unsigned i;
+
+	event->cpu_map.nr = bswap_64(event->cpu_map.nr);
+
+	for (i = 0; i < event->cpu_map.nr; i++)
+		event->cpu_map.cpu[i] = bswap_64(event->cpu_map.cpu[i]);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -667,6 +689,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE]		  = perf_event__auxtrace_swap,
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
+	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1205,6 +1228,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->auxtrace_error(tool, event, session);
 	case PERF_RECORD_THREAD_MAP:
 		return tool->thread_map(tool, event, session);
+	case PERF_RECORD_CPU_MAP:
+		return tool->cpu_map(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 1af4774960c3..9e5925c78519 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -56,7 +56,8 @@ struct perf_tool {
 			id_index,
 			auxtrace_info,
 			auxtrace_error,
-			thread_map;
+			thread_map,
+			cpu_map;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 06/56] perf tools: Add cpu_map event synthesize function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (4 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 05/56] perf tools: Add cpu_map event Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 07/56] perf tools: Add cpu_map__new_event function Jiri Olsa
                   ` (50 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introduce perf_event__synthesize_cpu_map function to
synthesize struct cpu_map.

Link: http://lkml.kernel.org/n/tip-miidn8vqsx3udu4ct8103v5f@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/Build          |  1 +
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/cpumap.c       | 29 +++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 28 ++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  5 +++++
 6 files changed, 68 insertions(+)
 create mode 100644 tools/perf/tests/cpumap.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 50de2253cff6..1c0296fc95ea 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -33,6 +33,7 @@ perf-y += kmod-path.o
 perf-y += thread-map.o
 perf-y += llvm.o
 perf-y += topology.o
+perf-y += cpumap.o
 
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 9bbe1c39740e..3b8b518d96f9 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -171,6 +171,10 @@ static struct test generic_tests[] = {
 		.func = test__thread_map_synthesize,
 	},
 	{
+		.desc = "Test cpu map synthesize",
+		.func = test__cpu_map_synthesize,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
new file mode 100644
index 000000000000..475c040f8a8d
--- /dev/null
+++ b/tools/perf/tests/cpumap.c
@@ -0,0 +1,29 @@
+#include "tests.h"
+#include "cpumap.h"
+
+static int process_event(struct perf_tool *tool __maybe_unused,
+			 union perf_event *event,
+			 struct perf_sample *sample __maybe_unused,
+			 struct machine *machine __maybe_unused)
+{
+	struct cpu_map_event *map = &event->cpu_map;
+
+	TEST_ASSERT_VAL("wrong nr",   map->nr == 3);
+	TEST_ASSERT_VAL("wrong cpu",  map->cpu[0] == 1);
+	TEST_ASSERT_VAL("wrong cpu",  map->cpu[1] == 2);
+	TEST_ASSERT_VAL("wrong cpu",  map->cpu[2] == 4);
+	return 0;
+}
+
+int test__cpu_map_synthesize(void)
+{
+	struct cpu_map *cpus;
+
+	cpus = cpu_map__new("1,2,4");
+
+
+	TEST_ASSERT_VAL("failed to synthesize map",
+		!perf_event__synthesize_cpu_map(NULL, cpus, process_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 2e280a5cd579..c7f3c3211bcf 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -68,6 +68,7 @@ int test__thread_map(void);
 int test__llvm(void);
 int test_session_topology(void);
 int test__thread_map_synthesize(void);
+int test__cpu_map_synthesize(void);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index c05f4b036069..eac52f12c5c4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -737,6 +737,34 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_cpu_map(struct perf_tool *tool,
+				   struct cpu_map *cpus,
+				   perf_event__handler_t process,
+				   struct machine *machine)
+{
+	union perf_event *event;
+	int i, err, size;
+
+	size  = sizeof(event->cpu_map);
+	size +=	cpus->nr * sizeof(event->cpu_map.cpu[0]);
+
+	event = zalloc(size);
+	if (!event)
+		return -ENOMEM;
+
+	event->header.type = PERF_RECORD_CPU_MAP;
+	event->header.size = size;
+	event->cpu_map.nr = cpus->nr;
+
+	for (i = 0; i < cpus->nr; i++)
+		event->cpu_map.cpu[i] = cpus->map[i];
+
+	err = process(tool, event, NULL, machine);
+
+	free(event);
+	return err;
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 84104cfaab87..e58a36b8ecbc 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -405,6 +405,7 @@ void perf_event__print_totals(void);
 
 struct perf_tool;
 struct thread_map;
+struct cpu_map;
 
 typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 				     union perf_event *event,
@@ -420,6 +421,10 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
 				      struct machine *machine);
+int perf_event__synthesize_cpu_map(struct perf_tool *tool,
+				   struct cpu_map *cpus,
+				   perf_event__handler_t process,
+				   struct machine *machine);
 int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine, bool mmap_data,
-- 
2.4.3


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

* [PATCH 07/56] perf tools: Add cpu_map__new_event function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (5 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 06/56] perf tools: Add cpu_map event synthesize function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 08/56] perf tools: Add perf_event__fprintf_cpu_map function Jiri Olsa
                   ` (49 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introducing cpu_map__new_event function to create
struct cpu_map object from cpu_map event.

Link: http://lkml.kernel.org/n/tip-tepv49tbjsqeprmf8k05lc6r@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/cpumap.c | 10 ++++++++++
 tools/perf/util/cpumap.c  | 27 +++++++++++++++++++++++++++
 tools/perf/util/cpumap.h  |  3 +++
 3 files changed, 40 insertions(+)

diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index 475c040f8a8d..af8a3f520a2a 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -7,11 +7,21 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
 	struct cpu_map_event *map = &event->cpu_map;
+	struct cpu_map *cpus;
 
 	TEST_ASSERT_VAL("wrong nr",   map->nr == 3);
 	TEST_ASSERT_VAL("wrong cpu",  map->cpu[0] == 1);
 	TEST_ASSERT_VAL("wrong cpu",  map->cpu[1] == 2);
 	TEST_ASSERT_VAL("wrong cpu",  map->cpu[2] == 4);
+
+	cpus = cpu_map__new_event(&event->cpu_map);
+	TEST_ASSERT_VAL("wrong nr",  cpus->nr == 3);
+	TEST_ASSERT_VAL("wrong cpu", cpus->map[0] == 1);
+	TEST_ASSERT_VAL("wrong cpu", cpus->map[1] == 2);
+	TEST_ASSERT_VAL("wrong cpu", cpus->map[2] == 4);
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&cpus->refcnt) == 1);
+	cpu_map__put(cpus);
 	return 0;
 }
 
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index c51c29fd0732..e44849ad2c9c 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -179,6 +179,33 @@ out:
 	return cpus;
 }
 
+static void cpu_map__copy_event(struct cpu_map *cpus,
+				struct cpu_map_event *event)
+{
+	unsigned i;
+
+	cpus->nr = event->nr;
+
+	for (i = 0; i < event->nr; i++)
+		cpus->map[i] = (int) event->cpu[i];
+
+	atomic_set(&cpus->refcnt, 1);
+}
+
+struct cpu_map *cpu_map__new_event(struct cpu_map_event *event)
+{
+	struct cpu_map *cpus;
+	int size;
+
+	size = sizeof(cpus) + (event->nr * sizeof(cpus->map[0]));
+
+	cpus = zalloc(size);
+	if (cpus)
+		cpu_map__copy_event(cpus, event);
+
+	return cpus;
+}
+
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
 {
 	int i;
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 8982d538da83..c5b28dd18f6b 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -14,8 +14,11 @@ struct cpu_map {
 	int map[];
 };
 
+struct cpu_map_event;
+
 struct cpu_map *cpu_map__new(const char *cpu_list);
 struct cpu_map *cpu_map__dummy_new(void);
+struct cpu_map *cpu_map__new_event(struct cpu_map_event *event);
 struct cpu_map *cpu_map__read(FILE *file);
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
 int cpu_map__get_socket_id(int cpu);
-- 
2.4.3


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

* [PATCH 08/56] perf tools: Add perf_event__fprintf_cpu_map function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (6 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 07/56] perf tools: Add cpu_map__new_event function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 09/56] perf tools: Add stat config event Jiri Olsa
                   ` (48 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

To display cpu_map event for raw dump.

Link: http://lkml.kernel.org/n/tip-3uv795xlylejtbkf76om5rb5@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c | 16 ++++++++++++++++
 tools/perf/util/event.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index eac52f12c5c4..d55e5a5ca757 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -865,6 +865,22 @@ size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
 	return ret;
 }
 
+size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
+{
+	struct cpu_map *cpus = cpu_map__new_event(&event->cpu_map);
+	size_t ret;
+
+	ret = fprintf(fp, " nr: ");
+
+	if (cpus)
+		ret += cpu_map__fprintf(cpus, fp);
+	else
+		ret += fprintf(fp, "failed to get cpumap from event\n");
+
+	cpu_map__put(cpus);
+	return ret;
+}
+
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
 			     struct perf_sample *sample,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index e58a36b8ecbc..8e4fe4ea7704 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -530,6 +530,7 @@ size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
 u64 kallsyms__get_function_start(const char *kallsyms_filename,
-- 
2.4.3


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

* [PATCH 09/56] perf tools: Add stat config event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (7 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 08/56] perf tools: Add perf_event__fprintf_cpu_map function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 10/56] perf tools: Add stat config event synthesize function Jiri Olsa
                   ` (47 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding stat config event to pass/store stat config data,
so report tools (report/script) know how to interpret
stat data.

The config data are stored in 'tag|value' way to allow
easy extension and backward compatibility.

Link: http://lkml.kernel.org/n/tip-1npdsfez8635vogthpqwtkd0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 20 ++++++++++++++++++++
 tools/perf/util/session.c | 24 ++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index d55e5a5ca757..35a678c06b7b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -39,6 +39,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
+	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8e4fe4ea7704..ce8462255631 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -228,6 +228,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
 	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_CPU_MAP			= 74,
+	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -375,6 +376,24 @@ struct cpu_map_event {
 	u64				cpu[];
 };
 
+enum {
+	PERF_STAT_CONFIG_TERM__AGGR_MODE	= 0,
+	PERF_STAT_CONFIG_TERM__INTERVAL		= 1,
+	PERF_STAT_CONFIG_TERM__SCALE		= 2,
+	PERF_STAT_CONFIG_TERM__MAX		= 3,
+};
+
+struct stat_config_term_event {
+	u64	tag;
+	u64	val;
+};
+
+struct stat_config_event {
+	struct perf_event_header	header;
+	u64				nr;
+	struct stat_config_term_event	data[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -399,6 +418,7 @@ union perf_event {
 	struct context_switch_event	context_switch;
 	struct thread_map_event		thread_map;
 	struct cpu_map_event		cpu_map;
+	struct stat_config_event	stat_config;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 735ecf84f977..150ddc14b3fd 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -315,6 +315,15 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static
+int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event __maybe_unused,
+				   struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -369,6 +378,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->thread_map = process_event_thread_map_stub;
 	if (tool->cpu_map == NULL)
 		tool->cpu_map = process_event_cpu_map_stub;
+	if (tool->stat_config == NULL)
+		tool->stat_config = process_event_stat_config_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -661,6 +672,16 @@ static void perf_event__cpu_map_swap(union perf_event *event,
 		event->cpu_map.cpu[i] = bswap_64(event->cpu_map.cpu[i]);
 }
 
+static void perf_event__stat_config_swap(union perf_event *event,
+					 bool sample_id_all __maybe_unused)
+{
+	u64 size;
+
+	size  = event->stat_config.nr * sizeof(event->stat_config.data[0]);
+	size += 1; /* nr item itself */
+	mem_bswap_64(&event->stat_config.nr, size);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -690,6 +711,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
+	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1230,6 +1252,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->thread_map(tool, event, session);
 	case PERF_RECORD_CPU_MAP:
 		return tool->cpu_map(tool, event, session);
+	case PERF_RECORD_STAT_CONFIG:
+		return tool->stat_config(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 9e5925c78519..aa7ae73d76b4 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -57,7 +57,8 @@ struct perf_tool {
 			auxtrace_info,
 			auxtrace_error,
 			thread_map,
-			cpu_map;
+			cpu_map,
+			stat_config;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 10/56] perf tools: Add stat config event synthesize function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (8 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 09/56] perf tools: Add stat config event Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 11/56] perf tools: Add stat config event read function Jiri Olsa
                   ` (46 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introduce perf_event__synthesize_stat_config function to
synthesize 'struct perf_stat_config'.

Storing stat config in form of tag-value pairs in a believe
it'll sort out future version issues.

Link: http://lkml.kernel.org/n/tip-zof1adf5flwp38xdzxzn4p2z@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/Build          |  1 +
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/stat.c         | 53 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 40 +++++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  5 ++++
 6 files changed, 104 insertions(+)
 create mode 100644 tools/perf/tests/stat.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 1c0296fc95ea..ea4ef8fdd463 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -34,6 +34,7 @@ perf-y += thread-map.o
 perf-y += llvm.o
 perf-y += topology.o
 perf-y += cpumap.o
+perf-y += stat.o
 
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 3b8b518d96f9..f7a09d45408b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -175,6 +175,10 @@ static struct test generic_tests[] = {
 		.func = test__cpu_map_synthesize,
 	},
 	{
+		.desc = "Test stat config synthesize",
+		.func = test__synthesize_stat_config,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
new file mode 100644
index 000000000000..5e6a2441998c
--- /dev/null
+++ b/tools/perf/tests/stat.c
@@ -0,0 +1,53 @@
+#include <linux/compiler.h>
+#include "event.h"
+#include "tests.h"
+#include "stat.h"
+#include "debug.h"
+
+static bool has_term(struct stat_config_event *config,
+		     u64 tag, u64 val)
+{
+	unsigned i;
+
+	for (i = 0; i < config->nr; i++) {
+		if ((config->data[i].tag == tag) &&
+		    (config->data[i].val == val))
+			return true;
+	}
+
+	return false;
+}
+
+static int process_event(struct perf_tool *tool __maybe_unused,
+			 union perf_event *event,
+			 struct perf_sample *sample __maybe_unused,
+			 struct machine *machine __maybe_unused)
+{
+	struct stat_config_event *config = &event->stat_config;
+
+#define HAS(term, val) \
+	has_term(config, PERF_STAT_CONFIG_TERM__##term, val)
+
+	TEST_ASSERT_VAL("wrong nr",        config->nr == PERF_STAT_CONFIG_TERM__MAX);
+	TEST_ASSERT_VAL("wrong aggr_mode", HAS(AGGR_MODE, AGGR_CORE));
+	TEST_ASSERT_VAL("wrong scale",     HAS(SCALE, 1));
+	TEST_ASSERT_VAL("wrong interval",  HAS(INTERVAL, 1));
+
+#undef HAS
+
+	return 0;
+}
+
+int test__synthesize_stat_config(void)
+{
+	struct perf_stat_config stat_config = {
+		.aggr_mode	= AGGR_CORE,
+		.scale		= 1,
+		.interval	= 1,
+	};
+
+	TEST_ASSERT_VAL("failed to synthesize stat_config",
+		!perf_event__synthesize_stat_config(NULL, &stat_config, process_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index c7f3c3211bcf..227ad216197e 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -69,6 +69,7 @@ int test__llvm(void);
 int test_session_topology(void);
 int test__thread_map_synthesize(void);
 int test__cpu_map_synthesize(void);
+int test__synthesize_stat_config(void);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 35a678c06b7b..9c193b99fcee 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -10,6 +10,8 @@
 #include "thread.h"
 #include "thread_map.h"
 #include "symbol/kallsyms.h"
+#include "asm/bug.h"
+#include "stat.h"
 
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
@@ -766,6 +768,44 @@ int perf_event__synthesize_cpu_map(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_stat_config(struct perf_tool *tool,
+				       struct perf_stat_config *config,
+				       perf_event__handler_t process,
+				       struct machine *machine)
+{
+	struct stat_config_event *event;
+	int size, i = 0, err;
+
+	size  = sizeof(*event);
+	size += (PERF_STAT_CONFIG_TERM__MAX * sizeof(event->data[0]));
+
+	event = zalloc(size);
+	if (!event)
+		return -ENOMEM;
+
+	event->header.type = PERF_RECORD_STAT_CONFIG;
+	event->header.size = size;
+	event->nr          = PERF_STAT_CONFIG_TERM__MAX;
+
+#define ADD(__term, __val)					\
+	event->data[i].tag = PERF_STAT_CONFIG_TERM__##__term;	\
+	event->data[i].val = __val;				\
+	i++;
+
+	ADD(AGGR_MODE,	config->aggr_mode)
+	ADD(INTERVAL,	config->interval)
+	ADD(SCALE,	config->scale)
+
+	WARN_ONCE(i != PERF_STAT_CONFIG_TERM__MAX,
+		  "stat config terms unbalanced\n");
+#undef ADD
+
+	err = process(tool, (union perf_event *) event, NULL, machine);
+
+	free(event);
+	return err;
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index ce8462255631..d4652940e086 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -426,6 +426,7 @@ void perf_event__print_totals(void);
 struct perf_tool;
 struct thread_map;
 struct cpu_map;
+struct perf_stat_config;
 
 typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 				     union perf_event *event,
@@ -452,6 +453,10 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine);
+int perf_event__synthesize_stat_config(struct perf_tool *tool,
+				       struct perf_stat_config *config,
+				       perf_event__handler_t process,
+				       struct machine *machine);
 
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
-- 
2.4.3


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

* [PATCH 11/56] perf tools: Add stat config event read function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (9 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 10/56] perf tools: Add stat config event synthesize function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 12/56] perf tools: Add stat event Jiri Olsa
                   ` (45 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introducing perf_event__read_stat_config function to read
struct perf_stat_config object data from stat config event.

Link: http://lkml.kernel.org/n/tip-62ae08zz97jp2qkhygp8uet5@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/stat.c |  6 ++++++
 tools/perf/util/event.c | 24 ++++++++++++++++++++++++
 tools/perf/util/event.h |  2 ++
 3 files changed, 32 insertions(+)

diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 5e6a2441998c..2049c5a3e4a2 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -24,6 +24,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
 	struct stat_config_event *config = &event->stat_config;
+	struct perf_stat_config stat_config;
 
 #define HAS(term, val) \
 	has_term(config, PERF_STAT_CONFIG_TERM__##term, val)
@@ -35,6 +36,11 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 
 #undef HAS
 
+	perf_event__read_stat_config(&stat_config, config);
+
+	TEST_ASSERT_VAL("wrong aggr_mode", stat_config.aggr_mode == AGGR_CORE);
+	TEST_ASSERT_VAL("wrong scale",     stat_config.scale == 1);
+	TEST_ASSERT_VAL("wrong interval",  stat_config.interval == 1);
 	return 0;
 }
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9c193b99fcee..f60540c8987e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -806,6 +806,30 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 	return err;
 }
 
+void perf_event__read_stat_config(struct perf_stat_config *config,
+				  struct stat_config_event *event)
+{
+	unsigned i;
+
+	for (i = 0; i < event->nr; i++) {
+
+		switch (event->data[i].tag) {
+#define CASE(__term, __val)					\
+		case PERF_STAT_CONFIG_TERM__##__term:		\
+			config->__val = event->data[i].val;	\
+			break;
+
+		CASE(AGGR_MODE, aggr_mode)
+		CASE(SCALE,     scale)
+		CASE(INTERVAL,  interval)
+#undef CASE
+		default:
+			pr_warning("unknown stat config term %" PRIu64 "\n",
+				   event->data[i].tag);
+		}
+	}
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index d4652940e086..1111b9824c69 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -457,6 +457,8 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 				       struct perf_stat_config *config,
 				       perf_event__handler_t process,
 				       struct machine *machine);
+void perf_event__read_stat_config(struct perf_stat_config *config,
+				  struct stat_config_event *event);
 
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
-- 
2.4.3


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

* [PATCH 12/56] perf tools: Add stat event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (10 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 11/56] perf tools: Add stat config event read function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 13/56] perf tools: Add stat event synthesize function Jiri Olsa
                   ` (44 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding stat event to store 'struct perf_counter_values' for
given event/cpu/thread.

Link: http://lkml.kernel.org/n/tip-56xpt7m6au4d8u39nffoqgx1@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 19 +++++++++++++++++++
 tools/perf/util/session.c | 26 +++++++++++++++++++++++++-
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index f60540c8987e..f7a61b0975c2 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -42,6 +42,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
+	[PERF_RECORD_STAT]			= "STAT",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1111b9824c69..20e28fd1eed7 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -229,6 +229,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_STAT_CONFIG			= 75,
+	PERF_RECORD_STAT			= 76,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -394,6 +395,23 @@ struct stat_config_event {
 	struct stat_config_term_event	data[];
 };
 
+struct stat_event {
+	struct perf_event_header	header;
+
+	u64	id;
+	u32	cpu;
+	u32	thread;
+
+	union {
+		struct {
+			u64 val;
+			u64 ena;
+			u64 run;
+		};
+		u64 values[3];
+	};
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -419,6 +437,7 @@ union perf_event {
 	struct thread_map_event		thread_map;
 	struct cpu_map_event		cpu_map;
 	struct stat_config_event	stat_config;
+	struct stat_event		stat;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 150ddc14b3fd..c5cedb8a20fb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -296,7 +296,6 @@ int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
-
 static
 int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
 				  union perf_event *event __maybe_unused,
@@ -324,6 +323,15 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_stat_stub(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event __maybe_unused,
+			     struct perf_session *perf_session
+			     __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -380,6 +388,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->cpu_map = process_event_cpu_map_stub;
 	if (tool->stat_config == NULL)
 		tool->stat_config = process_event_stat_config_stub;
+	if (tool->stat == NULL)
+		tool->stat = process_stat_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -682,6 +692,17 @@ static void perf_event__stat_config_swap(union perf_event *event,
 	mem_bswap_64(&event->stat_config.nr, size);
 }
 
+static void perf_event__stat_swap(union perf_event *event,
+				  bool sample_id_all __maybe_unused)
+{
+	event->stat.id     = bswap_64(event->stat.id);
+	event->stat.thread = bswap_32(event->stat.thread);
+	event->stat.cpu    = bswap_32(event->stat.cpu);
+	event->stat.val    = bswap_64(event->stat.val);
+	event->stat.ena    = bswap_64(event->stat.ena);
+	event->stat.run    = bswap_64(event->stat.run);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -712,6 +733,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
+	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1254,6 +1276,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->cpu_map(tool, event, session);
 	case PERF_RECORD_STAT_CONFIG:
 		return tool->stat_config(tool, event, session);
+	case PERF_RECORD_STAT:
+		return tool->stat(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index aa7ae73d76b4..f0b9da0c166a 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -58,7 +58,8 @@ struct perf_tool {
 			auxtrace_error,
 			thread_map,
 			cpu_map,
-			stat_config;
+			stat_config,
+			stat;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 13/56] perf tools: Add stat event synthesize function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (11 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 12/56] perf tools: Add stat event Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 14/56] perf tools: Add stat event read function Jiri Olsa
                   ` (43 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introduce perf_event__synthesize_stat function to
synthesize 'struct stat_event'.

Link: http://lkml.kernel.org/n/tip-0jr9x4vwk0nxbs2ueclj7jfy@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/stat.c         | 41 ++++++++++++++++++++++++++++++++++++-----
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 22 ++++++++++++++++++++++
 tools/perf/util/event.h         |  7 ++++++-
 5 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index f7a09d45408b..a37db6fee905 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -179,6 +179,10 @@ static struct test generic_tests[] = {
 		.func = test__synthesize_stat_config,
 	},
 	{
+		.desc = "Test stat synthesize",
+		.func = test__synthesize_stat,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 2049c5a3e4a2..5918fb74dfd8 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -2,6 +2,7 @@
 #include "event.h"
 #include "tests.h"
 #include "stat.h"
+#include "counts.h"
 #include "debug.h"
 
 static bool has_term(struct stat_config_event *config,
@@ -18,10 +19,10 @@ static bool has_term(struct stat_config_event *config,
 	return false;
 }
 
-static int process_event(struct perf_tool *tool __maybe_unused,
-			 union perf_event *event,
-			 struct perf_sample *sample __maybe_unused,
-			 struct machine *machine __maybe_unused)
+static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_sample *sample __maybe_unused,
+				     struct machine *machine __maybe_unused)
 {
 	struct stat_config_event *config = &event->stat_config;
 	struct perf_stat_config stat_config;
@@ -53,7 +54,37 @@ int test__synthesize_stat_config(void)
 	};
 
 	TEST_ASSERT_VAL("failed to synthesize stat_config",
-		!perf_event__synthesize_stat_config(NULL, &stat_config, process_event, NULL));
+		!perf_event__synthesize_stat_config(NULL, &stat_config, process_stat_config_event, NULL));
+
+	return 0;
+}
+
+static int process_stat_event(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_sample *sample __maybe_unused,
+			      struct machine *machine __maybe_unused)
+{
+	struct stat_event *stat = &event->stat;
+
+	TEST_ASSERT_VAL("wrong cpu",    stat->cpu    == 1);
+	TEST_ASSERT_VAL("wrong thread", stat->thread == 2);
+	TEST_ASSERT_VAL("wrong id",     stat->id     == 3);
+	TEST_ASSERT_VAL("wrong val",    stat->val    == 100);
+	TEST_ASSERT_VAL("wrong run",    stat->ena    == 200);
+	TEST_ASSERT_VAL("wrong ena",    stat->run    == 300);
+	return 0;
+}
+
+int test__synthesize_stat(void)
+{
+	struct perf_counts_values count = {
+		.val = 100,
+		.ena = 200,
+		.run = 300,
+	};
+
+	TEST_ASSERT_VAL("failed to synthesize stat_config",
+		!perf_event__synthesize_stat(NULL, 1, 2, 3, &count, process_stat_event, NULL));
 
 	return 0;
 }
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 227ad216197e..edf460e5cd64 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -70,6 +70,7 @@ int test_session_topology(void);
 int test__thread_map_synthesize(void);
 int test__cpu_map_synthesize(void);
 int test__synthesize_stat_config(void);
+int test__synthesize_stat(void);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index f7a61b0975c2..2f8ec744ba9e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -807,6 +807,28 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_stat(struct perf_tool *tool,
+				u32 cpu, u32 thread, u64 id,
+				struct perf_counts_values *count,
+				perf_event__handler_t process,
+				struct machine *machine)
+{
+	struct stat_event event;
+
+	event.header.type = PERF_RECORD_STAT;
+	event.header.size = sizeof(event);
+	event.header.misc = 0;
+
+	event.id        = id;
+	event.cpu       = cpu;
+	event.thread    = thread;
+	event.val       = count->val;
+	event.ena       = count->ena;
+	event.run       = count->run;
+
+	return process(tool, (union perf_event *) &event, NULL, machine);
+}
+
 void perf_event__read_stat_config(struct perf_stat_config *config,
 				  struct stat_config_event *event)
 {
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 20e28fd1eed7..eab93d78bb9a 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -446,6 +446,7 @@ struct perf_tool;
 struct thread_map;
 struct cpu_map;
 struct perf_stat_config;
+struct perf_counts_values;
 
 typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 				     union perf_event *event,
@@ -478,7 +479,11 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 				       struct machine *machine);
 void perf_event__read_stat_config(struct perf_stat_config *config,
 				  struct stat_config_event *event);
-
+int perf_event__synthesize_stat(struct perf_tool *tool,
+				u32 cpu, u32 thread, u64 id,
+				struct perf_counts_values *count,
+				perf_event__handler_t process,
+				struct machine *machine);
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine);
-- 
2.4.3


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

* [PATCH 14/56] perf tools: Add stat event read function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (12 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 13/56] perf tools: Add stat event synthesize function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 15/56] perf tools: Add stat round event Jiri Olsa
                   ` (42 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introducing perf_event__process_stat_event function to process
'struct perf_stat' data from stat event.

Link: http://lkml.kernel.org/n/tip-2bvpxxp60e0qqcsecohgeju3@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/stat.c | 23 +++++++++++++++++++++++
 tools/perf/util/stat.h |  6 ++++++
 2 files changed, 29 insertions(+)

diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 2d065d065b67..0369b4516c29 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -340,3 +340,26 @@ int perf_stat_process_counter(struct perf_stat_config *config,
 
 	return 0;
 }
+
+int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event,
+				   struct perf_session *session)
+{
+	struct perf_counts_values count;
+	struct stat_event *stat = &event->stat;
+	struct perf_evsel *counter;
+
+	count.val = stat->val;
+	count.ena = stat->ena;
+	count.run = stat->run;
+
+	counter = perf_evlist__id2evsel(session->evlist, stat->id);
+	if (!counter) {
+		pr_err("Failed to resolve counter for stat event.\n");
+		return -EINVAL;
+	}
+
+	*perf_counts(counter->counts, stat->cpu, stat->thread) = count;
+	counter->supported = true;
+	return 0;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 62448c8175d3..a61cb0a9f23a 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -89,4 +89,10 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist);
 
 int perf_stat_process_counter(struct perf_stat_config *config,
 			      struct perf_evsel *counter);
+struct perf_tool;
+union perf_event;
+struct perf_session;
+int perf_event__process_stat_event(struct perf_tool *tool,
+				   union perf_event *event,
+				   struct perf_session *session);
 #endif
-- 
2.4.3


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

* [PATCH 15/56] perf tools: Add stat round event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (13 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 14/56] perf tools: Add stat event read function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 16/56] perf tools: Add stat round event synthesize function Jiri Olsa
                   ` (41 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding stat round event to be stored after each stat interval round,
so report tools (report/script) get notified and process interval
data.

Link: http://lkml.kernel.org/n/tip-nqhzuxrv12ulccx11k7x86mr@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 13 +++++++++++++
 tools/perf/util/session.c | 21 +++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2f8ec744ba9e..a47ca1e55532 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -43,6 +43,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 	[PERF_RECORD_STAT]			= "STAT",
+	[PERF_RECORD_STAT_ROUND]		= "STAT_ROUND",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index eab93d78bb9a..c9eeb2627ec3 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -230,6 +230,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_STAT			= 76,
+	PERF_RECORD_STAT_ROUND			= 77,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -412,6 +413,17 @@ struct stat_event {
 	};
 };
 
+enum {
+	PERF_STAT_ROUND_TYPE__INTERVAL	= 0,
+	PERF_STAT_ROUND_TYPE__FINAL	= 1,
+};
+
+struct stat_round_event {
+	struct perf_event_header	header;
+	u64				type;
+	u64				time;
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -438,6 +450,7 @@ union perf_event {
 	struct cpu_map_event		cpu_map;
 	struct stat_config_event	stat_config;
 	struct stat_event		stat;
+	struct stat_round_event		stat_round;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c5cedb8a20fb..25cee7f3af1f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -332,6 +332,15 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event __maybe_unused,
+				   struct perf_session *perf_session
+				   __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -390,6 +399,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->stat_config = process_event_stat_config_stub;
 	if (tool->stat == NULL)
 		tool->stat = process_stat_stub;
+	if (tool->stat_round == NULL)
+		tool->stat_round = process_stat_round_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -703,6 +714,13 @@ static void perf_event__stat_swap(union perf_event *event,
 	event->stat.run    = bswap_64(event->stat.run);
 }
 
+static void perf_event__stat_round_swap(union perf_event *event,
+					bool sample_id_all __maybe_unused)
+{
+	event->stat_round.type = bswap_64(event->stat_round.type);
+	event->stat_round.time = bswap_64(event->stat_round.time);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -734,6 +752,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
+	[PERF_RECORD_STAT_ROUND]	  = perf_event__stat_round_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1278,6 +1297,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->stat_config(tool, event, session);
 	case PERF_RECORD_STAT:
 		return tool->stat(tool, event, session);
+	case PERF_RECORD_STAT_ROUND:
+		return tool->stat_round(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index f0b9da0c166a..d04d9e5f444a 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -59,7 +59,8 @@ struct perf_tool {
 			thread_map,
 			cpu_map,
 			stat_config,
-			stat;
+			stat,
+			stat_round;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 16/56] perf tools: Add stat round event synthesize function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (14 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 15/56] perf tools: Add stat round event Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 17/56] perf tools: Add stat events fprintf functions Jiri Olsa
                   ` (40 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introduce perf_event__synthesize_stat_round function to
synthesize 'struct stat_round_event'.

Link: http://lkml.kernel.org/n/tip-gl8rk2il9grrnqalrqlo7iym@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/stat.c         | 21 +++++++++++++++++++++
 tools/perf/tests/tests.h        |  2 ++
 tools/perf/util/event.c         | 17 +++++++++++++++++
 tools/perf/util/event.h         |  4 ++++
 5 files changed, 48 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index a37db6fee905..44f30d1997ad 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -183,6 +183,10 @@ static struct test generic_tests[] = {
 		.func = test__synthesize_stat,
 	},
 	{
+		.desc = "Test stat round synthesize",
+		.func = test__synthesize_stat_round,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 5918fb74dfd8..ff42574adfd8 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -88,3 +88,24 @@ int test__synthesize_stat(void)
 
 	return 0;
 }
+
+static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_sample *sample __maybe_unused,
+				    struct machine *machine __maybe_unused)
+{
+	struct stat_round_event *stat_round = &event->stat_round;
+
+	TEST_ASSERT_VAL("wrong time", stat_round->time == 0xdeadbeef);
+	TEST_ASSERT_VAL("wrong type", stat_round->type == PERF_STAT_ROUND_TYPE__INTERVAL);
+	return 0;
+}
+
+int test__synthesize_stat_round(void)
+{
+	TEST_ASSERT_VAL("failed to synthesize stat_config",
+		!perf_event__synthesize_stat_round(NULL, 0xdeadbeef, PERF_STAT_ROUND_TYPE__INTERVAL,
+						   process_stat_round_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index edf460e5cd64..261716924ad9 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -71,6 +71,8 @@ int test__thread_map_synthesize(void);
 int test__cpu_map_synthesize(void);
 int test__synthesize_stat_config(void);
 int test__synthesize_stat(void);
+int test__synthesize_stat_round(void);
+
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index a47ca1e55532..f879385ec199 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -830,6 +830,23 @@ int perf_event__synthesize_stat(struct perf_tool *tool,
 	return process(tool, (union perf_event *) &event, NULL, machine);
 }
 
+int perf_event__synthesize_stat_round(struct perf_tool *tool,
+				      u64 time, u64 type,
+				      perf_event__handler_t process,
+				      struct machine *machine)
+{
+	struct stat_round_event event;
+
+	event.header.type = PERF_RECORD_STAT_ROUND;
+	event.header.size = sizeof(event);
+	event.header.misc = 0;
+
+	event.time = time;
+	event.type = type;
+
+	return process(tool, (union perf_event *) &event, NULL, machine);
+}
+
 void perf_event__read_stat_config(struct perf_stat_config *config,
 				  struct stat_config_event *event)
 {
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c9eeb2627ec3..04ba8ddf28f8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -497,6 +497,10 @@ int perf_event__synthesize_stat(struct perf_tool *tool,
 				struct perf_counts_values *count,
 				perf_event__handler_t process,
 				struct machine *machine);
+int perf_event__synthesize_stat_round(struct perf_tool *tool,
+				      u64 time, u64 type,
+				      perf_event__handler_t process,
+				      struct machine *machine);
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine);
-- 
2.4.3


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

* [PATCH 17/56] perf tools: Add stat events fprintf functions
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (15 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 16/56] perf tools: Add stat round event synthesize function Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 18/56] perf tools: Add attr_update event Jiri Olsa
                   ` (39 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introducing following functions to display stat events
for raw dump.

  perf_event__fprintf_stat
  perf_event__fprintf_stat_round
  perf_event__fprintf_stat_config

Link: http://lkml.kernel.org/n/tip-hw2aywbi4w9jsq7cw8cene3u@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/stat.c | 39 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h |  4 ++++
 2 files changed, 43 insertions(+)

diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 0369b4516c29..0db0f8c05d5e 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -363,3 +363,42 @@ int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
 	counter->supported = true;
 	return 0;
 }
+
+size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
+{
+	struct stat_event *stat = (struct stat_event*) event;
+	size_t ret;
+
+	ret  = fprintf(fp, "\n... id %" PRIu64 ", cpu %d, thread %d\n",
+		       stat->id, stat->cpu, stat->thread);
+	ret += fprintf(fp, "... value %" PRIu64 ", enabled %" PRIu64 ", running %" PRIu64 "\n",
+		       stat->val, stat->ena, stat->run);
+
+	return ret;
+}
+
+size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
+{
+	struct stat_round_event *round = (struct stat_round_event*) event;
+	size_t ret;
+
+	ret = fprintf(fp, "\n... time %" PRIu64 ", type %s\n", round->time,
+		      round->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
+
+	return ret;
+}
+
+size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
+{
+	struct perf_stat_config sc;
+	size_t ret;
+
+	perf_event__read_stat_config(&sc, &event->stat_config);
+
+	ret  = fprintf(fp, "\n");
+	ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode);
+	ret += fprintf(fp, "... scale     %d\n", sc.scale);
+	ret += fprintf(fp, "... interval  %u\n", sc.interval);
+
+	return ret;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index a61cb0a9f23a..f313955a24f2 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -95,4 +95,8 @@ struct perf_session;
 int perf_event__process_stat_event(struct perf_tool *tool,
 				   union perf_event *event,
 				   struct perf_session *session);
+
+size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
 #endif
-- 
2.4.3


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

* [PATCH 18/56] perf tools: Add attr_update event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (16 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 17/56] perf tools: Add stat events fprintf functions Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 19/56] perf tools: Add attr_update event unit type Jiri Olsa
                   ` (38 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

It'll server as base event for additional event attributes
details, that are not part of the attr event.

At the moment this event is just dummy one without specific
functionality. The type value will distinguish the update
event details. It comes in following patches.

The idea for this event is to be extensible for any update
that attr event might need in the future.

Link: http://lkml.kernel.org/n/tip-uik5iyftzgk488ttrgpjvtf6@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   |  8 ++++++++
 tools/perf/util/header.c  | 20 ++++++++++++++++++++
 tools/perf/util/header.h  |  3 +++
 tools/perf/util/session.c | 21 +++++++++++++++++++++
 tools/perf/util/tool.h    |  1 +
 6 files changed, 54 insertions(+)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index f879385ec199..ffc3d524126a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -44,6 +44,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 	[PERF_RECORD_STAT]			= "STAT",
 	[PERF_RECORD_STAT_ROUND]		= "STAT_ROUND",
+	[PERF_RECORD_HEADER_ATTR_UPDATE]	= "ATTR_UPDATE",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 04ba8ddf28f8..164ff6864ef9 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -231,6 +231,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_STAT			= 76,
 	PERF_RECORD_STAT_ROUND			= 77,
+	PERF_RECORD_HEADER_ATTR_UPDATE		= 78,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -281,6 +282,12 @@ struct attr_event {
 	u64 id[];
 };
 
+struct attr_update_event {
+	struct perf_event_header header;
+	u64 type;
+	u64 id;
+};
+
 #define MAX_EVENT_NAME 64
 
 struct perf_trace_event_type {
@@ -436,6 +443,7 @@ union perf_event {
 	struct throttle_event		throttle;
 	struct sample_event		sample;
 	struct attr_event		attr;
+	struct attr_update_event	attr_update;
 	struct event_type_event		event_type;
 	struct tracing_data_event	tracing_data;
 	struct build_id_event		build_id;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 43838003c1a1..437856eec7c4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2745,6 +2745,26 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_evlist **pevlist)
+{
+	struct attr_update_event *ev = &event->attr_update;
+	struct perf_evlist *evlist;
+	struct perf_evsel *evsel;
+
+	if (!pevlist || *pevlist == NULL)
+		return -EINVAL;
+
+	evlist = *pevlist;
+
+	evsel = perf_evlist__id2evsel(evlist, ev->id);
+	if (evsel == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
 int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
 					struct perf_evlist *evlist,
 					perf_event__handler_t process)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 05f27cb6b7e3..069298367348 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -107,6 +107,9 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
+int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_evlist **pevlist);
 
 int perf_event__synthesize_tracing_data(struct perf_tool *tool,
 					int fd, struct perf_evlist *evlist,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 25cee7f3af1f..47152ae58f66 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -205,6 +205,15 @@ static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_event_synth_attr_update_stub(struct perf_tool *tool __maybe_unused,
+						union perf_event *event __maybe_unused,
+						struct perf_evlist **pevlist
+						__maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
 				     union perf_event *event __maybe_unused,
 				     struct perf_sample *sample __maybe_unused,
@@ -373,6 +382,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->unthrottle = process_event_stub;
 	if (tool->attr == NULL)
 		tool->attr = process_event_synth_attr_stub;
+	if (tool->attr_update == NULL)
+		tool->attr_update = process_event_synth_attr_update_stub;
 	if (tool->tracing_data == NULL)
 		tool->tracing_data = process_event_synth_tracing_data_stub;
 	if (tool->build_id == NULL)
@@ -624,6 +635,13 @@ static void perf_event__hdr_attr_swap(union perf_event *event,
 	mem_bswap_64(event->attr.id, size);
 }
 
+static void perf_event__hdr_attr_update_swap(union perf_event *event,
+					     bool sample_id_all __maybe_unused)
+{
+	event->attr_update.type = bswap_64(event->attr_update.type);
+	event->attr_update.id   = bswap_64(event->attr_update.id);
+}
+
 static void perf_event__event_type_swap(union perf_event *event,
 					bool sample_id_all __maybe_unused)
 {
@@ -753,6 +771,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
 	[PERF_RECORD_STAT_ROUND]	  = perf_event__stat_round_swap,
+	[PERF_RECORD_HEADER_ATTR_UPDATE]  = perf_event__hdr_attr_update_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1264,6 +1283,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 			perf_session__set_comm_exec(session);
 		}
 		return err;
+	case PERF_RECORD_HEADER_ATTR_UPDATE:
+		return tool->attr_update(tool, event, &session->evlist);
 	case PERF_RECORD_HEADER_EVENT_TYPE:
 		/*
 		 * Depreceated, but we need to handle it for sake
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index d04d9e5f444a..59702b5d703f 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -50,6 +50,7 @@ struct perf_tool {
 			throttle,
 			unthrottle;
 	event_attr_op	attr;
+	event_attr_op	attr_update;
 	event_op2	tracing_data;
 	event_oe	finished_round;
 	event_op2	build_id,
-- 
2.4.3


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

* [PATCH 19/56] perf tools: Add attr_update event unit type
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (17 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 18/56] perf tools: Add attr_update event Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:54 ` [PATCH 20/56] perf tools: Add attr_update event scale type Jiri Olsa
                   ` (37 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding unit type attr update event, that stores/transfer
events unit name. The unit name is part of the perf stat
output data.

Link: http://lkml.kernel.org/n/tip-5s6ape0vz2sfxgzu16eu8y7r@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/Build          |  1 +
 tools/perf/tests/attr_update.c  | 41 ++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.h         |  8 ++++++++
 tools/perf/util/header.c        | 44 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h        |  3 +++
 7 files changed, 102 insertions(+)
 create mode 100644 tools/perf/tests/attr_update.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index ea4ef8fdd463..039bba2918b0 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -35,6 +35,7 @@ perf-y += llvm.o
 perf-y += topology.o
 perf-y += cpumap.o
 perf-y += stat.o
+perf-y += attr_update.o
 
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
diff --git a/tools/perf/tests/attr_update.c b/tools/perf/tests/attr_update.c
new file mode 100644
index 000000000000..cfdb56cf3a95
--- /dev/null
+++ b/tools/perf/tests/attr_update.c
@@ -0,0 +1,41 @@
+#include <linux/compiler.h>
+#include "evlist.h"
+#include "evsel.h"
+#include "machine.h"
+#include "tests.h"
+#include "debug.h"
+
+static int process_event_unit(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_sample *sample __maybe_unused,
+			      struct machine *machine __maybe_unused)
+{
+	struct attr_update_event *ev = (struct attr_update_event*) event;
+
+	TEST_ASSERT_VAL("wrong id", ev->id == 123);
+	TEST_ASSERT_VAL("wrong unit", !strcmp(ev->str, "KRAVA"));
+	return 0;
+}
+
+int test__attr_update(void)
+{
+	struct perf_evlist *evlist;
+	struct perf_evsel *evsel;
+
+	evlist = perf_evlist__new_default();
+	TEST_ASSERT_VAL("failed to get evlist", evlist);
+
+	evsel = perf_evlist__first(evlist);
+
+	TEST_ASSERT_VAL("failed to allos ids",
+			!perf_evsel__alloc_id(evsel, 1, 1));
+
+	perf_evlist__id_add(evlist, evsel, 0, 0, 123);
+
+	evsel->unit = strdup("KRAVA");
+
+	TEST_ASSERT_VAL("failed to synthesize attr update unit",
+			!perf_event__synthesize_attr_update_unit(NULL, evsel, process_event_unit));
+
+	return 0;
+}
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 44f30d1997ad..d488e12e72c2 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -187,6 +187,10 @@ static struct test generic_tests[] = {
 		.func = test__synthesize_stat_round,
 	},
 	{
+		.desc = "Test attr update synthesize",
+		.func = test__attr_update,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 261716924ad9..e4e3cebcb7f3 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -72,6 +72,7 @@ int test__cpu_map_synthesize(void);
 int test__synthesize_stat_config(void);
 int test__synthesize_stat(void);
 int test__synthesize_stat_round(void);
+int test__attr_update(void);
 
 
 #if defined(__arm__) || defined(__aarch64__)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 164ff6864ef9..501bb4a40982 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -282,10 +282,18 @@ struct attr_event {
 	u64 id[];
 };
 
+
+enum {
+	PERF_ATTR_UPDATE__UNIT  = 0,
+};
+
 struct attr_update_event {
 	struct perf_event_header header;
 	u64 type;
 	u64 id;
+
+	/* Having 'str' for all string updates. */
+	char str[];
 };
 
 #define MAX_EVENT_NAME 64
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 437856eec7c4..a3f4bd45d880 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2686,6 +2686,43 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 	return err;
 }
 
+static struct attr_update_event*
+attr_update_event__alloc(size_t size, u64 type, u64 id)
+{
+	struct attr_update_event *ev;
+
+	size += sizeof(*ev);
+	size  = PERF_ALIGN(size, sizeof(u64));
+
+	ev = zalloc(size);
+	if (ev) {
+		ev->header.type = PERF_RECORD_HEADER_ATTR_UPDATE;
+		ev->header.size = (u16)size;
+		ev->type = type;
+		ev->id = id;
+	}
+	return ev;
+}
+
+int
+perf_event__synthesize_attr_update_unit(struct perf_tool *tool,
+					struct perf_evsel *evsel,
+					perf_event__handler_t process)
+{
+	struct attr_update_event *ev;
+	size_t size = strlen(evsel->unit);
+	int err;
+
+	ev = attr_update_event__alloc(size + 1, PERF_ATTR_UPDATE__UNIT, evsel->id[0]);
+	if (ev == NULL)
+		return -ENOMEM;
+
+	strncpy(ev->str, evsel->unit, size);
+	err = process(tool, (union perf_event*) ev, NULL, NULL);
+	free(ev);
+	return err;
+}
+
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
@@ -2762,6 +2799,13 @@ int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
 	if (evsel == NULL)
 		return -EINVAL;
 
+	switch (ev->type) {
+	case PERF_ATTR_UPDATE__UNIT:
+		evsel->unit = strdup(ev->str);
+	default:
+		break;
+	}
+
 	return 0;
 }
 
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 069298367348..0f00ff55f451 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -105,6 +105,9 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 struct perf_session *session,
 				 perf_event__handler_t process);
+int perf_event__synthesize_attr_update_unit(struct perf_tool *tool,
+					    struct perf_evsel *evsel,
+					    perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
 int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
-- 
2.4.3


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

* [PATCH 20/56] perf tools: Add attr_update event scale type
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (18 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 19/56] perf tools: Add attr_update event unit type Jiri Olsa
@ 2015-10-06 19:54 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 21/56] perf tools: Add attr_update event name type Jiri Olsa
                   ` (36 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding scale type attr update event, that stores/transfer
events scale value. The PMU events can define the scale
value which is used to multiply events data.

Link: http://lkml.kernel.org/n/tip-by8wb1atqzhtpx86ybjhwge2@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/attr_update.c | 17 +++++++++++++++++
 tools/perf/util/event.h        |  3 +++
 tools/perf/util/header.c       | 22 ++++++++++++++++++++++
 tools/perf/util/header.h       |  3 +++
 4 files changed, 45 insertions(+)

diff --git a/tools/perf/tests/attr_update.c b/tools/perf/tests/attr_update.c
index cfdb56cf3a95..bb190d3aaefd 100644
--- a/tools/perf/tests/attr_update.c
+++ b/tools/perf/tests/attr_update.c
@@ -17,6 +17,18 @@ static int process_event_unit(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_event_scale(struct perf_tool *tool __maybe_unused,
+			       union perf_event *event,
+			       struct perf_sample *sample __maybe_unused,
+			       struct machine *machine __maybe_unused)
+{
+	struct attr_update_event *ev = (struct attr_update_event*) event;
+
+	TEST_ASSERT_VAL("wrong id", ev->id == 123);
+	TEST_ASSERT_VAL("wrong scale", ev->scale = 0.123);
+	return 0;
+}
+
 int test__attr_update(void)
 {
 	struct perf_evlist *evlist;
@@ -37,5 +49,10 @@ int test__attr_update(void)
 	TEST_ASSERT_VAL("failed to synthesize attr update unit",
 			!perf_event__synthesize_attr_update_unit(NULL, evsel, process_event_unit));
 
+	evsel->scale = 0.123;
+
+	TEST_ASSERT_VAL("failed to synthesize attr update scale",
+			!perf_event__synthesize_attr_update_scale(NULL, evsel, process_event_scale));
+
 	return 0;
 }
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 501bb4a40982..d9248975585b 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -285,6 +285,7 @@ struct attr_event {
 
 enum {
 	PERF_ATTR_UPDATE__UNIT  = 0,
+	PERF_ATTR_UPDATE__SCALE = 1,
 };
 
 struct attr_update_event {
@@ -292,6 +293,8 @@ struct attr_update_event {
 	u64 type;
 	u64 id;
 
+	double scale;
+
 	/* Having 'str' for all string updates. */
 	char str[];
 };
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a3f4bd45d880..a47ac44f6a59 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2723,6 +2723,25 @@ perf_event__synthesize_attr_update_unit(struct perf_tool *tool,
 	return err;
 }
 
+int
+perf_event__synthesize_attr_update_scale(struct perf_tool *tool,
+					 struct perf_evsel *evsel,
+					 perf_event__handler_t process)
+{
+	struct attr_update_event *ev;
+	int err;
+
+	ev = attr_update_event__alloc(0, PERF_ATTR_UPDATE__SCALE, evsel->id[0]);
+	if (ev == NULL)
+		return -ENOMEM;
+
+	ev->scale = evsel->scale;
+	err = process(tool, (union perf_event*) ev, NULL, NULL);
+	free(ev);
+	return err;
+}
+
+
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
@@ -2802,6 +2821,9 @@ int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
 	switch (ev->type) {
 	case PERF_ATTR_UPDATE__UNIT:
 		evsel->unit = strdup(ev->str);
+		break;
+	case PERF_ATTR_UPDATE__SCALE:
+		evsel->scale = ev->scale;
 	default:
 		break;
 	}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 0f00ff55f451..628ee46e14fd 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -108,6 +108,9 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 int perf_event__synthesize_attr_update_unit(struct perf_tool *tool,
 					    struct perf_evsel *evsel,
 					    perf_event__handler_t process);
+int perf_event__synthesize_attr_update_scale(struct perf_tool *tool,
+					     struct perf_evsel *evsel,
+					     perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
 int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
-- 
2.4.3


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

* [PATCH 21/56] perf tools: Add attr_update event name type
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (19 preceding siblings ...)
  2015-10-06 19:54 ` [PATCH 20/56] perf tools: Add attr_update event scale type Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 22/56] perf tools: Add perf_event__fprintf_attr_update function Jiri Olsa
                   ` (35 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding name type attr update event, that stores/transfer
events name. Event's name is stored within perf.data's
EVENT_DESC feature, but we don't have if we get report
data from pipe.

Link: http://lkml.kernel.org/n/tip-j8b9c0ev11zisop3qup1hdy8@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/attr_update.c | 24 ++++++++++++++++++++++++
 tools/perf/util/event.h        |  1 +
 tools/perf/util/header.c       | 21 +++++++++++++++++++++
 tools/perf/util/header.h       |  3 +++
 4 files changed, 49 insertions(+)

diff --git a/tools/perf/tests/attr_update.c b/tools/perf/tests/attr_update.c
index bb190d3aaefd..23ba1db9b2d4 100644
--- a/tools/perf/tests/attr_update.c
+++ b/tools/perf/tests/attr_update.c
@@ -29,10 +29,29 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+struct event_name {
+	struct perf_tool tool;
+	const char *name;
+};
+
+static int process_event_name(struct perf_tool *tool,
+			      union perf_event *event,
+			      struct perf_sample *sample __maybe_unused,
+			      struct machine *machine __maybe_unused)
+{
+	struct event_name *tmp = container_of(tool, struct event_name, tool);
+	struct attr_update_event *ev = (struct attr_update_event*) event;
+
+	TEST_ASSERT_VAL("wrong id", ev->id == 123);
+	TEST_ASSERT_VAL("wrong name", !strcmp(ev->str, tmp->name));
+	return 0;
+}
+
 int test__attr_update(void)
 {
 	struct perf_evlist *evlist;
 	struct perf_evsel *evsel;
+	struct event_name tmp;
 
 	evlist = perf_evlist__new_default();
 	TEST_ASSERT_VAL("failed to get evlist", evlist);
@@ -54,5 +73,10 @@ int test__attr_update(void)
 	TEST_ASSERT_VAL("failed to synthesize attr update scale",
 			!perf_event__synthesize_attr_update_scale(NULL, evsel, process_event_scale));
 
+	tmp.name = perf_evsel__name(evsel);
+
+	TEST_ASSERT_VAL("failed to synthesize attr update name",
+			!perf_event__synthesize_attr_update_name(&tmp.tool, evsel, process_event_name));
+
 	return 0;
 }
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index d9248975585b..88101c8fe0b1 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -286,6 +286,7 @@ struct attr_event {
 enum {
 	PERF_ATTR_UPDATE__UNIT  = 0,
 	PERF_ATTR_UPDATE__SCALE = 1,
+	PERF_ATTR_UPDATE__NAME  = 2,
 };
 
 struct attr_update_event {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a47ac44f6a59..2009f1fd1188 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2741,6 +2741,24 @@ perf_event__synthesize_attr_update_scale(struct perf_tool *tool,
 	return err;
 }
 
+int
+perf_event__synthesize_attr_update_name(struct perf_tool *tool,
+					struct perf_evsel *evsel,
+					perf_event__handler_t process)
+{
+	struct attr_update_event *ev;
+	size_t len = strlen(evsel->name);
+	int err;
+
+	ev = attr_update_event__alloc(len + 1, PERF_ATTR_UPDATE__NAME, evsel->id[0]);
+	if (ev == NULL)
+		return -ENOMEM;
+
+	strncpy(ev->str, evsel->name, len);
+	err = process(tool, (union perf_event*) ev, NULL, NULL);
+	free(ev);
+	return err;
+}
 
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
@@ -2822,6 +2840,9 @@ int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
 	case PERF_ATTR_UPDATE__UNIT:
 		evsel->unit = strdup(ev->str);
 		break;
+	case PERF_ATTR_UPDATE__NAME:
+		evsel->name = strdup(ev->str);
+		break;
 	case PERF_ATTR_UPDATE__SCALE:
 		evsel->scale = ev->scale;
 	default:
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 628ee46e14fd..cb538ade38d3 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -111,6 +111,9 @@ int perf_event__synthesize_attr_update_unit(struct perf_tool *tool,
 int perf_event__synthesize_attr_update_scale(struct perf_tool *tool,
 					     struct perf_evsel *evsel,
 					     perf_event__handler_t process);
+int perf_event__synthesize_attr_update_name(struct perf_tool *tool,
+					    struct perf_evsel *evsel,
+					    perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
 int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
-- 
2.4.3


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

* [PATCH 22/56] perf tools: Add perf_event__fprintf_attr_update function
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (20 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 21/56] perf tools: Add attr_update event name type Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 23/56] perf report: Display newly added events in raw dump Jiri Olsa
                   ` (34 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

To display attr_update event for raw dump.

Link: http://lkml.kernel.org/n/tip-ch2nor544486ppvwscqg55ik@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/header.c | 25 +++++++++++++++++++++++++
 tools/perf/util/header.h |  1 +
 2 files changed, 26 insertions(+)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2009f1fd1188..f35e8355cb1f 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2760,6 +2760,31 @@ perf_event__synthesize_attr_update_name(struct perf_tool *tool,
 	return err;
 }
 
+size_t perf_event__fprintf_attr_update(union perf_event *event, FILE *fp)
+{
+	struct attr_update_event *ev = &event->attr_update;
+	size_t ret;
+
+	ret = fprintf(fp, "\n... id:    %" PRIu64 "\n", ev->id);
+
+	switch (ev->type) {
+	case PERF_ATTR_UPDATE__SCALE:
+		ret += fprintf(fp, "... scale: %f\n", ev->scale);
+		break;
+	case PERF_ATTR_UPDATE__UNIT:
+		ret += fprintf(fp, "... unit:  %s\n", ev->str);
+		break;
+	case PERF_ATTR_UPDATE__NAME:
+		ret += fprintf(fp, "... name:  %s\n", ev->str);
+		break;
+	default:
+		ret += fprintf(fp, "... unknown type\n");
+		break;
+	}
+
+	return ret;
+}
+
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index cb538ade38d3..d39fd61db4c0 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -119,6 +119,7 @@ int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
 				    union perf_event *event,
 				    struct perf_evlist **pevlist);
+size_t perf_event__fprintf_attr_update(union perf_event *event, FILE *fp);
 
 int perf_event__synthesize_tracing_data(struct perf_tool *tool,
 					int fd, struct perf_evlist *evlist,
-- 
2.4.3


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

* [PATCH 23/56] perf report: Display newly added events in raw dump
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (21 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 22/56] perf tools: Add perf_event__fprintf_attr_update function Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 24/56] perf tools: Introduce stat feature Jiri Olsa
                   ` (33 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

The 'perf report -D' command will now display dump
and detailed output for newly added events:

  attr_update
  thread_map
  cpu_map
  stat
  stat_config
  stat_round

Link: http://lkml.kernel.org/n/tip-8dgrmsf866ltq2s86d1zezvm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 47152ae58f66..dd5af1acce2c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -17,6 +17,7 @@
 #include "asm/bug.h"
 #include "auxtrace.h"
 #include "thread-stack.h"
+#include "stat.h"
 
 static int perf_session__deliver_event(struct perf_session *session,
 				       union perf_event *event,
@@ -210,6 +211,9 @@ static int process_event_synth_attr_update_stub(struct perf_tool *tool __maybe_u
 						struct perf_evlist **pevlist
 						__maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_attr_update(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -310,6 +314,9 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
 				  union perf_event *event __maybe_unused,
 				  struct perf_session *session __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_thread_map(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -319,6 +326,9 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
 			       union perf_event *event __maybe_unused,
 			       struct perf_session *session __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_cpu_map(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -328,6 +338,9 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
 				   union perf_event *event __maybe_unused,
 				   struct perf_session *session __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_stat_config(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -337,6 +350,9 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
 			     struct perf_session *perf_session
 			     __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_stat(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -346,6 +362,9 @@ static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
 				   struct perf_session *perf_session
 				   __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_stat_round(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
-- 
2.4.3


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

* [PATCH 24/56] perf tools: Introduce stat feature
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (22 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 23/56] perf report: Display newly added events in raw dump Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 25/56] perf tools: Move id_offset out of struct perf_evsel union Jiri Olsa
                   ` (32 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Introducing stat feature to mark perf.data as created by
perf stat record command. It contains no data.

It's needed for report tools (report/script) to differentiate
sampling data from stat data, because they need to be treated
in a different way.

In future it might be used to store version of the stat
storage system we used.

Link: http://lkml.kernel.org/n/tip-56xpt7m6au4d8u39nffoqgx1@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c |  2 ++
 tools/perf/util/header.c    | 14 ++++++++++++++
 tools/perf/util/header.h    |  1 +
 3 files changed, 17 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 24ace2f318c1..99b690b51bff 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -451,6 +451,8 @@ static void record__init_features(struct record *rec)
 
 	if (!rec->opts.full_auxtrace)
 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
+
+	perf_header__clear_feat(&session->header, HEADER_STAT);
 }
 
 static volatile int workload_exec_errno;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index f35e8355cb1f..09baecf79036 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -868,6 +868,13 @@ static int write_auxtrace(int fd, struct perf_header *h,
 	return err;
 }
 
+static int write_stat(int fd __maybe_unused,
+		      struct perf_header *h __maybe_unused,
+		      struct perf_evlist *evlist __maybe_unused)
+{
+	return 0;
+}
+
 static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
 			   FILE *fp)
 {
@@ -1159,6 +1166,12 @@ static void print_auxtrace(struct perf_header *ph __maybe_unused,
 	fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
 }
 
+static void print_stat(struct perf_header *ph __maybe_unused,
+		       int fd __maybe_unused, FILE *fp)
+{
+	fprintf(fp, "# contains stat data\n");
+}
+
 static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
 			       FILE *fp)
 {
@@ -1948,6 +1961,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPP(HEADER_PMU_MAPPINGS,	pmu_mappings),
 	FEAT_OPP(HEADER_GROUP_DESC,	group_desc),
 	FEAT_OPP(HEADER_AUXTRACE,	auxtrace),
+	FEAT_OPA(HEADER_STAT,		stat),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d39fd61db4c0..51b8f6c2ee6f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -31,6 +31,7 @@ enum {
 	HEADER_PMU_MAPPINGS,
 	HEADER_GROUP_DESC,
 	HEADER_AUXTRACE,
+	HEADER_STAT,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };
-- 
2.4.3


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

* [PATCH 25/56] perf tools: Move id_offset out of struct perf_evsel union
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (23 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 24/56] perf tools: Introduce stat feature Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 26/56] perf stat: Rename perf_stat struct into perf_stat_evsel Jiri Olsa
                   ` (31 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Because following stat patches use id_offset together
with priv pointer.

Link: http://lkml.kernel.org/n/tip-ts3nkj35lx54whb649by02py@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/evsel.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 02a5fed8d924..0e22c0b7dab5 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -90,9 +90,9 @@ struct perf_evsel {
 	double			scale;
 	const char		*unit;
 	struct event_format	*tp_format;
+	off_t			id_offset;
 	union {
 		void		*priv;
-		off_t		id_offset;
 		u64		db_id;
 	};
 	struct cgroup_sel	*cgrp;
-- 
2.4.3


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

* [PATCH 26/56] perf stat: Rename perf_stat struct into perf_stat_evsel
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (24 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 25/56] perf tools: Move id_offset out of struct perf_evsel union Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 27/56] perf stat: Add AGGR_UNSET mode Jiri Olsa
                   ` (30 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

It's used as the perf_evsel::priv data, so the name
suits better. Also we'll need the perf_stat name
free for more generic struct.

Link: http://lkml.kernel.org/n/tip-sajxmhozt3ltu69sxguktyy3@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c |  4 ++--
 tools/perf/util/stat.c    | 10 +++++-----
 tools/perf/util/stat.h    |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5ef88f760b12..184057295970 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -434,7 +434,7 @@ static void print_noise_pct(double total, double avg)
 
 static void print_noise(struct perf_evsel *evsel, double avg)
 {
-	struct perf_stat *ps;
+	struct perf_stat_evsel *ps;
 
 	if (run_count == 1)
 		return;
@@ -671,7 +671,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
 static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 {
 	FILE *output = stat_config.output;
-	struct perf_stat *ps = counter->priv;
+	struct perf_stat_evsel *ps = counter->priv;
 	double avg = avg_stats(&ps->res_stats[0]);
 	int scaled = counter->counts->scaled;
 	double uval;
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 0db0f8c05d5e..c9f361e097d6 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg)
 bool __perf_evsel_stat__is(struct perf_evsel *evsel,
 			   enum perf_stat_evsel_id id)
 {
-	struct perf_stat *ps = evsel->priv;
+	struct perf_stat_evsel *ps = evsel->priv;
 
 	return ps->id == id;
 }
@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
 
 void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 {
-	struct perf_stat *ps = evsel->priv;
+	struct perf_stat_evsel *ps = evsel->priv;
 	int i;
 
 	/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
 {
 	int i;
-	struct perf_stat *ps = evsel->priv;
+	struct perf_stat_evsel *ps = evsel->priv;
 
 	for (i = 0; i < 3; i++)
 		init_stats(&ps->res_stats[i]);
@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
 
 int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
 {
-	evsel->priv = zalloc(sizeof(struct perf_stat));
+	evsel->priv = zalloc(sizeof(struct perf_stat_evsel));
 	if (evsel->priv == NULL)
 		return -ENOMEM;
 	perf_evsel__reset_stat_priv(evsel);
@@ -304,7 +304,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
 			      struct perf_evsel *counter)
 {
 	struct perf_counts_values *aggr = &counter->counts->aggr;
-	struct perf_stat *ps = counter->priv;
+	struct perf_stat_evsel *ps = counter->priv;
 	u64 *count = counter->counts->aggr.values;
 	int i, ret;
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index f313955a24f2..b4ade679320d 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -20,7 +20,7 @@ enum perf_stat_evsel_id {
 	PERF_STAT_EVSEL_ID__MAX,
 };
 
-struct perf_stat {
+struct perf_stat_evsel {
 	struct stats		res_stats[3];
 	enum perf_stat_evsel_id	id;
 };
-- 
2.4.3


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

* [PATCH 27/56] perf stat: Add AGGR_UNSET mode
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (25 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 26/56] perf stat: Rename perf_stat struct into perf_stat_evsel Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 28/56] perf stat record: Add record command Jiri Olsa
                   ` (29 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding AGGR_UNSET mode, so we could distinguish
unset aggr_mode in following patches.

Link: http://lkml.kernel.org/n/tip-26j5x8z8p5n7yeb2s846yvag@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 +++++
 tools/perf/util/stat.c    | 1 +
 tools/perf/util/stat.h    | 1 +
 3 files changed, 7 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 184057295970..abeb15aebd12 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -479,6 +479,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 		break;
 	case AGGR_GLOBAL:
+	case AGGR_UNSET:
 	default:
 		break;
 	}
@@ -799,6 +800,8 @@ static void print_interval(char *prefix, struct timespec *ts)
 		case AGGR_GLOBAL:
 		default:
 			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
+		case AGGR_UNSET:
+			break;
 		}
 	}
 
@@ -880,6 +883,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 		evlist__for_each(evsel_list, counter)
 			print_counter(counter, prefix);
 		break;
+	case AGGR_UNSET:
 	default:
 		break;
 	}
@@ -960,6 +964,7 @@ static int perf_stat_init_aggr_mode(void)
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
 	case AGGR_THREAD:
+	case AGGR_UNSET:
 	default:
 		break;
 	}
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index c9f361e097d6..45efa520427a 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -272,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
 			aggr->ena += count->ena;
 			aggr->run += count->run;
 		}
+	case AGGR_UNSET:
 	default:
 		break;
 	}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index b4ade679320d..086f4e128d63 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -31,6 +31,7 @@ enum aggr_mode {
 	AGGR_SOCKET,
 	AGGR_CORE,
 	AGGR_THREAD,
+	AGGR_UNSET,
 };
 
 struct perf_stat_config {
-- 
2.4.3


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

* [PATCH 28/56] perf stat record: Add record command
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (26 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 27/56] perf stat: Add AGGR_UNSET mode Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 29/56] perf stat record: Initialize record features Jiri Olsa
                   ` (28 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Add 'perf stat record' command support. It creates simple
(header only) perf.data file ATM.

Link: http://lkml.kernel.org/n/tip-0av5yfkwyywwgoiali88w4hi@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt | 12 ++++++
 tools/perf/builtin-stat.c              | 74 +++++++++++++++++++++++++++++++++-
 2 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 4e074a660826..70eee1c2c444 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -10,6 +10,7 @@ SYNOPSIS
 [verse]
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
+'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>]
 
 DESCRIPTION
 -----------
@@ -22,6 +23,8 @@ OPTIONS
 <command>...::
 	Any command you can specify in a shell.
 
+record::
+	See STAT RECORD.
 
 -e::
 --event=::
@@ -159,6 +162,15 @@ filter out the startup phase of the program, which is often very different.
 
 Print statistics of transactional execution if supported.
 
+STAT RECORD
+-----------
+Stores stat data into perf data file.
+
+-o file::
+--output file::
+Output file name.
+
+
 EXAMPLES
 --------
 
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index abeb15aebd12..a909160bdf8e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -59,6 +59,7 @@
 #include "util/thread.h"
 #include "util/thread_map.h"
 #include "util/counts.h"
+#include "util/session.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -121,6 +122,16 @@ static struct timespec		ref_time;
 static struct cpu_map		*aggr_map;
 static int			(*aggr_get_id)(struct cpu_map *m, int cpu);
 
+struct perf_stat {
+	bool			 record;
+	struct perf_data_file	 file;
+	struct perf_session	*session;
+	u64			 bytes_written;
+};
+
+static struct perf_stat		perf_stat;
+#define STAT_RECORD		perf_stat.record
+
 static volatile int done = 0;
 
 static struct perf_stat_config stat_config = {
@@ -339,6 +350,15 @@ static int __run_perf_stat(int argc, const char **argv)
 		return -1;
 	}
 
+	if (STAT_RECORD) {
+		int err, fd = perf_data_file__fd(&perf_stat.file);
+
+		err = perf_session__write_header(perf_stat.session, evsel_list,
+						 fd, false);
+		if (err < 0)
+			return err;
+	}
+
 	/*
 	 * Enable counters and exec the command:
 	 */
@@ -1130,6 +1150,39 @@ static int add_default_attributes(void)
 	return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
 }
 
+static const char * const recort_usage[] = {
+	"perf stat record [<options>]",
+	NULL,
+};
+
+static int __cmd_record(int argc, const char **argv)
+{
+	struct perf_session *session;
+	struct perf_data_file *file = &perf_stat.file;
+	const struct option options[] = {
+	OPT_STRING('o', "output", &perf_stat.file.path, "file", "output file name"),
+	OPT_END()
+	};
+
+	argc = parse_options(argc, argv, options, record_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
+	session = perf_session__new(file, false, NULL);
+	if (session == NULL) {
+		pr_err("Perf session creation failed.\n");
+		return -1;
+	}
+
+	/* No pipe support ATM */
+	if (perf_stat.file.is_pipe)
+		return -EINVAL;
+
+	session->evlist   = evsel_list;
+	perf_stat.session = session;
+	perf_stat.record  = true;
+	return argc;
+}
+
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	bool append_file = false;
@@ -1203,6 +1256,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	const char *mode;
 	FILE *output = stderr;
 	unsigned int interval;
+	const char * const stat_subcommands[] = { "record" };
 
 	setlocale(LC_ALL, "");
 
@@ -1210,8 +1264,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (evsel_list == NULL)
 		return -ENOMEM;
 
-	argc = parse_options(argc, argv, options, stat_usage,
-		PARSE_OPT_STOP_AT_NON_OPTION);
+	argc = parse_options_subcommand(argc, argv, options, stat_subcommands,
+					(const char **) stat_usage,
+					PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc && !strncmp(argv[0], "rec", 3)) {
+		argc = __cmd_record(argc, argv);
+		if (argc < 0)
+			return -1;
+	}
 
 	interval = stat_config.interval;
 
@@ -1382,6 +1443,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (!forever && status != -1 && !interval)
 		print_counters(NULL, argc, argv);
 
+	if (STAT_RECORD) {
+		int fd = perf_data_file__fd(&perf_stat.file);
+
+		perf_stat.session->header.data_size += perf_stat.bytes_written;
+		perf_session__write_header(perf_stat.session, evsel_list, fd, true);
+
+		perf_session__delete(perf_stat.session);
+	}
+
 	perf_evlist__free_stats(evsel_list);
 out:
 	perf_evlist__delete(evsel_list);
-- 
2.4.3


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

* [PATCH 29/56] perf stat record: Initialize record features
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (27 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 28/56] perf stat record: Add record command Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 30/56] perf stat record: Synthesize stat record data Jiri Olsa
                   ` (27 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Disabling all non stat related features.

Link: http://lkml.kernel.org/n/tip-0av5yfkwyywwgoiali88w4hi@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a909160bdf8e..d5645109766b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1155,6 +1155,19 @@ static const char * const recort_usage[] = {
 	NULL,
 };
 
+static void init_features(struct perf_session *session)
+{
+	int feat;
+
+	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
+		perf_header__set_feat(&session->header, feat);
+
+	perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
+	perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
+	perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
+	perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
+}
+
 static int __cmd_record(int argc, const char **argv)
 {
 	struct perf_session *session;
@@ -1177,6 +1190,8 @@ static int __cmd_record(int argc, const char **argv)
 	if (perf_stat.file.is_pipe)
 		return -EINVAL;
 
+	init_features(session);
+
 	session->evlist   = evsel_list;
 	perf_stat.session = session;
 	perf_stat.record  = true;
-- 
2.4.3


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

* [PATCH 30/56] perf stat record: Synthesize stat record data
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (28 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 29/56] perf stat record: Initialize record features Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 31/56] perf stat record: Store events IDs in perf data file Jiri Olsa
                   ` (26 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Synthesizing needed stat record data for report/script:
  - cpu/thread maps
  - stat config

Link: http://lkml.kernel.org/n/tip-wni1s2i2sq17g4vomjyda2yf@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d5645109766b..dd986b14b985 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -191,6 +191,20 @@ static inline int nsec_counter(struct perf_evsel *evsel)
 	return 0;
 }
 
+static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_sample *sample __maybe_unused,
+				     struct machine *machine __maybe_unused)
+{
+	if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) {
+		pr_err("failed to write perf data, error: %m\n");
+		return -1;
+	}
+
+	perf_stat.bytes_written += event->header.size;
+	return 0;
+}
+
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -277,6 +291,35 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
+static int perf_stat_synthesize_config(void)
+{
+	int err;
+
+	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
+						process_synthesized_event,
+						NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
+					     process_synthesized_event, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_stat_config(NULL, &stat_config,
+						 process_synthesized_event, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize config.\n");
+		return err;
+	}
+
+	return 0;
+}
+
 static int __run_perf_stat(int argc, const char **argv)
 {
 	int interval = stat_config.interval;
@@ -357,6 +400,10 @@ static int __run_perf_stat(int argc, const char **argv)
 						 fd, false);
 		if (err < 0)
 			return err;
+
+		err = perf_stat_synthesize_config();
+		if (err < 0)
+			return err;
 	}
 
 	/*
-- 
2.4.3


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

* [PATCH 31/56] perf stat record: Store events IDs in perf data file
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (29 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 30/56] perf stat record: Synthesize stat record data Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 32/56] perf stat record: Add pipe support for record command Jiri Olsa
                   ` (25 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Store event IDs in evlist object so it get stored
into perf.data file.

Also making perf_evlist__id_add_fd global.

Link: http://lkml.kernel.org/n/tip-v2xwpeots3tz08e44lej5y9e@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 35 +++++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.c  |  6 +++---
 tools/perf/util/evlist.h  |  3 +++
 3 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index dd986b14b985..39a6ecd532b6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -320,6 +320,38 @@ static int perf_stat_synthesize_config(void)
 	return 0;
 }
 
+#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+
+static int __store_counter_ids(struct perf_evsel *counter,
+			       struct cpu_map *cpus,
+			       struct thread_map *threads)
+{
+	int cpu, thread;
+
+	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		for (thread = 0; thread < threads->nr; thread++) {
+			int fd = FD(counter, cpu, thread);
+
+			if (perf_evlist__id_add_fd(evsel_list, counter,
+						   cpu, thread, fd) < 0)
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int store_counter_ids(struct perf_evsel *counter)
+{
+	struct cpu_map *cpus = counter->cpus;
+	struct thread_map *threads = counter->threads;
+
+	if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
+		return -ENOMEM;
+
+	return __store_counter_ids(counter, cpus, threads);
+}
+
 static int __run_perf_stat(int argc, const char **argv)
 {
 	int interval = stat_config.interval;
@@ -384,6 +416,9 @@ static int __run_perf_stat(int argc, const char **argv)
 		l = strlen(counter->unit);
 		if (l > unit_width)
 			unit_width = l;
+
+		if (STAT_RECORD && store_counter_ids(counter))
+			return -1;
 	}
 
 	if (perf_evlist__apply_filters(evsel_list, &counter)) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d1392194a9a9..8069a6a588df 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -550,9 +550,9 @@ void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 	evsel->id[evsel->ids++] = id;
 }
 
-static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
-				  struct perf_evsel *evsel,
-				  int cpu, int thread, int fd)
+int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+			   struct perf_evsel *evsel,
+			   int cpu, int thread, int fd)
 {
 	u64 read_data[4] = { 0, };
 	int id_idx = 1; /* The first entry is the counter value */
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a459fe71b452..139a50038097 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -97,6 +97,9 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
 
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 			 int cpu, int thread, u64 id);
+int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+			   struct perf_evsel *evsel,
+			   int cpu, int thread, int fd);
 
 int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
 int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
-- 
2.4.3


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

* [PATCH 32/56] perf stat record: Add pipe support for record command
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (30 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 31/56] perf stat record: Store events IDs in perf data file Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 33/56] perf stat record: Write stat events on record Jiri Olsa
                   ` (24 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Allowing storing stat record data into pipe, so report
tools (report/script) could read data directly from
record.

Link: http://lkml.kernel.org/n/tip-m8fj758gty57hgvss5efy6na@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 39 ++++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 39a6ecd532b6..539566eeea97 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -291,10 +291,19 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
-static int perf_stat_synthesize_config(void)
+static int perf_stat_synthesize_config(bool is_pipe)
 {
 	int err;
 
+	if (is_pipe) {
+		err = perf_event__synthesize_attrs(NULL, perf_stat.session,
+						   process_synthesized_event);
+		if (err < 0) {
+			pr_err("Couldn't synthesize attrs.\n");
+			return err;
+		}
+	}
+
 	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
 						process_synthesized_event,
 						NULL);
@@ -362,6 +371,7 @@ static int __run_perf_stat(int argc, const char **argv)
 	size_t l;
 	int status = 0;
 	const bool forks = (argc > 0);
+	bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false;
 
 	if (interval) {
 		ts.tv_sec  = interval / 1000;
@@ -372,7 +382,7 @@ static int __run_perf_stat(int argc, const char **argv)
 	}
 
 	if (forks) {
-		if (perf_evlist__prepare_workload(evsel_list, &target, argv, false,
+		if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
 						  workload_exec_failed_signal) < 0) {
 			perror("failed to prepare workload");
 			return -1;
@@ -431,12 +441,17 @@ static int __run_perf_stat(int argc, const char **argv)
 	if (STAT_RECORD) {
 		int err, fd = perf_data_file__fd(&perf_stat.file);
 
-		err = perf_session__write_header(perf_stat.session, evsel_list,
-						 fd, false);
+		if (is_pipe) {
+			err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file));
+		} else {
+			err = perf_session__write_header(perf_stat.session, evsel_list,
+							 fd, false);
+		}
+
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config();
+		err = perf_stat_synthesize_config(is_pipe);
 		if (err < 0)
 			return err;
 	}
@@ -963,6 +978,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
+	/* Do not print anything if we record to the pipe. */
+	if (STAT_RECORD && perf_stat.file.is_pipe)
+		return;
+
 	if (interval)
 		print_interval(prefix = buf, ts);
 	else
@@ -1268,10 +1287,6 @@ static int __cmd_record(int argc, const char **argv)
 		return -1;
 	}
 
-	/* No pipe support ATM */
-	if (perf_stat.file.is_pipe)
-		return -EINVAL;
-
 	init_features(session);
 
 	session->evlist   = evsel_list;
@@ -1543,8 +1558,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (STAT_RECORD) {
 		int fd = perf_data_file__fd(&perf_stat.file);
 
-		perf_stat.session->header.data_size += perf_stat.bytes_written;
-		perf_session__write_header(perf_stat.session, evsel_list, fd, true);
+		if (!perf_stat.file.is_pipe) {
+			perf_stat.session->header.data_size += perf_stat.bytes_written;
+			perf_session__write_header(perf_stat.session, evsel_list, fd, true);
+		}
 
 		perf_session__delete(perf_stat.session);
 	}
-- 
2.4.3


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

* [PATCH 33/56] perf stat record: Write stat events on record
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (31 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 32/56] perf stat record: Add pipe support for record command Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 34/56] perf stat record: Write stat round " Jiri Olsa
                   ` (23 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Writing stat events on 'perf stat record' at the time
we read counter values from kernel.

Link: http://lkml.kernel.org/n/tip-ojc826gy0x9jj74elbjfccej@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 539566eeea97..81ba5955b1da 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -205,6 +205,18 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
+
+static int
+perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
+			     struct perf_counts_values *count)
+{
+	struct perf_sample_id *sid = SID(counter, cpu, thread);
+
+	return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count,
+					   process_synthesized_event, NULL);
+}
+
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -228,6 +240,13 @@ static int read_counter(struct perf_evsel *counter)
 			count = perf_counts(counter->counts, cpu, thread);
 			if (perf_evsel__read(counter, cpu, thread, count))
 				return -1;
+
+			if (STAT_RECORD) {
+				if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
+					pr_err("failed to write stat event\n");
+					return -1;
+				}
+			}
 		}
 	}
 
-- 
2.4.3


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

* [PATCH 34/56] perf stat record: Write stat round events on record
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (32 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 33/56] perf stat record: Write stat events on record Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 35/56] perf stat record: Do not allow record with multiple runs mode Jiri Olsa
                   ` (22 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Writing stat round events on 'perf stat record' for
each interval round. In non interval mode we store
round event after the last stat event.

Link: http://lkml.kernel.org/n/tip-a43rs4c6szofeuo2gjlcpm0h@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 81ba5955b1da..f053447fde6e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -205,6 +205,16 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int write_stat_round_event(u64 time, u64 type)
+{
+	return perf_event__synthesize_stat_round(NULL, time, type,
+						 process_synthesized_event,
+						 NULL);
+}
+
+#define WRITE_STAT_ROUND_EVENT(time, interval) \
+	write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval)
+
 #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
 
 static int
@@ -280,6 +290,11 @@ static void process_interval(void)
 	clock_gettime(CLOCK_MONOTONIC, &ts);
 	diff_timespec(&rs, &ts, &ref_time);
 
+	if (STAT_RECORD) {
+		if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec, INTERVAL))
+			pr_err("failed to write stat round event\n");
+	}
+
 	print_counters(&rs, 0, NULL);
 }
 
@@ -1577,6 +1592,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (STAT_RECORD) {
 		int fd = perf_data_file__fd(&perf_stat.file);
 
+		if (!interval) {
+			if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))
+				pr_err("failed to write stat round event\n");
+		}
+
 		if (!perf_stat.file.is_pipe) {
 			perf_stat.session->header.data_size += perf_stat.bytes_written;
 			perf_session__write_header(perf_stat.session, evsel_list, fd, true);
-- 
2.4.3


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

* [PATCH 35/56] perf stat record: Do not allow record with multiple runs mode
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (33 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 34/56] perf stat record: Write stat round " Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 36/56] perf stat record: Synthesize attr update events Jiri Olsa
                   ` (21 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

We currently don't support storing multiple session in perf.data,
so we can't allow -r option in stat record.

   $ perf stat -e cycles -r 2 record ls
   Cannot use -r option with perf stat record.

Link: http://lkml.kernel.org/n/tip-wulio303py16c5hbbo8zrib6@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f053447fde6e..67630d490a1c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1315,6 +1315,11 @@ static int __cmd_record(int argc, const char **argv)
 	argc = parse_options(argc, argv, options, record_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
+	if (run_count != 1 || forever) {
+		pr_err("Cannot use -r option with perf stat record.\n");
+		return -1;
+	}
+
 	session = perf_session__new(file, false, NULL);
 	if (session == NULL) {
 		pr_err("Perf session creation failed.\n");
-- 
2.4.3


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

* [PATCH 36/56] perf stat record: Synthesize attr update events
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (34 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 35/56] perf stat record: Do not allow record with multiple runs mode Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 37/56] perf tools: Add cpu_map__empty_new interface Jiri Olsa
                   ` (20 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Synthesize other events stuff not carried within
attr event - unit, scale, name.

Link: http://lkml.kernel.org/n/tip-dzt1cls17hvc9nowg778z7vm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 67630d490a1c..ad4d1241484a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -325,8 +325,19 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
+static bool has_unit(struct perf_evsel *counter)
+{
+	return counter->unit && *counter->unit;
+}
+
+static bool has_scale(struct perf_evsel *counter)
+{
+	return counter->scale != 1;
+}
+
 static int perf_stat_synthesize_config(bool is_pipe)
 {
+	struct perf_evsel *counter;
 	int err;
 
 	if (is_pipe) {
@@ -338,6 +349,46 @@ static int perf_stat_synthesize_config(bool is_pipe)
 		}
 	}
 
+	/*
+	 * Synthesize other events stuff not carried within
+	 * attr event - unit, scale, name
+	 */
+	evlist__for_each(evsel_list, counter) {
+		if (!counter->supported)
+			continue;
+
+		/*
+		 * Synthesize unit and scale only if it's defined.
+		 */
+		if (has_unit(counter)) {
+			err = perf_event__synthesize_attr_update_unit(NULL, counter, process_synthesized_event);
+			if (err < 0) {
+				pr_err("Couldn't synthesize evsel unit.\n");
+				return err;
+			}
+		}
+
+		if (has_scale(counter)) {
+			err = perf_event__synthesize_attr_update_scale(NULL, counter, process_synthesized_event);
+			if (err < 0) {
+				pr_err("Couldn't synthesize evsel scale.\n");
+				return err;
+			}
+		}
+
+		/*
+		 * Name is needed only for pipe output,
+		 * perf.data carries event names.
+		 */
+		if (is_pipe) {
+			err = perf_event__synthesize_attr_update_name(NULL, counter, process_synthesized_event);
+			if (err < 0) {
+				pr_err("Couldn't synthesize evsel name.\n");
+				return err;
+			}
+		}
+	}
+
 	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
 						process_synthesized_event,
 						NULL);
-- 
2.4.3


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

* [PATCH 37/56] perf tools: Add cpu_map__empty_new interface
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (35 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 36/56] perf stat record: Synthesize attr update events Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 38/56] perf tools: Make cpu_map__build_map global Jiri Olsa
                   ` (19 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding cpu_map__empty_new interface to create empty cpumap
with given size. The cpumap entries are initialized with -1.

It'll be used for caching cpu_map in following patches.

Link: http://lkml.kernel.org/n/tip-2q9tmp3shdscmtiv6h8afhvd@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/cpumap.c | 17 +++++++++++++++++
 tools/perf/util/cpumap.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index e44849ad2c9c..891af6a5efed 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -230,6 +230,23 @@ struct cpu_map *cpu_map__dummy_new(void)
 	return cpus;
 }
 
+struct cpu_map *cpu_map__empty_new(int nr)
+{
+	struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr);
+
+	if (cpus != NULL) {
+		int i;
+
+		cpus->nr = nr;
+		for (i = 0; i < nr; i++)
+			cpus->map[i] = -1;
+
+		atomic_set(&cpus->refcnt, 1);
+	}
+
+	return cpus;
+}
+
 static void cpu_map__delete(struct cpu_map *map)
 {
 	if (map) {
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index c5b28dd18f6b..1f536164050b 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -17,6 +17,7 @@ struct cpu_map {
 struct cpu_map_event;
 
 struct cpu_map *cpu_map__new(const char *cpu_list);
+struct cpu_map *cpu_map__empty_new(int nr);
 struct cpu_map *cpu_map__dummy_new(void);
 struct cpu_map *cpu_map__new_event(struct cpu_map_event *event);
 struct cpu_map *cpu_map__read(FILE *file);
-- 
2.4.3


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

* [PATCH 38/56] perf tools: Make cpu_map__build_map global
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (36 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 37/56] perf tools: Add cpu_map__empty_new interface Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 39/56] perf tools: Add data arg to cpu_map__build_map callback Jiri Olsa
                   ` (18 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

We'll need to call it from perf stat in following patches.

Link: http://lkml.kernel.org/n/tip-yh8s2m4cz0hfrr6mmldtww8r@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/cpumap.c | 4 ++--
 tools/perf/util/cpumap.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 891af6a5efed..6d0a2ddf4eba 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -302,8 +302,8 @@ static int cmp_ids(const void *a, const void *b)
 	return *(int *)a - *(int *)b;
 }
 
-static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
-			      int (*f)(struct cpu_map *map, int cpu))
+int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
+		       int (*f)(struct cpu_map *map, int cpu))
 {
 	struct cpu_map *c;
 	int nr = cpus->nr;
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 1f536164050b..74f0151c3fab 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -91,4 +91,6 @@ static inline int cpu__get_node(int cpu)
 	return cpunode_map[cpu];
 }
 
+int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
+		       int (*f)(struct cpu_map *map, int cpu));
 #endif /* __PERF_CPUMAP_H */
-- 
2.4.3


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

* [PATCH 39/56] perf tools: Add data arg to cpu_map__build_map callback
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (37 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 38/56] perf tools: Make cpu_map__build_map global Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 40/56] perf stat report: Cache aggregated map entries in extra cpumap Jiri Olsa
                   ` (17 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding data arg to cpu_map__build_map callback, so we could
pass data along to the callback. It'll be needed in following
patches to retrieve topology info from perf.data.

Link: http://lkml.kernel.org/n/tip-tv914j1vjnexg3fhq0q55h23@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c   | 14 ++++++++++++--
 tools/perf/tests/topology.c |  4 ++--
 tools/perf/util/cpumap.c    | 15 ++++++++-------
 tools/perf/util/cpumap.h    |  7 ++++---
 tools/perf/util/stat.c      |  2 +-
 5 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index ad4d1241484a..9ce8ce6377ab 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1150,6 +1150,16 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
 	return 0;
 }
 
+static int perf_stat__get_socket(struct cpu_map *map, int cpu)
+{
+	return cpu_map__get_socket(map, cpu, NULL);
+}
+
+static int perf_stat__get_core(struct cpu_map *map, int cpu)
+{
+	return cpu_map__get_core(map, cpu, NULL);
+}
+
 static int perf_stat_init_aggr_mode(void)
 {
 	switch (stat_config.aggr_mode) {
@@ -1158,14 +1168,14 @@ static int perf_stat_init_aggr_mode(void)
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = cpu_map__get_socket;
+		aggr_get_id = perf_stat__get_socket;
 		break;
 	case AGGR_CORE:
 		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = cpu_map__get_core;
+		aggr_get_id = perf_stat__get_core;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index c3aff53a976a..f5bb096c3bd9 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -73,10 +73,10 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
 
 	for (i = 0; i < map->nr; i++) {
 		TEST_ASSERT_VAL("Core ID doesn't match",
-			(session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i) & 0xffff)));
+			(session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff)));
 
 		TEST_ASSERT_VAL("Socket ID doesn't match",
-			(session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i)));
+			(session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL)));
 	}
 
 	perf_session__delete(session);
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 6d0a2ddf4eba..52d3f8bbf733 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -285,7 +285,7 @@ int cpu_map__get_socket_id(int cpu)
 	return ret ?: value;
 }
 
-int cpu_map__get_socket(struct cpu_map *map, int idx)
+int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused)
 {
 	int cpu;
 
@@ -303,7 +303,8 @@ static int cmp_ids(const void *a, const void *b)
 }
 
 int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
-		       int (*f)(struct cpu_map *map, int cpu))
+		       int (*f)(struct cpu_map *map, int cpu, void *data),
+		       void *data)
 {
 	struct cpu_map *c;
 	int nr = cpus->nr;
@@ -315,7 +316,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
 		return -1;
 
 	for (cpu = 0; cpu < nr; cpu++) {
-		s1 = f(cpus, cpu);
+		s1 = f(cpus, cpu, data);
 		for (s2 = 0; s2 < c->nr; s2++) {
 			if (s1 == c->map[s2])
 				break;
@@ -339,7 +340,7 @@ int cpu_map__get_core_id(int cpu)
 	return ret ?: value;
 }
 
-int cpu_map__get_core(struct cpu_map *map, int idx)
+int cpu_map__get_core(struct cpu_map *map, int idx, void *data)
 {
 	int cpu, s;
 
@@ -350,7 +351,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
 
 	cpu = cpu_map__get_core_id(cpu);
 
-	s = cpu_map__get_socket(map, idx);
+	s = cpu_map__get_socket(map, idx, data);
 	if (s == -1)
 		return -1;
 
@@ -365,12 +366,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
 
 int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp)
 {
-	return cpu_map__build_map(cpus, sockp, cpu_map__get_socket);
+	return cpu_map__build_map(cpus, sockp, cpu_map__get_socket, NULL);
 }
 
 int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)
 {
-	return cpu_map__build_map(cpus, corep, cpu_map__get_core);
+	return cpu_map__build_map(cpus, corep, cpu_map__get_core, NULL);
 }
 
 /* setup simple routines to easily access node numbers given a cpu number */
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 74f0151c3fab..a44eab0083bd 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -23,9 +23,9 @@ struct cpu_map *cpu_map__new_event(struct cpu_map_event *event);
 struct cpu_map *cpu_map__read(FILE *file);
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
 int cpu_map__get_socket_id(int cpu);
-int cpu_map__get_socket(struct cpu_map *map, int idx);
+int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
 int cpu_map__get_core_id(int cpu);
-int cpu_map__get_core(struct cpu_map *map, int idx);
+int cpu_map__get_core(struct cpu_map *map, int idx, void *data);
 int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
 int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
 
@@ -92,5 +92,6 @@ static inline int cpu__get_node(int cpu)
 }
 
 int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
-		       int (*f)(struct cpu_map *map, int cpu));
+		       int (*f)(struct cpu_map *map, int cpu, void *data),
+		       void *data);
 #endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 45efa520427a..0480f39c8c4a 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -230,7 +230,7 @@ static int check_per_pkg(struct perf_evsel *counter,
 	if (!(vals->run && vals->ena))
 		return 0;
 
-	s = cpu_map__get_socket(cpus, cpu);
+	s = cpu_map__get_socket(cpus, cpu, NULL);
 	if (s < 0)
 		return -1;
 
-- 
2.4.3


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

* [PATCH 40/56] perf stat report: Cache aggregated map entries in extra cpumap
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (38 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 39/56] perf tools: Add data arg to cpu_map__build_map callback Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 41/56] perf stat report: Add report command Jiri Olsa
                   ` (16 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Currently any time we need to access socket or core id for
given cpu, we access the sysfs topology file.

Adding cpus_aggr_map cpu_map to cache those entries.

Link: http://lkml.kernel.org/n/tip-2cw82b5piydhao8sft09am3r@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 60 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 9ce8ce6377ab..f38edfc1985c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -101,6 +101,8 @@ static struct target target = {
 	.uid	= UINT_MAX,
 };
 
+typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
+
 static int			run_count			=  1;
 static bool			no_inherit			= false;
 static volatile pid_t		child_pid			= -1;
@@ -120,7 +122,7 @@ static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
 static struct timespec		ref_time;
 static struct cpu_map		*aggr_map;
-static int			(*aggr_get_id)(struct cpu_map *m, int cpu);
+static aggr_get_id_t		aggr_get_id;
 
 struct perf_stat {
 	bool			 record;
@@ -1150,6 +1152,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
 	return 0;
 }
 
+
 static int perf_stat__get_socket(struct cpu_map *map, int cpu)
 {
 	return cpu_map__get_socket(map, cpu, NULL);
@@ -1160,22 +1163,63 @@ static int perf_stat__get_core(struct cpu_map *map, int cpu)
 	return cpu_map__get_core(map, cpu, NULL);
 }
 
+static int cpu_map__get_max(struct cpu_map *map)
+{
+	int i, max = -1;
+
+	for (i = 0; i < map->nr; i++) {
+		if (map->map[i] > max)
+			max = map->map[i];
+	}
+
+	return max;
+}
+
+static struct cpu_map *cpus_aggr_map;
+
+static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
+{
+	int cpu;
+
+	if (idx > map->nr)
+		return -1;
+
+	cpu = map->map[idx];
+
+	if (cpus_aggr_map->map[cpu] == -1)
+		cpus_aggr_map->map[cpu] = get_id(map, idx);
+
+	return cpus_aggr_map->map[cpu];
+}
+
+static int perf_stat__get_socket_cached(struct cpu_map *map, int idx)
+{
+	return perf_stat__get_aggr(perf_stat__get_socket, map, idx);
+}
+
+static int perf_stat__get_core_cached(struct cpu_map *map, int idx)
+{
+	return perf_stat__get_aggr(perf_stat__get_core, map, idx);
+}
+
 static int perf_stat_init_aggr_mode(void)
 {
+	int nr;
+
 	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
 		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_socket;
+		aggr_get_id = perf_stat__get_socket_cached;
 		break;
 	case AGGR_CORE:
 		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_core;
+		aggr_get_id = perf_stat__get_core_cached;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
@@ -1184,7 +1228,15 @@ static int perf_stat_init_aggr_mode(void)
 	default:
 		break;
 	}
-	return 0;
+
+	/*
+	 * The evsel_list->cpus is the base we operate on,
+	 * taking the highest cpu number to be the size of
+	 * the aggregation translate cpumap.
+	 */
+	nr = cpu_map__get_max(evsel_list->cpus);
+	cpus_aggr_map = cpu_map__empty_new(nr + 1);
+	return cpus_aggr_map ? 0 : -ENOMEM;
 }
 
 /*
-- 
2.4.3


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

* [PATCH 41/56] perf stat report: Add report command
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (39 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 40/56] perf stat report: Cache aggregated map entries in extra cpumap Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 42/56] perf stat report: Process cpu/threads maps Jiri Olsa
                   ` (15 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding 'perf stat report' command support. ATM it only
processes attr events and display nothing.

Link: http://lkml.kernel.org/n/tip-a43rs4c6szofeuo2gjlcpm0h@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt | 12 +++++++
 tools/perf/builtin-stat.c              | 61 +++++++++++++++++++++++++++++++---
 tools/perf/util/session.c              |  3 ++
 3 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 70eee1c2c444..95f492828657 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>]
+'perf stat' report [-i file]
 
 DESCRIPTION
 -----------
@@ -26,6 +27,9 @@ OPTIONS
 record::
 	See STAT RECORD.
 
+report::
+	See STAT REPORT.
+
 -e::
 --event=::
 	Select the PMU event. Selection can be:
@@ -170,6 +174,14 @@ Stores stat data into perf data file.
 --output file::
 Output file name.
 
+STAT REPORT
+-----------
+Reads and reports stat data from perf data file.
+
+-i file::
+--input file::
+Input file name.
+
 
 EXAMPLES
 --------
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f38edfc1985c..61d2abb87def 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -60,6 +60,8 @@
 #include "util/thread_map.h"
 #include "util/counts.h"
 #include "util/session.h"
+#include "util/tool.h"
+#include "asm/bug.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -129,6 +131,7 @@ struct perf_stat {
 	struct perf_data_file	 file;
 	struct perf_session	*session;
 	u64			 bytes_written;
+	struct perf_tool	 tool;
 };
 
 static struct perf_stat		perf_stat;
@@ -1028,8 +1031,8 @@ static void print_header(int argc, const char **argv)
 		else if (target.cpu_list)
 			fprintf(output, "\'CPU(s) %s", target.cpu_list);
 		else if (!target__has_task(&target)) {
-			fprintf(output, "\'%s", argv[0]);
-			for (i = 1; i < argc; i++)
+			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
+			for (i = 1; argv && (i < argc); i++)
 				fprintf(output, " %s", argv[i]);
 		} else if (target.pid)
 			fprintf(output, "process id \'%s", target.pid);
@@ -1447,6 +1450,55 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static const char * const report_usage[] = {
+	"perf stat report [<options>]",
+	NULL,
+};
+
+static struct perf_stat perf_stat = {
+	.tool = {
+		.attr		= perf_event__process_attr,
+	},
+};
+
+static int __cmd_report(int argc, const char **argv)
+{
+	struct perf_session *session;
+	const struct option options[] = {
+	OPT_STRING('i', "input", &input_name, "file", "input file name"),
+	OPT_END()
+	};
+	struct stat st;
+	int ret;
+
+	argc = parse_options(argc, argv, options, report_usage, 0);
+
+	if (!input_name || !strlen(input_name)) {
+		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
+			input_name = "-";
+		else
+			input_name = "perf.data";
+	}
+
+	perf_stat.file.path = input_name;
+	perf_stat.file.mode = PERF_DATA_MODE_READ;
+
+	session = perf_session__new(&perf_stat.file, false, &perf_stat.tool);
+	if (session == NULL)
+		return -1;
+
+	perf_stat.session  = session;
+	stat_config.output = stderr;
+	evsel_list         = session->evlist;
+
+	ret = perf_session__process_events(session);
+	if (ret)
+		return ret;
+
+	perf_session__delete(session);
+	return 0;
+}
+
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	bool append_file = false;
@@ -1520,7 +1572,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	const char *mode;
 	FILE *output = stderr;
 	unsigned int interval;
-	const char * const stat_subcommands[] = { "record" };
+	const char * const stat_subcommands[] = { "record", "report" };
 
 	setlocale(LC_ALL, "");
 
@@ -1536,7 +1588,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		argc = __cmd_record(argc, argv);
 		if (argc < 0)
 			return -1;
-	}
+	} else if (argc && !strncmp(argv[0], "rep", 3))
+		return __cmd_report(argc, argv);
 
 	interval = stat_config.interval;
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index dd5af1acce2c..9072dd252eb1 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -37,6 +37,9 @@ static int perf_session__open(struct perf_session *session)
 	if (perf_data_file__is_pipe(file))
 		return 0;
 
+	if (perf_header__has_feat(&session->header, HEADER_STAT))
+		return 0;
+
 	if (!perf_evlist__valid_sample_type(session->evlist)) {
 		pr_err("non matching sample_type");
 		return -1;
-- 
2.4.3


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

* [PATCH 42/56] perf stat report: Process cpu/threads maps
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (40 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 41/56] perf stat report: Add report command Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 43/56] perf stat report: Process stat config event Jiri Olsa
                   ` (14 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding processing of cpu/threads maps. Configuring session's
evlist with these maps.

Link: http://lkml.kernel.org/n/tip-f2bo5wm0cw76zc5qsjm4pztx@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 61d2abb87def..bcb9a6f85a1e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -132,6 +132,9 @@ struct perf_stat {
 	struct perf_session	*session;
 	u64			 bytes_written;
 	struct perf_tool	 tool;
+	bool			 maps_allocated;
+	struct cpu_map		*cpus;
+	struct thread_map	*threads;
 };
 
 static struct perf_stat		perf_stat;
@@ -1450,6 +1453,63 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static int set_maps(struct perf_stat *stat)
+{
+	if (!stat->cpus || !stat->threads)
+		return 0;
+
+	if (WARN_ONCE(stat->maps_allocated, "stats double allocation\n"))
+		return -EINVAL;
+
+	perf_evlist__set_maps(evsel_list, stat->cpus, stat->threads);
+
+	if (perf_evlist__alloc_stats(evsel_list, true))
+		return -ENOMEM;
+
+	stat->maps_allocated = true;
+	return 0;
+}
+
+static
+int process_thread_map_event(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event,
+			     struct perf_session *session __maybe_unused)
+{
+	struct perf_stat *stat = container_of(tool, struct perf_stat, tool);
+
+	if (stat->threads) {
+		pr_warning("Extra thread map event, ignoring.\n");
+		return 0;
+	}
+
+	stat->threads = thread_map__new_event(&event->thread_map);
+	if (!stat->threads)
+		return -ENOMEM;
+
+	return set_maps(stat);
+}
+
+static
+int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
+			  union perf_event *event,
+			  struct perf_session *session __maybe_unused)
+{
+	struct perf_stat *stat = container_of(tool, struct perf_stat, tool);
+	struct cpu_map *cpus;
+
+	if (stat->cpus) {
+		pr_warning("Extra cpu map event, ignoring.\n");
+		return 0;
+	}
+
+	cpus = cpu_map__new_event(&event->cpu_map);
+	if (!cpus)
+		return -ENOMEM;
+
+	stat->cpus = cpus;
+	return set_maps(stat);
+}
+
 static const char * const report_usage[] = {
 	"perf stat report [<options>]",
 	NULL,
@@ -1458,6 +1518,8 @@ static const char * const report_usage[] = {
 static struct perf_stat perf_stat = {
 	.tool = {
 		.attr		= perf_event__process_attr,
+		.thread_map	= process_thread_map_event,
+		.cpu_map	= process_cpu_map_event,
 	},
 };
 
-- 
2.4.3


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

* [PATCH 43/56] perf stat report: Process stat config event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (41 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 42/56] perf stat report: Process cpu/threads maps Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 44/56] perf stat report: Add support to initialize aggr_map from file Jiri Olsa
                   ` (13 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding processing of stat config event and initialize
stat_config object.

Link: http://lkml.kernel.org/n/tip-f2bo5wm0cw76zc5qsjm4pztx@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bcb9a6f85a1e..6c00e85a4fc0 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1453,6 +1453,15 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static
+int process_stat_config_event(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_session *session __maybe_unused)
+{
+	perf_event__read_stat_config(&stat_config, &event->stat_config);
+	return 0;
+}
+
 static int set_maps(struct perf_stat *stat)
 {
 	if (!stat->cpus || !stat->threads)
@@ -1520,6 +1529,7 @@ static struct perf_stat perf_stat = {
 		.attr		= perf_event__process_attr,
 		.thread_map	= process_thread_map_event,
 		.cpu_map	= process_cpu_map_event,
+		.stat_config	= process_stat_config_event,
 	},
 };
 
-- 
2.4.3


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

* [PATCH 44/56] perf stat report: Add support to initialize aggr_map from file
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (42 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 43/56] perf stat report: Process stat config event Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 45/56] perf stat report: Process stat and stat round events Jiri Olsa
                   ` (12 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Using perf.data's perf_env data to initialize
aggregate config.

Link: http://lkml.kernel.org/n/tip-p15mtcu2jon85trs37bwoh5f@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 6c00e85a4fc0..7b9b6d9bdead 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1245,6 +1245,89 @@ static int perf_stat_init_aggr_mode(void)
 	return cpus_aggr_map ? 0 : -ENOMEM;
 }
 
+static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
+{
+	int cpu;
+
+	if (idx > map->nr)
+		return -1;
+
+	cpu = map->map[idx];
+
+	if (cpu >= env->nr_cpus_online)
+		return -1;
+
+	return cpu;
+}
+
+static int perf_env__get_socket(struct cpu_map *map, int idx, void *data)
+{
+	struct perf_env *env = data;
+	int cpu = perf_env__get_cpu(env, map, idx);
+
+	return cpu == -1 ? -1 : env->cpu[cpu].socket_id;
+}
+
+static int perf_env__get_core(struct cpu_map *map, int idx, void *data)
+{
+	struct perf_env *env = data;
+	int cpu = perf_env__get_cpu(env, map, idx);
+
+	return cpu == -1 ? -1 : env->cpu[cpu].core_id;
+}
+
+static int perf_env__build_socket_map(struct perf_env *env, struct cpu_map *cpus,
+				      struct cpu_map **sockp)
+{
+	return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env);
+}
+
+static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
+				    struct cpu_map **corep)
+{
+	return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
+}
+
+static int perf_stat__get_socket_file(struct cpu_map *map, int idx)
+{
+	return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
+}
+
+static int perf_stat__get_core_file(struct cpu_map *map, int idx)
+{
+	return perf_env__get_core(map, idx, &perf_stat.session->header.env);
+}
+
+static int perf_stat_init_aggr_mode_file(struct perf_stat *stat)
+{
+	struct perf_env *env = &stat->session->header.env;
+
+	switch (stat_config.aggr_mode) {
+	case AGGR_SOCKET:
+		if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) {
+			perror("cannot build socket map");
+			return -1;
+		}
+		aggr_get_id = perf_stat__get_socket_file;
+		break;
+	case AGGR_CORE:
+		if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) {
+			perror("cannot build core map");
+			return -1;
+		}
+		aggr_get_id = perf_stat__get_core_file;
+		break;
+	case AGGR_NONE:
+	case AGGR_GLOBAL:
+	case AGGR_THREAD:
+	case AGGR_UNSET:
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * Add default attributes, if there were no attributes specified or
  * if -d/--detailed, -d -d or -d -d -d is used:
@@ -1458,7 +1541,15 @@ int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 			      union perf_event *event,
 			      struct perf_session *session __maybe_unused)
 {
+	struct perf_stat *stat = container_of(tool, struct perf_stat, tool);
+
 	perf_event__read_stat_config(&stat_config, &event->stat_config);
+
+	if (perf_stat.file.is_pipe)
+		perf_stat_init_aggr_mode();
+	else
+		perf_stat_init_aggr_mode_file(stat);
+
 	return 0;
 }
 
-- 
2.4.3


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

* [PATCH 45/56] perf stat report: Process stat and stat round events
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (43 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 44/56] perf stat report: Add support to initialize aggr_map from file Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 46/56] perf stat report: Process attr update events Jiri Olsa
                   ` (11 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding processing of stat and stat round events.

The stat data com in stat events, using generic
function process_stat_round_event to store data
under perf_evsel object.

The stat-round events comes each interval or as
last event in non interval mode. The function
process_stat_round_event process stored data
for each perf_evsel object and print it out.

Link: http://lkml.kernel.org/n/tip-qc3ihpf6j8hlfdts64uj4nmc@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7b9b6d9bdead..bdafc5c703ca 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1536,6 +1536,32 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_session *session)
+{
+	struct stat_round_event *round = &event->stat_round;
+	struct perf_evsel *counter;
+	struct timespec tsh, *ts = NULL;
+	const char **argv = session->header.env.cmdline_argv;
+	int argc = session->header.env.nr_cmdline;
+
+	evlist__for_each(evsel_list, counter)
+		perf_stat_process_counter(&stat_config, counter);
+
+	if (round->type == PERF_STAT_ROUND_TYPE__FINAL)
+		update_stats(&walltime_nsecs_stats, round->time);
+
+	if (stat_config.interval && round->time) {
+		tsh.tv_sec  = round->time / NSECS_PER_SEC;
+		tsh.tv_nsec = round->time % NSECS_PER_SEC;
+		ts = &tsh;
+	}
+
+	print_counters(ts, argc, argv);
+	return 0;
+}
+
 static
 int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 			      union perf_event *event,
@@ -1621,6 +1647,8 @@ static struct perf_stat perf_stat = {
 		.thread_map	= process_thread_map_event,
 		.cpu_map	= process_cpu_map_event,
 		.stat_config	= process_stat_config_event,
+		.stat		= perf_event__process_stat_event,
+		.stat_round	= process_stat_round_event,
 	},
 };
 
-- 
2.4.3


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

* [PATCH 46/56] perf stat report: Process attr update events
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (44 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 45/56] perf stat report: Process stat and stat round events Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 47/56] perf stat report: Move csv_sep initialization before report command Jiri Olsa
                   ` (10 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding processing of attr update events, so perf stat report
can store additional info for events - unit,scale,name.

Link: http://lkml.kernel.org/n/tip-3afz05w7naoeu8slxi9hc0d5@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bdafc5c703ca..2bc740319710 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1644,6 +1644,7 @@ static const char * const report_usage[] = {
 static struct perf_stat perf_stat = {
 	.tool = {
 		.attr		= perf_event__process_attr,
+		.attr_update	= perf_event__process_attr_update,
 		.thread_map	= process_thread_map_event,
 		.cpu_map	= process_cpu_map_event,
 		.stat_config	= process_stat_config_event,
-- 
2.4.3


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

* [PATCH 47/56] perf stat report: Move csv_sep initialization before report command
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (45 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 46/56] perf stat report: Process attr update events Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 48/56] perf stat report: Allow to override aggr_mode Jiri Olsa
                   ` (9 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

So we have csv_sep properly initialized before
report command leg.

Link: http://lkml.kernel.org/n/tip-i5mmbomj7lt4eg04awzocdd4@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2bc740319710..bf3b56bb8ecc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1776,6 +1776,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 					(const char **) stat_usage,
 					PARSE_OPT_STOP_AT_NON_OPTION);
 
+	if (csv_sep) {
+		csv_output = true;
+		if (!strcmp(csv_sep, "\\t"))
+			csv_sep = "\t";
+	} else
+		csv_sep = DEFAULT_SEPARATOR;
+
 	if (argc && !strncmp(argv[0], "rec", 3)) {
 		argc = __cmd_record(argc, argv);
 		if (argc < 0)
@@ -1823,13 +1830,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	stat_config.output = output;
 
-	if (csv_sep) {
-		csv_output = true;
-		if (!strcmp(csv_sep, "\\t"))
-			csv_sep = "\t";
-	} else
-		csv_sep = DEFAULT_SEPARATOR;
-
 	/*
 	 * let the spreadsheet do the pretty-printing
 	 */
-- 
2.4.3


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

* [PATCH 48/56] perf stat report: Allow to override aggr_mode
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (46 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 47/56] perf stat report: Move csv_sep initialization before report command Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 49/56] perf script: Check output fields only for samples Jiri Olsa
                   ` (8 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Allowing to override record aggr_mode. It's possible
to use perf stat like:

   $ perf stat report -A
   $ perf stat report --per-core
   $ perf stat report --per-socket

To customize the recorded aggregate mode regardless
what was used during the stat record command.

Link: http://lkml.kernel.org/n/tip-5ckzk91fsn6cvv7a740nfh8s@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt | 10 ++++++++++
 tools/perf/builtin-stat.c              | 11 +++++++++++
 2 files changed, 21 insertions(+)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 95f492828657..52ef7a9d50aa 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -182,6 +182,16 @@ Reads and reports stat data from perf data file.
 --input file::
 Input file name.
 
+--per-socket::
+Aggregate counts per processor socket for system-wide mode measurements.
+
+--per-core::
+Aggregate counts per physical processor for system-wide mode measurements.
+
+-A::
+--no-aggr::
+Do not aggregate counts across all monitored CPUs.
+
 
 EXAMPLES
 --------
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bf3b56bb8ecc..7e307d2672d4 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -135,6 +135,7 @@ struct perf_stat {
 	bool			 maps_allocated;
 	struct cpu_map		*cpus;
 	struct thread_map	*threads;
+	enum aggr_mode		 aggr_mode;
 };
 
 static struct perf_stat		perf_stat;
@@ -1571,6 +1572,9 @@ int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 
 	perf_event__read_stat_config(&stat_config, &event->stat_config);
 
+	if (stat->aggr_mode != AGGR_UNSET)
+		stat_config.aggr_mode = stat->aggr_mode;
+
 	if (perf_stat.file.is_pipe)
 		perf_stat_init_aggr_mode();
 	else
@@ -1651,6 +1655,7 @@ static struct perf_stat perf_stat = {
 		.stat		= perf_event__process_stat_event,
 		.stat_round	= process_stat_round_event,
 	},
+	.aggr_mode = AGGR_UNSET,
 };
 
 static int __cmd_report(int argc, const char **argv)
@@ -1658,6 +1663,12 @@ static int __cmd_report(int argc, const char **argv)
 	struct perf_session *session;
 	const struct option options[] = {
 	OPT_STRING('i', "input", &input_name, "file", "input file name"),
+	OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode,
+		     "aggregate counts per processor socket", AGGR_SOCKET),
+	OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode,
+		     "aggregate counts per physical processor core", AGGR_CORE),
+	OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode,
+		     "disable CPU count aggregation", AGGR_NONE),
 	OPT_END()
 	};
 	struct stat st;
-- 
2.4.3


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

* [PATCH 49/56] perf script: Check output fields only for samples
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (47 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 48/56] perf stat report: Allow to override aggr_mode Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 50/56] perf script: Process cpu/threads maps Jiri Olsa
                   ` (7 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

There's no need to check sampling output fields
for events without perf_event_attr::sample_type
field set.

Link: http://lkml.kernel.org/n/tip-uommbr3wo4913tpkkgq2sbvb@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-script.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 8ce1c6bbfa45..2653c0273b89 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -686,7 +686,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
 
 	set_print_ip_opts(&evsel->attr);
 
-	return perf_evsel__check_attr(evsel, scr->session);
+	if (evsel->attr.sample_type)
+		err = perf_evsel__check_attr(evsel, scr->session);
+
+	return err;
 }
 
 static int process_comm_event(struct perf_tool *tool,
-- 
2.4.3


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

* [PATCH 50/56] perf script: Process cpu/threads maps
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (48 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 49/56] perf script: Check output fields only for samples Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 51/56] perf script: Process stat config event Jiri Olsa
                   ` (6 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding processing of cpu/threads maps. Configuring session's
evlist with these maps.

Link: http://lkml.kernel.org/n/tip-s3txa1u2qv3bi8uspp4hi7al@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-script.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2653c0273b89..1d0a4469b74c 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -18,7 +18,11 @@
 #include "util/sort.h"
 #include "util/data.h"
 #include "util/auxtrace.h"
+#include "util/cpumap.h"
+#include "util/thread_map.h"
+#include "util/stat.h"
 #include <linux/bitmap.h>
+#include "asm/bug.h"
 
 static char const		*script_name;
 static char const		*generate_script_lang;
@@ -659,6 +663,9 @@ struct perf_script {
 	bool			show_task_events;
 	bool			show_mmap_events;
 	bool			show_switch_events;
+	bool			allocated;
+	struct cpu_map		*cpus;
+	struct thread_map	*threads;
 };
 
 static int process_attr(struct perf_tool *tool, union perf_event *event,
@@ -1615,6 +1622,63 @@ static void script__setup_sample_type(struct perf_script *script)
 	}
 }
 
+static int set_maps(struct perf_script *script)
+{
+	struct perf_evlist *evlist = script->session->evlist;
+
+	if (!script->cpus || !script->threads)
+		return 0;
+
+	if (WARN_ONCE(script->allocated, "stats double allocation\n"))
+		return -EINVAL;
+
+	perf_evlist__set_maps(evlist, script->cpus, script->threads);
+
+	if (perf_evlist__alloc_stats(evlist, true))
+		return -ENOMEM;
+
+	script->allocated = true;
+	return 0;
+}
+
+static
+int process_thread_map_event(struct perf_tool *tool,
+			     union perf_event *event,
+			     struct perf_session *session __maybe_unused)
+{
+	struct perf_script *script = container_of(tool, struct perf_script, tool);
+
+	if (script->threads) {
+		pr_warning("Extra thread map event, ignoring.\n");
+		return 0;
+	}
+
+	script->threads = thread_map__new_event(&event->thread_map);
+	if (!script->threads)
+		return -ENOMEM;
+
+	return set_maps(script);
+}
+
+static
+int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
+			  union perf_event *event,
+			  struct perf_session *session __maybe_unused)
+{
+	struct perf_script *script = container_of(tool, struct perf_script, tool);
+
+	if (script->cpus) {
+		pr_warning("Extra cpu map event, ignoring.\n");
+		return 0;
+	}
+
+	script->cpus = cpu_map__new_event(&event->cpu_map);
+	if (!script->cpus)
+		return -ENOMEM;
+
+	return set_maps(script);
+}
+
 int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	bool show_full_info = false;
@@ -1643,6 +1707,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 			.auxtrace_info	 = perf_event__process_auxtrace_info,
 			.auxtrace	 = perf_event__process_auxtrace,
 			.auxtrace_error	 = perf_event__process_auxtrace_error,
+			.thread_map	 = process_thread_map_event,
+			.cpu_map	 = process_cpu_map_event,
 			.ordered_events	 = true,
 			.ordering_requires_timestamps = true,
 		},
@@ -1996,6 +2062,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 	flush_scripting();
 
 out_delete:
+	perf_evlist__free_stats(session->evlist);
 	perf_session__delete(session);
 
 	if (script_started)
-- 
2.4.3


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

* [PATCH 51/56] perf script: Process stat config event
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (49 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 50/56] perf script: Process cpu/threads maps Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 52/56] perf script: Add process_stat/process_stat_interval scripting interface Jiri Olsa
                   ` (5 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding processing of stat config event and initialize
stat_config object.

Link: http://lkml.kernel.org/n/tip-1m1s8mahzq38foo32qb7p2a5@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-script.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 1d0a4469b74c..223ab33233eb 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -36,6 +36,7 @@ static bool			print_flags;
 static bool			nanosecs;
 static const char		*cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+static struct perf_stat_config	stat_config;
 
 unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
 
@@ -1622,6 +1623,14 @@ static void script__setup_sample_type(struct perf_script *script)
 	}
 }
 
+static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_session *session __maybe_unused)
+{
+	perf_event__read_stat_config(&stat_config, &event->stat_config);
+	return 0;
+}
+
 static int set_maps(struct perf_script *script)
 {
 	struct perf_evlist *evlist = script->session->evlist;
@@ -1707,6 +1716,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 			.auxtrace_info	 = perf_event__process_auxtrace_info,
 			.auxtrace	 = perf_event__process_auxtrace,
 			.auxtrace_error	 = perf_event__process_auxtrace_error,
+			.stat_config	 = process_stat_config_event,
 			.thread_map	 = process_thread_map_event,
 			.cpu_map	 = process_cpu_map_event,
 			.ordered_events	 = true,
-- 
2.4.3


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

* [PATCH 52/56] perf script: Add process_stat/process_stat_interval scripting interface
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (50 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 51/56] perf script: Process stat config event Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 53/56] perf script: Add stat default handlers Jiri Olsa
                   ` (4 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Python and perl scripting code will define those
callbacks and get stat data.

Link: http://lkml.kernel.org/n/tip-6802z3siu5f59wdsmhaym3wm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/trace-event.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b85ee55cca0c..0ebc9dab2c7c 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -65,6 +65,7 @@ int tracing_data_put(struct tracing_data *tdata);
 struct addr_location;
 
 struct perf_session;
+struct perf_stat_config;
 
 struct scripting_ops {
 	const char *name;
@@ -75,6 +76,9 @@ struct scripting_ops {
 			       struct perf_sample *sample,
 			       struct perf_evsel *evsel,
 			       struct addr_location *al);
+	void (*process_stat) (struct perf_stat_config *config,
+			      struct perf_evsel *evsel, u64 time);
+	void (*process_stat_interval) (u64 time);
 	int (*generate_script) (struct pevent *pevent, const char *outfile);
 };
 
-- 
2.4.3


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

* [PATCH 53/56] perf script: Add stat default handlers
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (51 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 52/56] perf script: Add process_stat/process_stat_interval scripting interface Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 54/56] perf script: Display stat events by default Jiri Olsa
                   ` (3 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Implement struct scripting_ops::(process_stat|process_stat_interval)
handlers - calling scripting handlers from stat events handlers.

Link: http://lkml.kernel.org/n/tip-3iu6vmvuur1bntbnh43v3bib@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-script.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 223ab33233eb..474811af0560 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -205,6 +205,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
 	struct perf_event_attr *attr = &evsel->attr;
 	bool allow_user_set;
 
+	if (perf_header__has_feat(&session->header, HEADER_STAT))
+		return 0;
+
 	allow_user_set = perf_header__has_feat(&session->header,
 					       HEADER_AUXTRACE);
 
@@ -568,6 +571,14 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
 	printf("\n");
 }
 
+static void process_stat(struct perf_stat_config *config __maybe_unused,
+			 struct perf_evsel *evsel __maybe_unused,
+			 u64 time __maybe_unused)
+{
+}
+
+static void process_stat_interval(u64 time __maybe_unused) { }
+
 static int default_start_script(const char *script __maybe_unused,
 				int argc __maybe_unused,
 				const char **argv __maybe_unused)
@@ -596,6 +607,8 @@ static struct scripting_ops default_scripting_ops = {
 	.flush_script		= default_flush_script,
 	.stop_script		= default_stop_script,
 	.process_event		= process_event,
+	.process_stat		= process_stat,
+	.process_stat_interval	= process_stat_interval,
 	.generate_script	= default_generate_script,
 };
 
@@ -1623,6 +1636,22 @@ static void script__setup_sample_type(struct perf_script *script)
 	}
 }
 
+static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_session *session)
+{
+	struct stat_round_event *round = &event->stat_round;
+	struct perf_evsel *counter;
+
+	evlist__for_each(session->evlist, counter) {
+		perf_stat_process_counter(&stat_config, counter);
+		scripting_ops->process_stat(&stat_config, counter, round->time);
+	}
+
+	scripting_ops->process_stat_interval(round->time);
+	return 0;
+}
+
 static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 				     union perf_event *event,
 				     struct perf_session *session __maybe_unused)
@@ -1716,6 +1745,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 			.auxtrace_info	 = perf_event__process_auxtrace_info,
 			.auxtrace	 = perf_event__process_auxtrace,
 			.auxtrace_error	 = perf_event__process_auxtrace_error,
+			.stat		 = perf_event__process_stat_event,
+			.stat_round	 = process_stat_round_event,
 			.stat_config	 = process_stat_config_event,
 			.thread_map	 = process_thread_map_event,
 			.cpu_map	 = process_cpu_map_event,
-- 
2.4.3


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

* [PATCH 54/56] perf script: Display stat events by default
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (52 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 53/56] perf script: Add stat default handlers Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 55/56] perf script: Add python support for stat events Jiri Olsa
                   ` (2 subsequent siblings)
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

If no script is specified for stat data, display
stat events in raw form.

  $ perf stat record ls

  SNIP

   Performance counter stats for 'ls':

            0.851585      task-clock (msec)         #    0.717 CPUs utilized
                   0      context-switches          #    0.000 K/sec
                   0      cpu-migrations            #    0.000 K/sec
                 114      page-faults               #    0.134 M/sec
           2,620,918      cycles                    #    3.078 GHz
     <not supported>      stalled-cycles-frontend
     <not supported>      stalled-cycles-backend
           2,714,111      instructions              #    1.04  insns per cycle
             542,434      branches                  #  636.970 M/sec
              15,946      branch-misses             #    2.94% of all branches

         0.001186954 seconds time elapsed

  $ perf script
  CPU   THREAD             VAL             ENA             RUN            TIME EVENT
   -1    26185          851585          851585          851585         1186954 task-clock
   -1    26185               0          851585          851585         1186954 context-switches
   -1    26185               0          851585          851585         1186954 cpu-migrations
   -1    26185             114          851585          851585         1186954 page-faults
   -1    26185         2620918          853340          853340         1186954 cycles
   -1    26185               0               0               0         1186954 stalled-cycles-frontend
   -1    26185               0               0               0         1186954 stalled-cycles-backend
   -1    26185         2714111          853340          853340         1186954 instructions
   -1    26185          542434          853340          853340         1186954 branches
   -1    26185           15946          853340          853340         1186954 branch-misses

Link: http://lkml.kernel.org/n/tip-ph7bpnetmskvmietfwllf6i6@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-script.c | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 474811af0560..ac8a5f824772 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -572,9 +572,40 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
 }
 
 static void process_stat(struct perf_stat_config *config __maybe_unused,
-			 struct perf_evsel *evsel __maybe_unused,
-			 u64 time __maybe_unused)
+			 struct perf_evsel *counter, u64 time)
 {
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = perf_evsel__nr_cpus(counter);
+	int cpu, thread;
+	static int header_printed;
+
+	if (counter->system_wide)
+		nthreads = 1;
+
+	if (!header_printed) {
+		printf("%3s %8s %15s %15s %15s %15s %s\n",
+		       "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");
+		header_printed = 1;
+	}
+
+	for (thread = 0; thread < nthreads; thread++) {
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			struct perf_counts_values *counts;
+
+			counts = perf_counts(counter->counts, cpu, thread);
+
+			printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
+				counter->cpus->map[cpu],
+				thread_map__pid(counter->threads, thread),
+				counts->val,
+				counts->ena,
+				counts->run,
+				time,
+				perf_evsel__name(counter));
+		}
+	}
+
+	return;
 }
 
 static void process_stat_interval(u64 time __maybe_unused) { }
-- 
2.4.3


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

* [PATCH 55/56] perf script: Add python support for stat events
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (53 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 54/56] perf script: Display stat events by default Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-06 19:55 ` [PATCH 56/56] perf script: Add stat-cpi.py script Jiri Olsa
  2015-10-08 18:37 ` [PATCHv3 00/56] perf stat: Add scripting support Liang, Kan
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Add support to get stat events data in perf python scripts.

The python script shall implement following
new interface to process stat data:

  def stat__<event_name>_[<modifier>](cpu, thread, time, val, ena, run):

    - is called for every stat event for given counter,
      if user monitors 'cycles,instructions:u" following
      callbacks should be defined:

      def stat__cycles(cpu, thread, time, val, ena, run):
      def stat__instructions_u(cpu, thread, time, val, ena, run):

  def stat__interval(time):

    - is called for every interval with its time,
      in non interval mode it's called after last
      stat event with total meassured time in ns

The rest of the current interface stays untouched..

Please check example CPI metrics script in following patch
with command line examples in changelogs.

Link: http://lkml.kernel.org/n/tip-jojiaelyckrw6040wqc06q1j@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../util/scripting-engines/trace-event-python.c    | 114 +++++++++++++++++++--
 1 file changed, 108 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index a8e825fca42a..8436eb23eb16 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -41,6 +41,9 @@
 #include "../thread-stack.h"
 #include "../trace-event.h"
 #include "../machine.h"
+#include "thread_map.h"
+#include "cpumap.h"
+#include "stat.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
 
@@ -859,6 +862,103 @@ static void python_process_event(union perf_event *event,
 	}
 }
 
+static void get_handler_name(char *str, size_t size,
+			     struct perf_evsel *evsel)
+{
+	char *p = str;
+
+	scnprintf(str, size, "stat__%s", perf_evsel__name(evsel));
+
+	while ((p = strchr(p, ':'))) {
+		*p = '_';
+		p++;
+	}
+}
+
+static void
+process_stat(struct perf_evsel *counter, int cpu, int thread, u64 time,
+	     struct perf_counts_values *count)
+{
+	PyObject *handler, *t;
+	static char handler_name[256];
+	int n = 0;
+
+	t = PyTuple_New(MAX_FIELDS);
+	if (!t)
+		Py_FatalError("couldn't create Python tuple");
+
+	get_handler_name(handler_name, sizeof(handler_name),
+			 counter);
+
+	handler = get_handler(handler_name);
+	if (!handler) {
+		pr_debug("can't find python handler %s\n", handler_name);
+		return;
+	}
+
+	PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
+	PyTuple_SetItem(t, n++, PyInt_FromLong(thread));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(time));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(count->val));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(count->ena));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(count->run));
+
+	if (_PyTuple_Resize(&t, n) == -1)
+		Py_FatalError("error resizing Python tuple");
+
+	call_object(handler, t, handler_name);
+
+	Py_DECREF(t);
+}
+
+static void python_process_stat(struct perf_stat_config *config,
+				struct perf_evsel *counter, u64 time)
+{
+	struct thread_map *threads = counter->threads;
+	struct cpu_map *cpus = counter->cpus;
+	int cpu, thread;
+
+	if (config->aggr_mode == AGGR_GLOBAL) {
+		process_stat(counter, -1, -1, time,
+			     &counter->counts->aggr);
+		return;
+	}
+
+	for (thread = 0; thread < threads->nr; thread++) {
+		for (cpu = 0; cpu < cpus->nr; cpu++) {
+			process_stat(counter, cpus->map[cpu],
+				     thread_map__pid(threads, thread), time,
+				     perf_counts(counter->counts, cpu, thread));
+		}
+	}
+}
+
+static void python_process_stat_interval(u64 time)
+{
+	PyObject *handler, *t;
+	static const char handler_name[] = "stat__interval";
+	int n = 0;
+
+	t = PyTuple_New(MAX_FIELDS);
+	if (!t)
+		Py_FatalError("couldn't create Python tuple");
+
+	handler = get_handler(handler_name);
+	if (!handler) {
+		pr_debug("can't find python handler %s\n", handler_name);
+		return;
+	}
+
+	PyTuple_SetItem(t, n++, PyLong_FromLong(time));
+
+	if (_PyTuple_Resize(&t, n) == -1)
+		Py_FatalError("error resizing Python tuple");
+
+	call_object(handler, t, handler_name);
+
+	Py_DECREF(t);
+}
+
 static int run_start_sub(void)
 {
 	main_module = PyImport_AddModule("__main__");
@@ -1201,10 +1301,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
 }
 
 struct scripting_ops python_scripting_ops = {
-	.name = "Python",
-	.start_script = python_start_script,
-	.flush_script = python_flush_script,
-	.stop_script = python_stop_script,
-	.process_event = python_process_event,
-	.generate_script = python_generate_script,
+	.name			= "Python",
+	.start_script		= python_start_script,
+	.flush_script		= python_flush_script,
+	.stop_script		= python_stop_script,
+	.process_event		= python_process_event,
+	.process_stat		= python_process_stat,
+	.process_stat_interval	= python_process_stat_interval,
+	.generate_script	= python_generate_script,
 };
-- 
2.4.3


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

* [PATCH 56/56] perf script: Add stat-cpi.py script
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (54 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 55/56] perf script: Add python support for stat events Jiri Olsa
@ 2015-10-06 19:55 ` Jiri Olsa
  2015-10-08 18:37 ` [PATCHv3 00/56] perf stat: Add scripting support Liang, Kan
  56 siblings, 0 replies; 62+ messages in thread
From: Jiri Olsa @ 2015-10-06 19:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Liang, Kan

Adding stat-cpi.py as an example of how to do stat scripting.
It computes the CPI metrics from cycles and instructions
events.

Following stat record/report/script combinations could be used:

- get CPI for given workload

    $ perf stat -e cycles,instructions record ls

    SNIP

     Performance counter stats for 'ls':

             2,904,431      cycles
             3,346,878      instructions              #    1.15  insns per cycle

           0.001782686 seconds time elapsed

    $ perf script -s ./scripts/python/stat-cpi.py
           0.001783: cpu -1, thread -1 -> cpi 0.867803 (2904431/3346878)

    $ perf stat -e cycles,instructions record ls | perf script -s ./scripts/python/stat-cpi.py

    SNIP

           0.001730: cpu -1, thread -1 -> cpi 0.869026 (2928292/3369627)

- get CPI systemwide:

    $ perf stat -e cycles,instructions -a -I 1000 record sleep 3
    #           time             counts unit events
         1.000158618        594,274,711      cycles                     (100.00%)
         1.000158618        441,898,250      instructions
         2.000350973        567,649,705      cycles                     (100.00%)
         2.000350973        432,669,206      instructions
         3.000559210        561,940,430      cycles                     (100.00%)
         3.000559210        420,403,465      instructions
         3.000670798            780,105      cycles                     (100.00%)
         3.000670798            326,516      instructions

    $ perf script -s ./scripts/python/stat-cpi.py
           1.000159: cpu -1, thread -1 -> cpi 1.344823 (594274711/441898250)
           2.000351: cpu -1, thread -1 -> cpi 1.311972 (567649705/432669206)
           3.000559: cpu -1, thread -1 -> cpi 1.336669 (561940430/420403465)
           3.000671: cpu -1, thread -1 -> cpi 2.389178 (780105/326516)

    $ perf stat -e cycles,instructions -a -I 1000 record sleep 3 | perf script -s ./scripts/python/stat-cpi.py
           1.000202: cpu -1, thread -1 -> cpi 1.035091 (940778881/908885530)
           2.000392: cpu -1, thread -1 -> cpi 1.442600 (627493992/434974455)
           3.000545: cpu -1, thread -1 -> cpi 1.353612 (741463930/547766890)
           3.000622: cpu -1, thread -1 -> cpi 2.642110 (784083/296764)

Link: http://lkml.kernel.org/n/tip-15vwwb4yea15wzz6bqbxdpc0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/scripts/python/stat-cpi.py | 74 +++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)
 create mode 100644 tools/perf/scripts/python/stat-cpi.py

diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
new file mode 100644
index 000000000000..eb3936e99862
--- /dev/null
+++ b/tools/perf/scripts/python/stat-cpi.py
@@ -0,0 +1,74 @@
+#!/bin/python
+
+data    = {}
+times   = []
+threads = []
+cpus    = []
+
+def get_key(time, event, cpu, thread):
+    return "%d-%s-%d-%d" % (time, event, cpu, thread)
+
+def store_key(time, cpu, thread):
+    if (time not in times):
+        times.append(time)
+
+    if (cpu not in cpus):
+        cpus.append(cpu)
+
+    if (thread not in threads):
+        threads.append(thread)
+
+def store(time, event, cpu, thread, val, ena, run):
+    #print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \
+    #      (event, cpu, thread, time, val, ena, run)
+
+    store_key(time, cpu, thread)
+    key = get_key(time, event, cpu, thread)
+    data[key] = [ val, ena, run]
+
+def get(time, event, cpu, thread):
+    key = get_key(time, event, cpu, thread)
+    return data[key][0]
+
+def stat__cycles_k(cpu, thread, time, val, ena, run):
+    store(time, "cycles", cpu, thread, val, ena, run);
+
+def stat__instructions_k(cpu, thread, time, val, ena, run):
+    store(time, "instructions", cpu, thread, val, ena, run);
+
+def stat__cycles_u(cpu, thread, time, val, ena, run):
+    store(time, "cycles", cpu, thread, val, ena, run);
+
+def stat__instructions_u(cpu, thread, time, val, ena, run):
+    store(time, "instructions", cpu, thread, val, ena, run);
+
+def stat__cycles(cpu, thread, time, val, ena, run):
+    store(time, "cycles", cpu, thread, val, ena, run);
+
+def stat__instructions(cpu, thread, time, val, ena, run):
+    store(time, "instructions", cpu, thread, val, ena, run);
+
+def stat__interval(time):
+    for cpu in cpus:
+        for thread in threads:
+            cyc = get(time, "cycles", cpu, thread)
+            ins = get(time, "instructions", cpu, thread)
+            cpi = 0
+
+            if ins != 0:
+                cpi = cyc/float(ins)
+
+            print "%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins)
+
+def trace_end():
+    pass
+#    for time in times:
+#        for cpu in cpus:
+#            for thread in threads:
+#                cyc = get(time, "cycles", cpu, thread)
+#                ins = get(time, "instructions", cpu, thread)
+#
+#                if ins != 0:
+#                    cpi = cyc/float(ins)
+#
+#                print "time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi)
-- 
2.4.3


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

* RE: [PATCHv3 00/56] perf stat: Add scripting support
  2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
                   ` (55 preceding siblings ...)
  2015-10-06 19:55 ` [PATCH 56/56] perf script: Add stat-cpi.py script Jiri Olsa
@ 2015-10-08 18:37 ` Liang, Kan
  2015-10-08 20:11   ` Jiri Olsa
  56 siblings, 1 reply; 62+ messages in thread
From: Liang, Kan @ 2015-10-08 18:37 UTC (permalink / raw)
  To: Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: Andi Kleen, Ulrich Drepper, Will Deacon, Stephane Eranian,
	Don Zickus, lkml, David Ahern, Ingo Molnar, Namhyung Kim,
	Peter Zijlstra


Hi Jirka

I'm doing some test with the perf/stat_script tree.
Here are the issues I found so far.

1 test case failed to build:

  CC       tests/stat.o
tests/stat.c: In function âtest__synthesize_statâ:
tests/stat.c:82:3: error: missing initializer for field âenaâ of
âstruct <anonymous>â [-Werror=missing-field-initializers]
   .ena = 200,
   ^
In file included from tests/stat.c:5:0:
/home/lk/group_read/test/perf/tools/perf/util/counts.h:10:8:
note: âenaâ declared here
    u64 ena;
        ^
tests/stat.c:83:3: error: missing initializer for field ârunâ of
âstruct <anonymous>â [-Werror=missing-field-initializers]
   .run = 300,
   ^
In file included from tests/stat.c:5:0:
/home/lk/group_read/test/perf/tools/perf/util/counts.h:11:8:
note: ârunâ declared here
    u64 run;
        ^
cc1: all warnings being treated as errors
mv: cannot stat âtests/.stat.o.tmpâ: No such file or directory
make[3]: *** [tests/stat.o] Error 1
make[2]: *** [tests] Error 2
make[1]: *** [perf-in.o] Error 2
make: *** [all] Error 2


2. it still doesn't work well with uncore event.

Here is an example:
sudo ./perf stat -e uncore_imc_1/cas_count_read/ -a --interval-print 100
--per-socket record -- sleep 1
#           time socket cpus             counts unit events
     0.100231142 S0        1               0.04 MiB  uncore_imc_1/cas_count_read/
     0.100231142 S1        1               0.08 MiB  uncore_imc_1/cas_count_read/
     0.200583556 S0        1               0.02 MiB  uncore_imc_1/cas_count_read/
     0.200583556 S1        1               0.02 MiB  uncore_imc_1/cas_count_read/

sudo ./perf stat report --per-socket
#           time socket cpus             counts unit events
     0.100231142 S0       36               0.12 MiB  uncore_imc_1/cas_count_read/
     0.100231142 S1       28      <not counted> 
MiB  uncore_imc_1/cas_count_read/
     0.200583556 S0       36               0.04 MiB  uncore_imc_1/cas_count_read/
     0.200583556 S1       28      <not counted> 
MiB  uncore_imc_1/cas_count_read/

The results are not consistent. 

I checked the perf report -D result. It looks the wrong CPU id is stored.
In my system, the uncore event should be monitored in CPU 0 and CPU 19
But it shows CPU0 and CPU1.

0x520 [0x30]: PERF_RECORD_STAT
... id 22385, cpu 0, thread 0

0x550 [0x30]: PERF_RECORD_STAT
... id 22386, cpu 1, thread 0


3. I think you have already handled new record type for perf stat record.
But the "unhandled!" message still show in the perf report -D.      

0x598 [0x30]: PERF_RECORD_STAT
... id 22385, cpu 0, thread 0
... value 1752, enabled 501473097, running 501473097
: unhandled!      <-------


4. Core dump when applying --per-core -a for stat record.

sudo ./perf stat -e 'cycles' --per-core -a record sleep 1

** Error in `./perf': corrupted double-linked list: 0x00000000036eb560 **
======= Backtrace: =========
/lib64/libc.so.6[0x3002e7bbe7]
/lib64/libc.so.6[0x3002e7d2b5]
./perf(perf_env__exit+0xfd)[0x484d1d]
./perf[0x47c45f]
./perf(main+0x610)[0x421ac0]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3002e21b45]
./perf[0x421bd9]


5.  perf stat record may not monitor on specific CPU/whole-system.
However, perf stat report can be set to aggregate per core/socket.
If so, there is problem to show the data.
I think we need some warning here.

For example,

sudo ./perf stat -e 'cycles' record sleep 1

 Performance counter stats for 'sleep 1':

           858,928      cycles

       1.001120735 seconds time elapsed

sudo ./perf stat report -A

 Performance counter stats for '/home/lk/group_read/test/perf/
tools/perf/perf stat -e cycles record sleep 1':

CPU-1              858,928      cycles

       1.001120735 seconds time elapsed



Thanks,
Kan

> hi,
> sending another version of stat scripting.
> 
> v3 changes:
>   - added attr update event to handle unit,scale,name for event
>     it fixed the uncore_imc_1/cas_count_read/ record/report
>   - perf report -D now displays stat related events
>   - some minor and changelog fixes
> 
> v2 changes:
>   - rebased to latest Arnaldo's perf/core
>   - patches 1 to 11 already merged in
>   - added --per-core/--per-socket/-A options for perf stat report
>     command to allow custom aggregation in stat report, please
>     check new examples below
>   - couple changelogs changes
> 
> The initial attempt defined its own formula lang and allowed triggering
> user's script on the end of the stat command:
>   http://marc.info/?l=linux-kernel&m=136742146322273&w=2
> 
> This patchset abandons the idea of new formula language and rather adds
> support to:
>   - store stat data into perf.data file
>   - add python support to process stat events
> 
> Basically it allows to store stat data into perf.data and post process it with
> python scripts in a similar way we do for sampling data.
> 
> The stat data are stored in new stat, stat-round, stat-config user events.
>   stat        - stored for each read syscall of the counter
>   stat round  - stored for each interval or end of the command invocation
>   stat config - stores all the config information needed to process data
>                 so report tool could restore the same output as record
> 
> The python script can now define 'stat__<eventname>_<modifier>'
> functions to get stat events data and 'stat__interval' to get stat-round data.
> 
> See CPI script example in scripts/python/stat-cpi.py.
> 
> Also available in:
>   git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
>   perf/stat_script
> 
> thanks,
> jirka
> 
> 
> Examples:
> 
> - To record data for command stat workload:
> 
>   $ perf stat record kill
>   ...
> 
>    Performance counter stats for 'kill':
> 
>             0.372007      task-clock (msec)         #    0.613 CPUs utilized
>                    3      context-switches          #    0.008 M/sec
>                    0      cpu-migrations            #    0.000 K/sec
>                   62      page-faults               #    0.167 M/sec
>            1,129,973      cycles                    #    3.038 GHz
>      <not supported>      stalled-cycles-frontend
>      <not supported>      stalled-cycles-backend
>              813,313      instructions              #    0.72  insns per cycle
>              166,161      branches                  #  446.661 M/sec
>                8,747      branch-misses             #    5.26% of all branches
> 
>          0.000607287 seconds time elapsed
> 
> - To report perf stat data:
> 
>   $ perf stat report
> 
>    Performance counter stats for '/home/jolsa/bin/perf stat record kill':
> 
>             0.372007      task-clock (msec)         #      inf CPUs utilized
>                    3      context-switches          #    0.008 M/sec
>                    0      cpu-migrations            #    0.000 K/sec
>                   62      page-faults               #    0.167 M/sec
>            1,129,973      cycles                    #    3.038 GHz
>      <not supported>      stalled-cycles-frontend
>      <not supported>      stalled-cycles-backend
>              813,313      instructions              #    0.72  insns per cycle
>              166,161      branches                  #  446.661 M/sec
>                8,747      branch-misses             #    5.26% of all branches
> 
>          0.000000000 seconds time elapsed
> 
> - To store system-wide period stat data:
> 
>   $ perf stat -e cycles:u,instructions:u -a -I 1000 record
>   #           time             counts unit events
>        1.000265471        462,311,482      cycles:u                   (100.00%)
>        1.000265471        590,037,440      instructions:u
>        2.000483453        722,532,336      cycles:u                   (100.00%)
>        2.000483453        848,678,197      instructions:u
>        3.000759876         75,990,880      cycles:u                   (100.00%)
>        3.000759876         86,187,813      instructions:u
>   ^C     3.213960893         85,329,533      cycles:u                   (100.00%)
>        3.213960893        135,954,296      instructions:u
> 
> - To report perf stat data:
> 
>   $ perf stat report
>   #           time             counts unit events
>        1.000265471        462,311,482      cycles:u                   (100.00%)
>        1.000265471        590,037,440      instructions:u
>        2.000483453        722,532,336      cycles:u                   (100.00%)
>        2.000483453        848,678,197      instructions:u
>        3.000759876         75,990,880      cycles:u                   (100.00%)
>        3.000759876         86,187,813      instructions:u
>        3.213960893         85,329,533      cycles:u                   (100.00%)
>        3.213960893        135,954,296      instructions:u
> 
> - To run stat-cpi.py script over perf.data:
> 
>   $ perf script -s scripts/python/stat-cpi.py
>          1.000265: cpu -1, thread -1 -> cpi 0.783529 (462311482/590037440)
>          2.000483: cpu -1, thread -1 -> cpi 0.851362 (722532336/848678197)
>          3.000760: cpu -1, thread -1 -> cpi 0.881689 (75990880/86187813)
>          3.213961: cpu -1, thread -1 -> cpi 0.627634 (85329533/135954296)
> 
> - To pipe data from stat to stat-cpi script:
> 
>   $ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf script -s
> scripts/python/stat-cpi.py
>          1.000192: cpu 0, thread -1 -> cpi 0.739535 (23921908/32347236)
>          2.000376: cpu 0, thread -1 -> cpi 1.663482 (2519340/1514498)
>          3.000621: cpu 0, thread -1 -> cpi 1.396308 (16162767/11575362)
>          4.000700: cpu 0, thread -1 -> cpi 1.092246 (20077258/18381624)
>          5.000867: cpu 0, thread -1 -> cpi 0.473816 (45157586/95306156)
>          6.001034: cpu 0, thread -1 -> cpi 0.532792 (43701668/82023818)
>          7.001195: cpu 0, thread -1 -> cpi 1.122059 (29890042/26638561)
> 
> - Raw script stat data output:
> 
>   $ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf --no-
> pager script
>   CPU   THREAD             VAL             ENA             RUN            TIME EVENT
>     0       -1        12302059      1000811347      1000810712      1000198821 cycles:u
>     0       -1         2565362      1000823218      1000823218      1000198821
> instructions:u
>     0       -1        14453353      1000812704      1000812704      2000382283 cycles:u
>     0       -1         4600932      1000799342      1000799342      2000382283
> instructions:u
>     0       -1        15245106      1000774425      1000774425      3000538255 cycles:u
>     0       -1         2624324      1000769310      1000769310      3000538255
> instructions:u
> 
> - To display different aggregation in report:
> 
>   $ perf stat -e cycles -a -I 1000 record sleep 3
>   #           time             counts unit events
>        1.000223609        703,427,617      cycles
>        2.000443651        609,975,307      cycles
>        3.000569616        668,479,597      cycles
>        3.000735323          1,155,816      cycles
> 
>   $ perf stat report
>   #           time             counts unit events
>        1.000223609        703,427,617      cycles
>        2.000443651        609,975,307      cycles
>        3.000569616        668,479,597      cycles
>        3.000735323          1,155,816      cycles
> 
>   $ perf stat report --per-core
>   #           time core         cpus             counts unit events
>        1.000223609 S0-C0           2        327,612,412      cycles
>        1.000223609 S0-C1           2        375,815,205      cycles
>        2.000443651 S0-C0           2        287,462,177      cycles
>        2.000443651 S0-C1           2        322,513,130      cycles
>        3.000569616 S0-C0           2        271,571,908      cycles
>        3.000569616 S0-C1           2        396,907,689      cycles
>        3.000735323 S0-C0           2            694,977      cycles
>        3.000735323 S0-C1           2            460,839      cycles
> 
>   $ perf stat report --per-socket
>   #           time socket cpus             counts unit events
>        1.000223609 S0        4        703,427,617      cycles
>        2.000443651 S0        4        609,975,307      cycles
>        3.000569616 S0        4        668,479,597      cycles
>        3.000735323 S0        4          1,155,816      cycles
> 
>   $ perf stat report -A
>   #           time CPU                counts unit events
>        1.000223609 CPU0           205,431,505      cycles
>        1.000223609 CPU1           122,180,907      cycles
>        1.000223609 CPU2           176,649,682      cycles
>        1.000223609 CPU3           199,165,523      cycles
>        2.000443651 CPU0           148,447,922      cycles
>        2.000443651 CPU1           139,014,255      cycles
>        2.000443651 CPU2           204,436,559      cycles
>        2.000443651 CPU3           118,076,571      cycles
>        3.000569616 CPU0           149,788,954      cycles
>        3.000569616 CPU1           121,782,954      cycles
>        3.000569616 CPU2           247,277,700      cycles
>        3.000569616 CPU3           149,629,989      cycles
>        3.000735323 CPU0               269,675      cycles
>        3.000735323 CPU1               425,302      cycles
>        3.000735323 CPU2               364,169      cycles
>        3.000735323 CPU3                96,670      cycles
> 
> 
> Cc: Andi Kleen <andi@firstfloor.org>
> Cc: Ulrich Drepper <drepper@gmail.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Stephane Eranian <eranian@google.com>
> Cc: Don Zickus <dzickus@redhat.com>
> ---
> Jiri Olsa (56):
>       perf tools: Add thread_map event
>       perf tools: Add thread_map event sythesize function
>       perf tools: Add thread_map__new_event function
>       perf tools: Add perf_event__fprintf_thread_map function
>       perf tools: Add cpu_map event
>       perf tools: Add cpu_map event synthesize function
>       perf tools: Add cpu_map__new_event function
>       perf tools: Add perf_event__fprintf_cpu_map function
>       perf tools: Add stat config event
>       perf tools: Add stat config event synthesize function
>       perf tools: Add stat config event read function
>       perf tools: Add stat event
>       perf tools: Add stat event synthesize function
>       perf tools: Add stat event read function
>       perf tools: Add stat round event
>       perf tools: Add stat round event synthesize function
>       perf tools: Add stat events fprintf functions
>       perf tools: Add attr_update event
>       perf tools: Add attr_update event unit type
>       perf tools: Add attr_update event scale type
>       perf tools: Add attr_update event name type
>       perf tools: Add perf_event__fprintf_attr_update function
>       perf report: Display newly added events in raw dump
>       perf tools: Introduce stat feature
>       perf tools: Move id_offset out of struct perf_evsel union
>       perf stat: Rename perf_stat struct into perf_stat_evsel
>       perf stat: Add AGGR_UNSET mode
>       perf stat record: Add record command
>       perf stat record: Initialize record features
>       perf stat record: Synthesize stat record data
>       perf stat record: Store events IDs in perf data file
>       perf stat record: Add pipe support for record command
>       perf stat record: Write stat events on record
>       perf stat record: Write stat round events on record
>       perf stat record: Do not allow record with multiple runs mode
>       perf stat record: Synthesize attr update events
>       perf tools: Add cpu_map__empty_new interface
>       perf tools: Make cpu_map__build_map global
>       perf tools: Add data arg to cpu_map__build_map callback
>       perf stat report: Cache aggregated map entries in extra cpumap
>       perf stat report: Add report command
>       perf stat report: Process cpu/threads maps
>       perf stat report: Process stat config event
>       perf stat report: Add support to initialize aggr_map from file
>       perf stat report: Process stat and stat round events
>       perf stat report: Process attr update events
>       perf stat report: Move csv_sep initialization before report command
>       perf stat report: Allow to override aggr_mode
>       perf script: Check output fields only for samples
>       perf script: Process cpu/threads maps
>       perf script: Process stat config event
>       perf script: Add process_stat/process_stat_interval scripting interface
>       perf script: Add stat default handlers
>       perf script: Display stat events by default
>       perf script: Add python support for stat events
>       perf script: Add stat-cpi.py script
> 
>  tools/perf/Documentation/perf-stat.txt             |  34 ++
>  tools/perf/builtin-record.c                        |   2 +
>  tools/perf/builtin-script.c                        | 144 ++++-
>  tools/perf/builtin-stat.c                          | 636 ++++++++++++++++++++-
>  tools/perf/scripts/python/stat-cpi.py              |  74 +++
>  tools/perf/tests/Build                             |   3 +
>  tools/perf/tests/attr_update.c                     |  82 +++
>  tools/perf/tests/builtin-test.c                    |  25 +
>  tools/perf/tests/cpumap.c                          |  39 ++
>  tools/perf/tests/stat.c                            | 111 ++++
>  tools/perf/tests/tests.h                           |   7 +
>  tools/perf/tests/thread-map.c                      |  43 ++
>  tools/perf/tests/topology.c                        |   4 +-
>  tools/perf/util/cpumap.c                           |  61 +-
>  tools/perf/util/cpumap.h                           |  11 +-
>  tools/perf/util/event.c                            | 205 +++++++
>  tools/perf/util/event.h                            | 122 +++-
>  tools/perf/util/evlist.c                           |   6 +-
>  tools/perf/util/evlist.h                           |   3 +
>  tools/perf/util/evsel.h                            |   2 +-
>  tools/perf/util/header.c                           | 146 +++++
>  tools/perf/util/header.h                           |  14 +
>  .../util/scripting-engines/trace-event-python.c    | 114 +++-
>  tools/perf/util/session.c                          | 163 ++++++
>  tools/perf/util/stat.c                             |  75 ++-
>  tools/perf/util/stat.h                             |  13 +-
>  tools/perf/util/thread_map.c                       |  27 +
>  tools/perf/util/thread_map.h                       |   3 +
>  tools/perf/util/tool.h                             |   8 +-
>  tools/perf/util/trace-event.h                      |   4 +
>  30 files changed, 2132 insertions(+), 49 deletions(-)  create mode 100644
> tools/perf/scripts/python/stat-cpi.py
>  create mode 100644 tools/perf/tests/attr_update.c  create mode 100644
> tools/perf/tests/cpumap.c  create mode 100644 tools/perf/tests/stat.c

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

* Re: [PATCHv3 00/56] perf stat: Add scripting support
  2015-10-08 18:37 ` [PATCHv3 00/56] perf stat: Add scripting support Liang, Kan
@ 2015-10-08 20:11   ` Jiri Olsa
  2015-10-09 18:31     ` Liang, Kan
  0 siblings, 1 reply; 62+ messages in thread
From: Jiri Olsa @ 2015-10-08 20:11 UTC (permalink / raw)
  To: Liang, Kan
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Andi Kleen, Ulrich Drepper,
	Will Deacon, Stephane Eranian, Don Zickus, lkml, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra

On Thu, Oct 08, 2015 at 06:37:43PM +0000, Liang, Kan wrote:
> 
> Hi Jirka
> 
> I'm doing some test with the perf/stat_script tree.
> Here are the issues I found so far.

hi,
thanks a lot for testing!

> 
> 1 test case failed to build:
> 
>   CC       tests/stat.o
> tests/stat.c: In function âtest__synthesize_statâ:
> tests/stat.c:82:3: error: missing initializer for field âenaâ of
> âstruct <anonymous>â [-Werror=missing-field-initializers]
>    .ena = 200,
>    ^
> In file included from tests/stat.c:5:0:
> /home/lk/group_read/test/perf/tools/perf/util/counts.h:10:8:
> note: âenaâ declared here
>     u64 ena;
>         ^
> tests/stat.c:83:3: error: missing initializer for field ârunâ of
> âstruct <anonymous>â [-Werror=missing-field-initializers]
>    .run = 300,
>    ^
> In file included from tests/stat.c:5:0:
> /home/lk/group_read/test/perf/tools/perf/util/counts.h:11:8:
> note: ârunâ declared here
>     u64 run;
>         ^
> cc1: all warnings being treated as errors
> mv: cannot stat âtests/.stat.o.tmpâ: No such file or directory
> make[3]: *** [tests/stat.o] Error 1
> make[2]: *** [tests] Error 2
> make[1]: *** [perf-in.o] Error 2
> make: *** [all] Error 2

saw this on another server.. have fix already

> 
> 
> 2. it still doesn't work well with uncore event.
> 
> Here is an example:
> sudo ./perf stat -e uncore_imc_1/cas_count_read/ -a --interval-print 100
> --per-socket record -- sleep 1
> #           time socket cpus             counts unit events
>      0.100231142 S0        1               0.04 MiB  uncore_imc_1/cas_count_read/
>      0.100231142 S1        1               0.08 MiB  uncore_imc_1/cas_count_read/
>      0.200583556 S0        1               0.02 MiB  uncore_imc_1/cas_count_read/
>      0.200583556 S1        1               0.02 MiB  uncore_imc_1/cas_count_read/
> 
> sudo ./perf stat report --per-socket
> #           time socket cpus             counts unit events
>      0.100231142 S0       36               0.12 MiB  uncore_imc_1/cas_count_read/
>      0.100231142 S1       28      <not counted> 
> MiB  uncore_imc_1/cas_count_read/
>      0.200583556 S0       36               0.04 MiB  uncore_imc_1/cas_count_read/
>      0.200583556 S1       28      <not counted> 
> MiB  uncore_imc_1/cas_count_read/
> 
> The results are not consistent. 
> 
> I checked the perf report -D result. It looks the wrong CPU id is stored.
> In my system, the uncore event should be monitored in CPU 0 and CPU 19
> But it shows CPU0 and CPU1.
> 
> 0x520 [0x30]: PERF_RECORD_STAT
> ... id 22385, cpu 0, thread 0
> 
> 0x550 [0x30]: PERF_RECORD_STAT
> ... id 22386, cpu 1, thread 0

it's the pmu's cpumask I did not take into account
I think we'll have to send cpumask as attr_update

> 
> 
> 3. I think you have already handled new record type for perf stat record.
> But the "unhandled!" message still show in the perf report -D.      
> 
> 0x598 [0x30]: PERF_RECORD_STAT
> ... id 22385, cpu 0, thread 0
> ... value 1752, enabled 501473097, running 501473097
> : unhandled!      <-------

yep, I was wondering about that as well.. but it's not 'handled' in perf report,
it just displays the raw output of the event.. but I think we could remove that
not to confuse

and perhaps we could also add -D for perf stat report

> 
> 
> 4. Core dump when applying --per-core -a for stat record.
> 
> sudo ./perf stat -e 'cycles' --per-core -a record sleep 1
> 
> ** Error in `./perf': corrupted double-linked list: 0x00000000036eb560 **
> ======= Backtrace: =========
> /lib64/libc.so.6[0x3002e7bbe7]
> /lib64/libc.so.6[0x3002e7d2b5]
> ./perf(perf_env__exit+0xfd)[0x484d1d]
> ./perf[0x47c45f]
> ./perf(main+0x610)[0x421ac0]
> /lib64/libc.so.6(__libc_start_main+0xf5)[0x3002e21b45]
> ./perf[0x421bd9]

could not reproduce this one.. any chance you could compile with
DEBUG=1 and re-run in gdb for more details? like which of the
frees got crazy.. ?

> 5.  perf stat record may not monitor on specific CPU/whole-system.
> However, perf stat report can be set to aggregate per core/socket.
> If so, there is problem to show the data.
> I think we need some warning here.
> 
> For example,
> 
> sudo ./perf stat -e 'cycles' record sleep 1
> 
>  Performance counter stats for 'sleep 1':
> 
>            858,928      cycles
> 
>        1.001120735 seconds time elapsed
> 
> sudo ./perf stat report -A
> 
>  Performance counter stats for '/home/lk/group_read/test/perf/
> tools/perf/perf stat -e cycles record sleep 1':
> 
> CPU-1              858,928      cycles
> 
>        1.001120735 seconds time elapsed

yep, we need to disable those options for process data 

thanks,
jirka

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

* RE: [PATCHv3 00/56] perf stat: Add scripting support
  2015-10-08 20:11   ` Jiri Olsa
@ 2015-10-09 18:31     ` Liang, Kan
  2015-10-14 10:54       ` Jiri Olsa
  0 siblings, 1 reply; 62+ messages in thread
From: Liang, Kan @ 2015-10-09 18:31 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Andi Kleen, Ulrich Drepper,
	Will Deacon, Stephane Eranian, Don Zickus, lkml, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra



> 
> >
> >
> > 3. I think you have already handled new record type for perf stat record.
> > But the "unhandled!" message still show in the perf report -D.
> >
> > 0x598 [0x30]: PERF_RECORD_STAT
> > ... id 22385, cpu 0, thread 0
> > ... value 1752, enabled 501473097, running 501473097
> > : unhandled!      <-------
> 
> yep, I was wondering about that as well.. but it's not 'handled' in perf
> report, it just displays the raw output of the event.. but I think we could
> remove that not to confuse
> 
> and perhaps we could also add -D for perf stat report

Agree.

> 
> >
> >
> > 4. Core dump when applying --per-core -a for stat record.
> >
> > sudo ./perf stat -e 'cycles' --per-core -a record sleep 1
> >
> > ** Error in `./perf': corrupted double-linked list: 0x00000000036eb560
> > ** ======= Backtrace: ========= /lib64/libc.so.6[0x3002e7bbe7]
> > /lib64/libc.so.6[0x3002e7d2b5] ./perf(perf_env__exit+0xfd)[0x484d1d]
> > ./perf[0x47c45f]
> > ./perf(main+0x610)[0x421ac0]
> > /lib64/libc.so.6(__libc_start_main+0xf5)[0x3002e21b45]
> > ./perf[0x421bd9]
> 
> could not reproduce this one.. any chance you could compile with
> DEBUG=1 and re-run in gdb for more details? like which of the frees got
> crazy.. ?
>
The crash is not caused by this patch set. It's also a bug in current perf.
I've submitted a patch for that.
https://lkml.org/lkml/2015/10/9/575

Thanks,
Kan


 


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

* Re: [PATCHv3 00/56] perf stat: Add scripting support
  2015-10-09 18:31     ` Liang, Kan
@ 2015-10-14 10:54       ` Jiri Olsa
  2015-10-14 19:41         ` Liang, Kan
  0 siblings, 1 reply; 62+ messages in thread
From: Jiri Olsa @ 2015-10-14 10:54 UTC (permalink / raw)
  To: Liang, Kan
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Andi Kleen, Ulrich Drepper,
	Will Deacon, Stephane Eranian, Don Zickus, lkml, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra

On Fri, Oct 09, 2015 at 06:31:23PM +0000, Liang, Kan wrote:

SNIP

> > could not reproduce this one.. any chance you could compile with
> > DEBUG=1 and re-run in gdb for more details? like which of the frees got
> > crazy.. ?
> >
> The crash is not caused by this patch set. It's also a bug in current perf.
> I've submitted a patch for that.
> https://lkml.org/lkml/2015/10/9/575
> 
> Thanks,
> Kan

I pushed fixed code into my perf/stat_script branch, could you please test?

thanks,
jirka

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

* RE: [PATCHv3 00/56] perf stat: Add scripting support
  2015-10-14 10:54       ` Jiri Olsa
@ 2015-10-14 19:41         ` Liang, Kan
  0 siblings, 0 replies; 62+ messages in thread
From: Liang, Kan @ 2015-10-14 19:41 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Andi Kleen, Ulrich Drepper,
	Will Deacon, Stephane Eranian, Don Zickus, lkml, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra



> 
> On Fri, Oct 09, 2015 at 06:31:23PM +0000, Liang, Kan wrote:
> 
> SNIP
> 
> > > could not reproduce this one.. any chance you could compile with
> > > DEBUG=1 and re-run in gdb for more details? like which of the frees
> > > got crazy.. ?
> > >
> > The crash is not caused by this patch set. It's also a bug in current perf.
> > I've submitted a patch for that.
> > https://lkml.org/lkml/2015/10/9/575
> >
> > Thanks,
> > Kan
> 
> I pushed fixed code into my perf/stat_script branch, could you please test?
> 

The new fixed code works well. I don't find any issues so far.

Kan

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

end of thread, other threads:[~2015-10-14 19:42 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-06 19:54 [PATCHv3 00/56] perf stat: Add scripting support Jiri Olsa
2015-10-06 19:54 ` [PATCH 01/56] perf tools: Add thread_map event Jiri Olsa
2015-10-06 19:54 ` [PATCH 02/56] perf tools: Add thread_map event sythesize function Jiri Olsa
2015-10-06 19:54 ` [PATCH 03/56] perf tools: Add thread_map__new_event function Jiri Olsa
2015-10-06 19:54 ` [PATCH 04/56] perf tools: Add perf_event__fprintf_thread_map function Jiri Olsa
2015-10-06 19:54 ` [PATCH 05/56] perf tools: Add cpu_map event Jiri Olsa
2015-10-06 19:54 ` [PATCH 06/56] perf tools: Add cpu_map event synthesize function Jiri Olsa
2015-10-06 19:54 ` [PATCH 07/56] perf tools: Add cpu_map__new_event function Jiri Olsa
2015-10-06 19:54 ` [PATCH 08/56] perf tools: Add perf_event__fprintf_cpu_map function Jiri Olsa
2015-10-06 19:54 ` [PATCH 09/56] perf tools: Add stat config event Jiri Olsa
2015-10-06 19:54 ` [PATCH 10/56] perf tools: Add stat config event synthesize function Jiri Olsa
2015-10-06 19:54 ` [PATCH 11/56] perf tools: Add stat config event read function Jiri Olsa
2015-10-06 19:54 ` [PATCH 12/56] perf tools: Add stat event Jiri Olsa
2015-10-06 19:54 ` [PATCH 13/56] perf tools: Add stat event synthesize function Jiri Olsa
2015-10-06 19:54 ` [PATCH 14/56] perf tools: Add stat event read function Jiri Olsa
2015-10-06 19:54 ` [PATCH 15/56] perf tools: Add stat round event Jiri Olsa
2015-10-06 19:54 ` [PATCH 16/56] perf tools: Add stat round event synthesize function Jiri Olsa
2015-10-06 19:54 ` [PATCH 17/56] perf tools: Add stat events fprintf functions Jiri Olsa
2015-10-06 19:54 ` [PATCH 18/56] perf tools: Add attr_update event Jiri Olsa
2015-10-06 19:54 ` [PATCH 19/56] perf tools: Add attr_update event unit type Jiri Olsa
2015-10-06 19:54 ` [PATCH 20/56] perf tools: Add attr_update event scale type Jiri Olsa
2015-10-06 19:55 ` [PATCH 21/56] perf tools: Add attr_update event name type Jiri Olsa
2015-10-06 19:55 ` [PATCH 22/56] perf tools: Add perf_event__fprintf_attr_update function Jiri Olsa
2015-10-06 19:55 ` [PATCH 23/56] perf report: Display newly added events in raw dump Jiri Olsa
2015-10-06 19:55 ` [PATCH 24/56] perf tools: Introduce stat feature Jiri Olsa
2015-10-06 19:55 ` [PATCH 25/56] perf tools: Move id_offset out of struct perf_evsel union Jiri Olsa
2015-10-06 19:55 ` [PATCH 26/56] perf stat: Rename perf_stat struct into perf_stat_evsel Jiri Olsa
2015-10-06 19:55 ` [PATCH 27/56] perf stat: Add AGGR_UNSET mode Jiri Olsa
2015-10-06 19:55 ` [PATCH 28/56] perf stat record: Add record command Jiri Olsa
2015-10-06 19:55 ` [PATCH 29/56] perf stat record: Initialize record features Jiri Olsa
2015-10-06 19:55 ` [PATCH 30/56] perf stat record: Synthesize stat record data Jiri Olsa
2015-10-06 19:55 ` [PATCH 31/56] perf stat record: Store events IDs in perf data file Jiri Olsa
2015-10-06 19:55 ` [PATCH 32/56] perf stat record: Add pipe support for record command Jiri Olsa
2015-10-06 19:55 ` [PATCH 33/56] perf stat record: Write stat events on record Jiri Olsa
2015-10-06 19:55 ` [PATCH 34/56] perf stat record: Write stat round " Jiri Olsa
2015-10-06 19:55 ` [PATCH 35/56] perf stat record: Do not allow record with multiple runs mode Jiri Olsa
2015-10-06 19:55 ` [PATCH 36/56] perf stat record: Synthesize attr update events Jiri Olsa
2015-10-06 19:55 ` [PATCH 37/56] perf tools: Add cpu_map__empty_new interface Jiri Olsa
2015-10-06 19:55 ` [PATCH 38/56] perf tools: Make cpu_map__build_map global Jiri Olsa
2015-10-06 19:55 ` [PATCH 39/56] perf tools: Add data arg to cpu_map__build_map callback Jiri Olsa
2015-10-06 19:55 ` [PATCH 40/56] perf stat report: Cache aggregated map entries in extra cpumap Jiri Olsa
2015-10-06 19:55 ` [PATCH 41/56] perf stat report: Add report command Jiri Olsa
2015-10-06 19:55 ` [PATCH 42/56] perf stat report: Process cpu/threads maps Jiri Olsa
2015-10-06 19:55 ` [PATCH 43/56] perf stat report: Process stat config event Jiri Olsa
2015-10-06 19:55 ` [PATCH 44/56] perf stat report: Add support to initialize aggr_map from file Jiri Olsa
2015-10-06 19:55 ` [PATCH 45/56] perf stat report: Process stat and stat round events Jiri Olsa
2015-10-06 19:55 ` [PATCH 46/56] perf stat report: Process attr update events Jiri Olsa
2015-10-06 19:55 ` [PATCH 47/56] perf stat report: Move csv_sep initialization before report command Jiri Olsa
2015-10-06 19:55 ` [PATCH 48/56] perf stat report: Allow to override aggr_mode Jiri Olsa
2015-10-06 19:55 ` [PATCH 49/56] perf script: Check output fields only for samples Jiri Olsa
2015-10-06 19:55 ` [PATCH 50/56] perf script: Process cpu/threads maps Jiri Olsa
2015-10-06 19:55 ` [PATCH 51/56] perf script: Process stat config event Jiri Olsa
2015-10-06 19:55 ` [PATCH 52/56] perf script: Add process_stat/process_stat_interval scripting interface Jiri Olsa
2015-10-06 19:55 ` [PATCH 53/56] perf script: Add stat default handlers Jiri Olsa
2015-10-06 19:55 ` [PATCH 54/56] perf script: Display stat events by default Jiri Olsa
2015-10-06 19:55 ` [PATCH 55/56] perf script: Add python support for stat events Jiri Olsa
2015-10-06 19:55 ` [PATCH 56/56] perf script: Add stat-cpi.py script Jiri Olsa
2015-10-08 18:37 ` [PATCHv3 00/56] perf stat: Add scripting support Liang, Kan
2015-10-08 20:11   ` Jiri Olsa
2015-10-09 18:31     ` Liang, Kan
2015-10-14 10:54       ` Jiri Olsa
2015-10-14 19:41         ` Liang, Kan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).