perf stat: Add scripting support
Jiri Olsa
reviewercover perf stat: Add scripting support
hi,
sending RFC on another attempt for stat scripting.
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.
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:uThe 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
This patchset still has MANY rough edges and loose ends, but I think it's better approach than to define our own formula scripting language.
The patchset is growing and there's still a long way to go, so I'd like to hear some opinions before I go further ;-)
thanks for comments,
jirka
---
Jiri Olsa (47):
perf test: Check for refcnt in thread_map test
perf stat: Introduce struct perf_stat_config
perf stat: Move scale into struct perf_stat_config
perf stat: Move output into struct perf_stat_config
perf stat: Move interval into struct perf_stat_config
perf stat: Pass struct perf_stat_config into process_counter perf stat: Move counter processing code into stat object
perf tools: Use bool instead of target argument in perf_evlist__propagate_maps perf tools: Tolerate NULL maps in perf_evlist__propagate_maps perf tools: Force perf_evlist__set_maps to propagate maps through events perf tools: Use argv style storage for cmdline feature data
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 cpu_map event
perf tools: Add cpu_map event synthesize function
perf tools: Add cpu_map__new_event 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: Introduce stat feature
perf tools: Move id_offset out of struct perf_evsel union
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 report: Add report command
perf stat report: Process cpu/threads maps
perf stat report: Process stat config event
perf stat report: Process stat and stat round events
perf stat report: Move csv_sep initialization before report command 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 | 24 + tools/perf/builtin-record.c | 2 + tools/perf/builtin-script.c | 143 ++++- tools/perf/builtin-stat.c | 579 +++++++++++++++------ tools/perf/scripts/python/stat-cpi.py | 74 +++ tools/perf/tests/Build | 2 + tools/perf/tests/builtin-test.c | 20 + tools/perf/tests/cpumap.c | 39 ++ tools/perf/tests/stat.c | 108 ++++ tools/perf/tests/tests.h | 6 + tools/perf/tests/thread-map.c | 47 ++ tools/perf/util/cpumap.c | 27 + tools/perf/util/cpumap.h | 3 + tools/perf/util/event.c | 170 ++++++ tools/perf/util/event.h | 94 +++- tools/perf/util/evlist.c | 34 +- tools/perf/util/evlist.h | 14 +- tools/perf/util/evsel.h | 2 +- tools/perf/util/header.c | 49 +- tools/perf/util/header.h | 2 + .../util/scripting-engines/trace-event-python.c | 113 +++- tools/perf/util/session.c | 123 +++++ tools/perf/util/stat.c | 162 ++++++ tools/perf/util/stat.h | 16 + tools/perf/util/thread_map.c | 27 + tools/perf/util/thread_map.h | 3 + tools/perf/util/tool.h | 7 +- tools/perf/util/trace-event.h | 4 + 28 files changed, 1686 insertions(+), 208 deletions(-) create mode 100644 tools/perf/scripts/python/stat-cpi.py create mode 100644 tools/perf/tests/cpumap.c create mode 100644 tools/perf/tests/stat.c
Jiri Olsa
reviewerPATCH 1/47 perf test: Check for refcnt in thread_map test
Checking also for refcnt in thread_map test.
--- tools/perf/tests/thread-map.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/tests/thread-map.c +4 -0
@@ -20,6 +20,8 @@ int test__thread_map(void)TEST_ASSERT_VAL ("wrong comm" ,thread_map__comm (map,0 ) && !strcmp (thread_map__comm (map,0 ),"perf" )); +TEST_ASSERT_VAL ("wrong refcnt" , +atomic_read (&map->refcnt) ==1 );thread_map__put (map);/* test dummy pid */
@@ -33,6 +35,8 @@ int test__thread_map(void)TEST_ASSERT_VAL ("wrong comm" ,thread_map__comm (map,0 ) && !strcmp (thread_map__comm (map,0 ),"dummy" )); +TEST_ASSERT_VAL ("wrong refcnt" , +atomic_read (&map->refcnt) ==1 );thread_map__put (map);return 0 ; }
Signature · 1 line
2.4.3
Re: [PATCH 01/47] perf test: Check for refcnt in thread_map test
Em Tue, Jul 21, 2015 at 02:31:21PM +0200, Jiri Olsa escreveu:
Quoted 1 line
Checking also for refcnt in
thread_maptest.
Applied.
Quoted 30 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/tests/thread-map.c | 4 ++++ 1 file changed, 4 insertions(+)tools/perf/tests/thread-map.c +4
-0@@ -20,6 +20,8 @@ int test__thread_map(void)TEST_ASSERT_VAL ("wrong comm" ,thread_map__comm (map,0 ) && !strcmp (thread_map__comm (map,0 ),"perf" )); +TEST_ASSERT_VAL ("wrong refcnt" , +atomic_read (&map->refcnt) ==1 );thread_map__put (map);/* test dummy pid */ @@ -33,6 +35,8 @@ int test__thread_map(void)TEST_ASSERT_VAL ("wrong comm" ,thread_map__comm (map,0 ) && !strcmp (thread_map__comm (map,0 ),"dummy" )); +TEST_ASSERT_VAL ("wrong refcnt" , +atomic_read (&map->refcnt) ==1 );thread_map__put (map);return 0 ; }Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf test: Check for refcnt in thread_map test
In reply to Jiri Olsaperf test: Check for refcnt in thread_map test
Commit-ID: 35318d204db83f5c1f24c281839763b271b9b323 Gitweb: http://git.kernel.org/tip/35318d204db83f5c1f24c281839763b271b9b323 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:21 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 21 Jul 2015 14:20:32 -0300
perf test: Check for refcnt in thread_map test
Checking also for refcnt in thread_map test.
--- tools/perf/tests/thread-map.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/tests/thread-map.c +4 -0
@@ -20,6 +20,8 @@ int test__thread_map(void)TEST_ASSERT_VAL ("wrong comm" ,thread_map__comm (map,0 ) && !strcmp (thread_map__comm (map,0 ),"perf" )); +TEST_ASSERT_VAL ("wrong refcnt" , +atomic_read (&map->refcnt) ==1 );thread_map__put (map);/* test dummy pid */
@@ -33,6 +35,8 @@ int test__thread_map(void)TEST_ASSERT_VAL ("wrong comm" ,thread_map__comm (map,0 ) && !strcmp (thread_map__comm (map,0 ),"dummy" )); +TEST_ASSERT_VAL ("wrong refcnt" , +atomic_read (&map->refcnt) ==1 );thread_map__put (map);return 0 ; }
Jiri Olsa
reviewerPATCH 2/47 perf stat: Introduce struct perf_stat_config
In reply to Jiri OlsaMoving aggr_mode into new struct. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 39 ++++++++++++++++++++++----------------- tools/perf/util/stat.h | 4 ++++ 2 files changed, 26 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +22 -17
@@ -102,7 +102,6 @@ static struct target target = {static int run_count =1 ;static bool no_inherit = false;static bool scale = true; -static enum aggr_mode aggr_mode =AGGR_GLOBAL ;static volatile pid_t child_pid =-1 ;static bool null_run = false;static int detailed_run =0 ;
@@ -126,6 +125,10 @@ static int (*aggr_get_id)(struct cpu_map *m, int cpu);static volatile int done =0 ; +static struct perf_stat_config stat_config = { + .aggr_mode =AGGR_GLOBAL , +}; +static inline void diff_timespec (struct timespec *r,struct timespec *a,struct timespec *b) {
@@ -230,7 +233,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (skip) count = &zero; -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_THREAD :case AGGR_CORE :case AGGR_SOCKET :
@@ -238,7 +241,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count);perf_counts_values__scale (count, scale,NULL ); -if (aggr_mode ==AGGR_NONE ) +if (stat_config.aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL :
@@ -291,7 +294,7 @@ static int process_counter(struct perf_evsel *counter)if (ret)return ret; -if (aggr_mode !=AGGR_GLOBAL ) +if (stat_config.aggr_mode !=AGGR_GLOBAL )return 0 ;if (!counter->snapshot)
@@ -578,7 +581,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)static void aggr_printout (struct perf_evsel *evsel,int id,int nr) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_CORE : fprintf(output, "S%d-C%*d%s%*d%s", cpu_map__id_to_socket(id),
@@ -670,7 +673,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)aggr_printout (evsel, id, nr); -if (aggr_mode ==AGGR_GLOBAL ) +if (stat_config.aggr_mode ==AGGR_GLOBAL ) cpu =0 ;fprintf (output, fmt, avg, csv_sep);
@@ -688,7 +691,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (csv_output || interval)return ; -perf_stat__print_shadow_stats (output, evsel, avg, cpu, aggr_mode); +perf_stat__print_shadow_stats (output, evsel, avg, cpu, + stat_config.aggr_mode); }static void print_aggr (char *prefix)
@@ -909,7 +913,7 @@ static void print_interval(char *prefix, struct timespec *ts)sprintf (prefix,"%6lu.%09lu%s" , ts->tv_sec, ts->tv_nsec, csv_sep);if (num_print_interval ==0 && !csv_output) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_SOCKET :fprintf (output,"# time socket cpus counts %*s events\n" , unit_width,"unit" );break ;
@@ -985,7 +989,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)else print_header (argc, argv); -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_CORE :case AGGR_SOCKET :print_aggr (prefix);
@@ -1064,7 +1068,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,static int perf_stat_init_aggr_mode (void ) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_SOCKET :if (cpu_map__build_socket_map (evsel_list->cpus, &aggr_map)) {perror ("cannot build socket map" );
@@ -1286,7 +1290,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) stat__set_big_num),OPT_STRING ('C' ,"cpu" , &target.cpu_list,"cpu" ,"list of cpus to monitor in system-wide" ), -OPT_SET_UINT ('A' ,"no-aggr" , &aggr_mode, +OPT_SET_UINT ('A' ,"no-aggr" , &stat_config.aggr_mode,"disable CPU count aggregation" ,AGGR_NONE ),OPT_STRING ('x' ,"field-separator" , &csv_sep,"separator" , "print counts with custom separator"),
@@ -1302,11 +1306,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "command to run after to the measured command"),OPT_UINTEGER ('I' ,"interval-print" , &interval,"print counts at regular interval in ms (>= 100)" ), -OPT_SET_UINT (0 ,"per-socket" , &aggr_mode, +OPT_SET_UINT (0 ,"per-socket" , &stat_config.aggr_mode,"aggregate counts per processor socket" ,AGGR_SOCKET ), -OPT_SET_UINT (0 ,"per-core" , &aggr_mode, +OPT_SET_UINT (0 ,"per-core" , &stat_config.aggr_mode,"aggregate counts per physical processor core" ,AGGR_CORE ), -OPT_SET_UINT (0 ,"per-thread" , &aggr_mode, +OPT_SET_UINT (0 ,"per-thread" , &stat_config.aggr_mode,"aggregate counts per thread" ,AGGR_THREAD ),OPT_UINTEGER ('D' ,"delay" , &initial_delay, "ms to wait before starting measurement after program start"),
@@ -1399,7 +1403,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) run_count =1 ; } -if ((aggr_mode ==AGGR_THREAD ) && !target__has_task (&target)) { +if ((stat_config.aggr_mode ==AGGR_THREAD ) && !target__has_task (&target)) {fprintf (stderr,"The --per-thread option is only available " "when monitoring via -p -t options.\n" );parse_options_usage (NULL , options,"p" ,1 );
@@ -1411,7 +1415,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)* no_aggr, cgroup are for system-wide only * --per-thread is aggregated per thread, we dont mix it with cpu mode */ -if (((aggr_mode !=AGGR_GLOBAL && aggr_mode !=AGGR_THREAD ) || nr_cgroups) && +if (((stat_config.aggr_mode !=AGGR_GLOBAL && + stat_config.aggr_mode !=AGGR_THREAD ) || nr_cgroups) && !target__has_cpu (&target)) {fprintf (stderr,"both cgroup and no-aggregation " "modes only available in system-wide mode\n" );
@@ -1444,7 +1449,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)* Initialize thread_map with comm names, * so we could print it out on output. */ -if (aggr_mode ==AGGR_THREAD ) +if (stat_config.aggr_mode ==AGGR_THREAD )thread_map__read_comms (evsel_list->threads);if (interval && interval <100 ) {
tools/perf/util/stat.h +4 -0
@@ -50,6 +50,10 @@ struct perf_counts {struct xyarray *values; }; +struct perf_stat_config { +enum aggr_mode aggr_mode; +}; +static inline struct perf_counts_values *perf_counts (struct perf_counts *counts,int cpu,int thread) {
Signature · 1 line
2.4.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/47] perf stat: Introduce struct perf_stat_config
Em Tue, Jul 21, 2015 at 02:31:22PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
Moving
aggr_modeinto new struct. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
Why not use 'struct perf_stat' for that? It is already there and is supposed to hold the stat tool internal state. Yeah, lots of those globals should go there as well, just like we have the 'perf_sched', 'perf_top', 'perf_script', etc structs.
- Arnaldo
Quoted 181 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/builtin-stat.c | 39 ++++++++++++++++++++++----------------- tools/perf/util/stat.h | 4 ++++ 2 files changed, 26 insertions(+), 17 deletions(-)tools/perf/builtin-stat.c +22
-17@@ -102,7 +102,6 @@ static struct target target = {static int run_count =1 ;static bool no_inherit = false;static bool scale = true; -static enum aggr_mode aggr_mode =AGGR_GLOBAL ;static volatile pid_t child_pid =-1 ;static bool null_run = false;static int detailed_run =0 ;@@ -126,6 +125,10 @@ static int (*aggr_get_id)(struct cpu_map *m, int cpu);static volatile int done =0 ; +static struct perf_stat_config stat_config = { + .aggr_mode =AGGR_GLOBAL , +}; +static inline void diff_timespec (struct timespec *r,struct timespec *a,struct timespec *b) {@@ -230,7 +233,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (skip) count = &zero; -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_THREAD :case AGGR_CORE :case AGGR_SOCKET :@@ -238,7 +241,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count);perf_counts_values__scale (count, scale,NULL ); -if (aggr_mode ==AGGR_NONE ) +if (stat_config.aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL :@@ -291,7 +294,7 @@ static int process_counter(struct perf_evsel *counter)if (ret)return ret; -if (aggr_mode !=AGGR_GLOBAL ) +if (stat_config.aggr_mode !=AGGR_GLOBAL )return 0 ;if (!counter->snapshot)@@ -578,7 +581,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)static void aggr_printout (struct perf_evsel *evsel,int id,int nr) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_CORE : fprintf(output, "S%d-C%*d%s%*d%s", cpu_map__id_to_socket(id),@@ -670,7 +673,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)aggr_printout (evsel, id, nr); -if (aggr_mode ==AGGR_GLOBAL ) +if (stat_config.aggr_mode ==AGGR_GLOBAL ) cpu =0 ;fprintf (output, fmt, avg, csv_sep);@@ -688,7 +691,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (csv_output || interval)return ; -perf_stat__print_shadow_stats (output, evsel, avg, cpu, aggr_mode); +perf_stat__print_shadow_stats (output, evsel, avg, cpu, + stat_config.aggr_mode); }static void print_aggr (char *prefix)@@ -909,7 +913,7 @@ static void print_interval(char *prefix, struct timespec *ts)sprintf (prefix,"%6lu.%09lu%s" , ts->tv_sec, ts->tv_nsec, csv_sep);if (num_print_interval ==0 && !csv_output) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_SOCKET :fprintf (output,"# time socket cpus counts %*s events\n" , unit_width,"unit" );break ;@@ -985,7 +989,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)else print_header (argc, argv); -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_CORE :case AGGR_SOCKET :print_aggr (prefix);@@ -1064,7 +1068,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,static int perf_stat_init_aggr_mode (void ) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_SOCKET :if (cpu_map__build_socket_map (evsel_list->cpus, &aggr_map)) {perror ("cannot build socket map" );@@ -1286,7 +1290,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) stat__set_big_num),OPT_STRING ('C' ,"cpu" , &target.cpu_list,"cpu" ,"list of cpus to monitor in system-wide" ), -OPT_SET_UINT ('A' ,"no-aggr" , &aggr_mode, +OPT_SET_UINT ('A' ,"no-aggr" , &stat_config.aggr_mode,"disable CPU count aggregation" ,AGGR_NONE ),OPT_STRING ('x' ,"field-separator" , &csv_sep,"separator" , "print counts with custom separator"),@@ -1302,11 +1306,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "command to run after to the measured command"),OPT_UINTEGER ('I' ,"interval-print" , &interval,"print counts at regular interval in ms (>= 100)" ), -OPT_SET_UINT (0 ,"per-socket" , &aggr_mode, +OPT_SET_UINT (0 ,"per-socket" , &stat_config.aggr_mode,"aggregate counts per processor socket" ,AGGR_SOCKET ), -OPT_SET_UINT (0 ,"per-core" , &aggr_mode, +OPT_SET_UINT (0 ,"per-core" , &stat_config.aggr_mode,"aggregate counts per physical processor core" ,AGGR_CORE ), -OPT_SET_UINT (0 ,"per-thread" , &aggr_mode, +OPT_SET_UINT (0 ,"per-thread" , &stat_config.aggr_mode,"aggregate counts per thread" ,AGGR_THREAD ),OPT_UINTEGER ('D' ,"delay" , &initial_delay, "ms to wait before starting measurement after program start"),@@ -1399,7 +1403,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) run_count =1 ; } -if ((aggr_mode ==AGGR_THREAD ) && !target__has_task (&target)) { +if ((stat_config.aggr_mode ==AGGR_THREAD ) && !target__has_task (&target)) {fprintf (stderr,"The --per-thread option is only available " "when monitoring via -p -t options.\n" );parse_options_usage (NULL , options,"p" ,1 );@@ -1411,7 +1415,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)* no_aggr, cgroup are for system-wide only * --per-thread is aggregated per thread, we dont mix it with cpu mode */ -if (((aggr_mode !=AGGR_GLOBAL && aggr_mode !=AGGR_THREAD ) || nr_cgroups) && +if (((stat_config.aggr_mode !=AGGR_GLOBAL && + stat_config.aggr_mode !=AGGR_THREAD ) || nr_cgroups) && !target__has_cpu (&target)) {fprintf (stderr,"both cgroup and no-aggregation " "modes only available in system-wide mode\n" );@@ -1444,7 +1449,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)* Initialize thread_map with comm names, * so we could print it out on output. */ -if (aggr_mode ==AGGR_THREAD ) +if (stat_config.aggr_mode ==AGGR_THREAD )thread_map__read_comms (evsel_list->threads);if (interval && interval <100 ) {tools/perf/util/stat.h +4
-0@@ -50,6 +50,10 @@ struct perf_counts {struct xyarray *values; }; +struct perf_stat_config { +enum aggr_mode aggr_mode; +}; +static inline struct perf_counts_values *perf_counts (struct perf_counts *counts,int cpu,int thread) {Signature · 1 line
2.4.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/47] perf stat: Introduce struct perf_stat_config
Em Tue, Jul 21, 2015 at 02:24:19PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Tue, Jul 21, 2015 at 02:31:22PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
Moving
aggr_modeinto new struct. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.Why not use 'struct
perf_stat' for that? It is already there and is supposed to hold the stat tool internal state. Yeah, lots of those globals should go there as well, just like we have the 'perf_sched', 'perf_top', 'perf_script',y etc structs.
Erm, saw some more patches, this stuff gets marshalled into perf.data, continuing to read... Probably you made this somehow extensible...
- Arnaldo
Re: [PATCH 02/47] perf stat: Introduce struct perf_stat_config
Quoted 10 lines · Arnaldo Carvalho de Melo
Em Tue, Jul 21, 2015 at 02:24:19PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Tue, Jul 21, 2015 at 02:31:22PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
Moving
aggr_modeinto new struct. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.Why not use 'struct
perf_stat' for that? It is already there and is supposed to hold the stat tool internal state. Yeah, lots of those globals should go there as well, just like we have the 'perf_sched', 'perf_top', 'perf_script',y etc structs.
hm, but it's used as perf_evsel priv data..
the 'struct perf_stat_config' is coupled with the same event, we could switch the name for:
'struct perf_stat' -> 'struct perf_evsel_stat'
'struct perf_stat_cmd' -> 'struct perf_stat'
and move 'struct perf_stat_record' under 'struct perf_stat' ;-)
Quoted 3 lines
Erm, saw some more patches, this stuff gets marshalled into perf.data, continuing to read... Probably you made this somehow extensible...
yep, I'm storing it in 'tag-value' way, it's mentioned in the changelog
jirka
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Introduce struct perf_stat_config
In reply to Jiri Olsaperf stat: Introduce struct perf_stat_config
Commit-ID: 421a50f3fafaf271bb3293378eaafca71337dfec Gitweb: http://git.kernel.org/tip/421a50f3fafaf271bb3293378eaafca71337dfec Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:22 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 6 Aug 2015 16:02:29 -0300
perf stat: Introduce struct perf_stat_config
Moving 'aggr_mode' into new struct. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 39 ++++++++++++++++++++++----------------- tools/perf/util/stat.h | 4 ++++ 2 files changed, 26 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +22 -17
@@ -102,7 +102,6 @@ static struct target target = {static int run_count =1 ;static bool no_inherit = false;static bool scale = true; -static enum aggr_mode aggr_mode =AGGR_GLOBAL ;static volatile pid_t child_pid =-1 ;static bool null_run = false;static int detailed_run =0 ;
@@ -126,6 +125,10 @@ static int (*aggr_get_id)(struct cpu_map *m, int cpu);static volatile int done =0 ; +static struct perf_stat_config stat_config = { + .aggr_mode =AGGR_GLOBAL , +}; +static inline void diff_timespec (struct timespec *r,struct timespec *a,struct timespec *b) {
@@ -230,7 +233,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (skip) count = &zero; -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_THREAD :case AGGR_CORE :case AGGR_SOCKET :
@@ -238,7 +241,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count);perf_counts_values__scale (count, scale,NULL ); -if (aggr_mode ==AGGR_NONE ) +if (stat_config.aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL :
@@ -291,7 +294,7 @@ static int process_counter(struct perf_evsel *counter)if (ret)return ret; -if (aggr_mode !=AGGR_GLOBAL ) +if (stat_config.aggr_mode !=AGGR_GLOBAL )return 0 ;if (!counter->snapshot)
@@ -578,7 +581,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)static void aggr_printout (struct perf_evsel *evsel,int id,int nr) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_CORE : fprintf(output, "S%d-C%*d%s%*d%s", cpu_map__id_to_socket(id),
@@ -670,7 +673,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)aggr_printout (evsel, id, nr); -if (aggr_mode ==AGGR_GLOBAL ) +if (stat_config.aggr_mode ==AGGR_GLOBAL ) cpu =0 ;fprintf (output, fmt, avg, csv_sep);
@@ -688,7 +691,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (csv_output || interval)return ; -perf_stat__print_shadow_stats (output, evsel, avg, cpu, aggr_mode); +perf_stat__print_shadow_stats (output, evsel, avg, cpu, + stat_config.aggr_mode); }static void print_aggr (char *prefix)
@@ -909,7 +913,7 @@ static void print_interval(char *prefix, struct timespec *ts)sprintf (prefix,"%6lu.%09lu%s" , ts->tv_sec, ts->tv_nsec, csv_sep);if (num_print_interval ==0 && !csv_output) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_SOCKET :fprintf (output,"# time socket cpus counts %*s events\n" , unit_width,"unit" );break ;
@@ -985,7 +989,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)else print_header (argc, argv); -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_CORE :case AGGR_SOCKET :print_aggr (prefix);
@@ -1064,7 +1068,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,static int perf_stat_init_aggr_mode (void ) { -switch (aggr_mode) { +switch (stat_config.aggr_mode) {case AGGR_SOCKET :if (cpu_map__build_socket_map (evsel_list->cpus, &aggr_map)) {perror ("cannot build socket map" );
@@ -1286,7 +1290,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) stat__set_big_num),OPT_STRING ('C' ,"cpu" , &target.cpu_list,"cpu" ,"list of cpus to monitor in system-wide" ), -OPT_SET_UINT ('A' ,"no-aggr" , &aggr_mode, +OPT_SET_UINT ('A' ,"no-aggr" , &stat_config.aggr_mode,"disable CPU count aggregation" ,AGGR_NONE ),OPT_STRING ('x' ,"field-separator" , &csv_sep,"separator" , "print counts with custom separator"),
@@ -1302,11 +1306,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "command to run after to the measured command"),OPT_UINTEGER ('I' ,"interval-print" , &interval,"print counts at regular interval in ms (>= 100)" ), -OPT_SET_UINT (0 ,"per-socket" , &aggr_mode, +OPT_SET_UINT (0 ,"per-socket" , &stat_config.aggr_mode,"aggregate counts per processor socket" ,AGGR_SOCKET ), -OPT_SET_UINT (0 ,"per-core" , &aggr_mode, +OPT_SET_UINT (0 ,"per-core" , &stat_config.aggr_mode,"aggregate counts per physical processor core" ,AGGR_CORE ), -OPT_SET_UINT (0 ,"per-thread" , &aggr_mode, +OPT_SET_UINT (0 ,"per-thread" , &stat_config.aggr_mode,"aggregate counts per thread" ,AGGR_THREAD ),OPT_UINTEGER ('D' ,"delay" , &initial_delay, "ms to wait before starting measurement after program start"),
@@ -1399,7 +1403,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) run_count =1 ; } -if ((aggr_mode ==AGGR_THREAD ) && !target__has_task (&target)) { +if ((stat_config.aggr_mode ==AGGR_THREAD ) && !target__has_task (&target)) {fprintf (stderr,"The --per-thread option is only available " "when monitoring via -p -t options.\n" );parse_options_usage (NULL , options,"p" ,1 );
@@ -1411,7 +1415,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)* no_aggr, cgroup are for system-wide only * --per-thread is aggregated per thread, we dont mix it with cpu mode */ -if (((aggr_mode !=AGGR_GLOBAL && aggr_mode !=AGGR_THREAD ) || nr_cgroups) && +if (((stat_config.aggr_mode !=AGGR_GLOBAL && + stat_config.aggr_mode !=AGGR_THREAD ) || nr_cgroups) && !target__has_cpu (&target)) {fprintf (stderr,"both cgroup and no-aggregation " "modes only available in system-wide mode\n" );
@@ -1444,7 +1449,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)* Initialize thread_map with comm names, * so we could print it out on output. */ -if (aggr_mode ==AGGR_THREAD ) +if (stat_config.aggr_mode ==AGGR_THREAD )thread_map__read_comms (evsel_list->threads);if (interval && interval <100 ) {
tools/perf/util/stat.h +4 -0
@@ -50,6 +50,10 @@ struct perf_counts {struct xyarray *values; }; +struct perf_stat_config { +enum aggr_mode aggr_mode; +}; +static inline struct perf_counts_values *perf_counts (struct perf_counts *counts,int cpu,int thread) {
Jiri Olsa
reviewerPATCH 3/47 perf stat: Move scale into struct perf_stat_config
In reply to Jiri OlsaMoving scale into struct perf_stat_config. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 12 ++++++------ tools/perf/util/stat.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-)
tools/perf/builtin-stat.c +6 -6
@@ -101,7 +101,6 @@ static struct target target = {static int run_count =1 ;static bool no_inherit = false; -static bool scale = true;static volatile pid_t child_pid =-1 ;static bool null_run = false;static int detailed_run =0 ;
@@ -127,6 +126,7 @@ static volatile int done = 0;static struct perf_stat_config stat_config = { .aggr_mode =AGGR_GLOBAL , + .scale = true, }; static inline void diff_timespec(struct timespec *r, struct timespec *a,
@@ -151,7 +151,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) {struct perf_event_attr *attr = &evsel->attr; -if (scale) +if (stat_config.scale) attr->read_format =PERF_FORMAT_TOTAL_TIME_ENABLED |PERF_FORMAT_TOTAL_TIME_RUNNING ;
@@ -240,13 +240,13 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,case AGGR_NONE :if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count); -perf_counts_values__scale (count, scale,NULL ); +perf_counts_values__scale (count, stat_config.scale,NULL );if (stat_config.aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL : aggr->val += count->val; -if (scale) { +if (stat_config.scale) { aggr->ena += count->ena; aggr->run += count->run; }
@@ -299,7 +299,7 @@ static int process_counter(struct perf_evsel *counter)if (!counter->snapshot)perf_evsel__compute_deltas (counter,-1 ,-1 , aggr); -perf_counts_values__scale (aggr, scale, &counter->counts->scaled); +perf_counts_values__scale (aggr, stat_config.scale, &counter->counts->scaled);for (i =0 ; i <3 ; i++)update_stats (&ps->res_stats[i], count[i]);
@@ -1274,7 +1274,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "system-wide collection from all CPUs"),OPT_BOOLEAN ('g' ,"group" , &group,"put the counters into a counter group" ), -OPT_BOOLEAN ('c' ,"scale" , &scale,"scale/normalize counters" ), +OPT_BOOLEAN ('c' ,"scale" , &stat_config.scale,"scale/normalize counters" ),OPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show counter open errors, etc)" ), OPT_INTEGER('r', "repeat", &run_count,
tools/perf/util/stat.h +1 -0
@@ -52,6 +52,7 @@ struct perf_counts {struct perf_stat_config {enum aggr_mode aggr_mode; +bool scale; }; static inline struct perf_counts_values*
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Move 'scale' into struct perf_stat_config
perf stat: Move 'scale' into struct perf_stat_config
Commit-ID: 711a572ea8ae7e9ab6575403c6d632d058d5cb3d Gitweb: http://git.kernel.org/tip/711a572ea8ae7e9ab6575403c6d632d058d5cb3d Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:23 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 6 Aug 2015 16:02:39 -0300
perf stat: Move 'scale' into struct perf_stat_config
Moving 'scale' into struct perf_stat_config. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 12 ++++++------ tools/perf/util/stat.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-)
tools/perf/builtin-stat.c +6 -6
@@ -101,7 +101,6 @@ static struct target target = {static int run_count =1 ;static bool no_inherit = false; -static bool scale = true;static volatile pid_t child_pid =-1 ;static bool null_run = false;static int detailed_run =0 ;
@@ -127,6 +126,7 @@ static volatile int done = 0;static struct perf_stat_config stat_config = { .aggr_mode =AGGR_GLOBAL , + .scale = true, }; static inline void diff_timespec(struct timespec *r, struct timespec *a,
@@ -151,7 +151,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) {struct perf_event_attr *attr = &evsel->attr; -if (scale) +if (stat_config.scale) attr->read_format =PERF_FORMAT_TOTAL_TIME_ENABLED |PERF_FORMAT_TOTAL_TIME_RUNNING ;
@@ -240,13 +240,13 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,case AGGR_NONE :if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count); -perf_counts_values__scale (count, scale,NULL ); +perf_counts_values__scale (count, stat_config.scale,NULL );if (stat_config.aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL : aggr->val += count->val; -if (scale) { +if (stat_config.scale) { aggr->ena += count->ena; aggr->run += count->run; }
@@ -299,7 +299,7 @@ static int process_counter(struct perf_evsel *counter)if (!counter->snapshot)perf_evsel__compute_deltas (counter,-1 ,-1 , aggr); -perf_counts_values__scale (aggr, scale, &counter->counts->scaled); +perf_counts_values__scale (aggr, stat_config.scale, &counter->counts->scaled);for (i =0 ; i <3 ; i++)update_stats (&ps->res_stats[i], count[i]);
@@ -1274,7 +1274,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "system-wide collection from all CPUs"),OPT_BOOLEAN ('g' ,"group" , &group,"put the counters into a counter group" ), -OPT_BOOLEAN ('c' ,"scale" , &scale,"scale/normalize counters" ), +OPT_BOOLEAN ('c' ,"scale" , &stat_config.scale,"scale/normalize counters" ),OPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show counter open errors, etc)" ), OPT_INTEGER('r', "repeat", &run_count,
tools/perf/util/stat.h +1 -0
@@ -52,6 +52,7 @@ struct perf_counts {struct perf_stat_config {enum aggr_mode aggr_mode; +bool scale; }; static inline struct perf_counts_values*
Jiri Olsa
reviewerPATCH 4/47 perf stat: Move output into struct perf_stat_config
In reply to Jiri OlsaMoving output into struct perf_stat_config. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 35 +++++++++++++++++++++++------------ tools/perf/util/stat.h | 1 + 2 files changed, 24 insertions(+), 12 deletions(-)
tools/perf/builtin-stat.c +23 -12
@@ -110,7 +110,6 @@ static int big_num_opt = -1;static const char *csv_sep =NULL ;static bool csv_output = false;static bool group = false; -static FILE *output =NULL ;static const char *pre_cmd =NULL ;static const char *post_cmd =NULL ;static bool sync_run = false;
@@ -305,7 +304,7 @@ static int process_counter(struct perf_evsel *counter)update_stats (&ps->res_stats[i], count[i]);if (verbose) { -fprintf (output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" , +fprintf (stat_config.output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" ,perf_evsel__name (counter), count[0 ], count[1 ], count[2 ]); }
@@ -548,13 +547,13 @@ static int run_perf_stat(int argc, const char **argv)static void print_running (u64 run,u64 ena) {if (csv_output) { -fprintf (output,"%s%" PRIu64"%s%.2f" , +fprintf (stat_config.output,"%s%" PRIu64"%s%.2f" , csv_sep, run, csv_sep, ena ?100.0 * run / ena :100.0 ); }else if (run != ena) { -fprintf (output," (%.2f%%)" ,100.0 * run / ena); +fprintf (stat_config.output," (%.2f%%)" ,100.0 * run / ena); } }
@@ -563,9 +562,9 @@ static void print_noise_pct(double total, double avg)double pct =rel_stddev_stats (total, avg);if (csv_output) -fprintf (output,"%s%.2f%%" , csv_sep, pct); +fprintf (stat_config.output,"%s%.2f%%" , csv_sep, pct);else if (pct) -fprintf (output," ( +-%6.2f%% )" , pct); +fprintf (stat_config.output," ( +-%6.2f%% )" , pct); }static void print_noise (struct perf_evsel *evsel,double avg)
@@ -583,7 +582,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) {switch (stat_config.aggr_mode) {case AGGR_CORE : - fprintf(output, "S%d-C%*d%s%*d%s", + fprintf(stat_config.output, "S%d-C%*d%s%*d%s", cpu_map__id_to_socket(id), csv_output ? 0 : -8, cpu_map__id_to_cpu(id),
@@ -593,7 +592,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep);break ;case AGGR_SOCKET : - fprintf(output, "S%*d%s%*d%s", + fprintf(stat_config.output, "S%*d%s%*d%s", csv_output ? 0 : -5, id, csv_sep,
@@ -602,12 +601,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep);break ;case AGGR_NONE : -fprintf (output,"CPU%*d%s" , +fprintf (stat_config.output,"CPU%*d%s" , csv_output ?0 :-4 ,perf_evsel__cpus (evsel)->map[id], csv_sep);break ;case AGGR_THREAD : - fprintf(output, "%*s-%*d%s", + fprintf(stat_config.output, "%*s-%*d%s", csv_output ? 0 : 16, thread_map__comm(evsel->threads, id), csv_output ? 0 : -8,
@@ -622,6 +621,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)static void nsec_printout (int id,int nr,struct perf_evsel *evsel,double avg) { +FILE *output = stat_config.output;double msecs = avg /1e6 ;const char *fmt_v, *fmt_n;char name[25 ];
@@ -658,6 +658,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)static void abs_printout (int id,int nr,struct perf_evsel *evsel,double avg) { +FILE *output = stat_config.output;double sc = evsel->scale;const char *fmt;int cpu =cpu_map__id_to_cpu (id);
@@ -697,6 +698,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)static void print_aggr (char *prefix) { +FILE *output = stat_config.output;struct perf_evsel *counter;int cpu, cpu2, s, s2, id, nr;double uval;
@@ -765,6 +767,7 @@ static void print_aggr(char *prefix)static void print_aggr_thread (struct perf_evsel *counter,char *prefix) { +FILE *output = stat_config.output;int nthreads =thread_map__nr (counter->threads);int ncpus =cpu_map__nr (counter->cpus);int cpu, thread;
@@ -803,6 +806,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;double avg =avg_stats (&ps->res_stats[0 ]);int scaled = counter->counts->scaled;
@@ -854,6 +858,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)*/ static void print_counter (struct perf_evsel *counter,char *prefix) { +FILE *output = stat_config.output;u64 ena, run, val;double uval;int cpu;
@@ -908,6 +913,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)static void print_interval (char *prefix,struct timespec *ts) { +FILE *output = stat_config.output;static int num_print_interval;sprintf (prefix,"%6lu.%09lu%s" , ts->tv_sec, ts->tv_nsec, csv_sep);
@@ -938,6 +944,7 @@ static void print_interval(char *prefix, struct timespec *ts)static void print_header (int argc,const char **argv) { +FILE *output = stat_config.output;int i;fflush (stdout);
@@ -967,6 +974,8 @@ static void print_header(int argc, const char **argv)static void print_footer (void ) { +FILE *output = stat_config.output; +if (!null_run)fprintf (output,"\n" ); fprintf(output, " %17.9f seconds time elapsed",
@@ -1013,7 +1022,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)if (!interval && !csv_output)print_footer (); -fflush (output); +fflush (stat_config.output); }static volatile int signr =-1 ;
@@ -1322,6 +1331,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) };int status = -EINVAL , run_idx;const char *mode; +FILE *output = stderr;setlocale (LC_ALL ,"" );
@@ -1332,7 +1342,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) argc =parse_options (argc, argv, options, stat_usage,PARSE_OPT_STOP_AT_NON_OPTION ); - output = stderr;if (output_name &&strcmp (output_name,"-" )) output =NULL ;
@@ -1369,6 +1378,8 @@ 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" ))
tools/perf/util/stat.h +1 -0
@@ -53,6 +53,7 @@ struct perf_counts {struct perf_stat_config {enum aggr_mode aggr_mode;bool scale; +FILE *output; }; static inline struct perf_counts_values*
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Move 'output' into struct perf_stat_config
perf stat: Move 'output' into struct perf_stat_config
Commit-ID: 5821522e9484a8b503f89aa546085900b99589e9 Gitweb: http://git.kernel.org/tip/5821522e9484a8b503f89aa546085900b99589e9 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:24 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 6 Aug 2015 16:02:51 -0300
perf stat: Move 'output' into struct perf_stat_config
Moving 'output' into struct perf_stat_config. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 35 +++++++++++++++++++++++------------ tools/perf/util/stat.h | 1 + 2 files changed, 24 insertions(+), 12 deletions(-)
tools/perf/builtin-stat.c +23 -12
@@ -110,7 +110,6 @@ static int big_num_opt = -1;static const char *csv_sep =NULL ;static bool csv_output = false;static bool group = false; -static FILE *output =NULL ;static const char *pre_cmd =NULL ;static const char *post_cmd =NULL ;static bool sync_run = false;
@@ -305,7 +304,7 @@ static int process_counter(struct perf_evsel *counter)update_stats (&ps->res_stats[i], count[i]);if (verbose) { -fprintf (output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" , +fprintf (stat_config.output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" ,perf_evsel__name (counter), count[0 ], count[1 ], count[2 ]); }
@@ -548,13 +547,13 @@ static int run_perf_stat(int argc, const char **argv)static void print_running (u64 run,u64 ena) {if (csv_output) { -fprintf (output,"%s%" PRIu64"%s%.2f" , +fprintf (stat_config.output,"%s%" PRIu64"%s%.2f" , csv_sep, run, csv_sep, ena ?100.0 * run / ena :100.0 ); }else if (run != ena) { -fprintf (output," (%.2f%%)" ,100.0 * run / ena); +fprintf (stat_config.output," (%.2f%%)" ,100.0 * run / ena); } }
@@ -563,9 +562,9 @@ static void print_noise_pct(double total, double avg)double pct =rel_stddev_stats (total, avg);if (csv_output) -fprintf (output,"%s%.2f%%" , csv_sep, pct); +fprintf (stat_config.output,"%s%.2f%%" , csv_sep, pct);else if (pct) -fprintf (output," ( +-%6.2f%% )" , pct); +fprintf (stat_config.output," ( +-%6.2f%% )" , pct); }static void print_noise (struct perf_evsel *evsel,double avg)
@@ -583,7 +582,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) {switch (stat_config.aggr_mode) {case AGGR_CORE : - fprintf(output, "S%d-C%*d%s%*d%s", + fprintf(stat_config.output, "S%d-C%*d%s%*d%s", cpu_map__id_to_socket(id), csv_output ? 0 : -8, cpu_map__id_to_cpu(id),
@@ -593,7 +592,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep);break ;case AGGR_SOCKET : - fprintf(output, "S%*d%s%*d%s", + fprintf(stat_config.output, "S%*d%s%*d%s", csv_output ? 0 : -5, id, csv_sep,
@@ -602,12 +601,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep);break ;case AGGR_NONE : -fprintf (output,"CPU%*d%s" , +fprintf (stat_config.output,"CPU%*d%s" , csv_output ?0 :-4 ,perf_evsel__cpus (evsel)->map[id], csv_sep);break ;case AGGR_THREAD : - fprintf(output, "%*s-%*d%s", + fprintf(stat_config.output, "%*s-%*d%s", csv_output ? 0 : 16, thread_map__comm(evsel->threads, id), csv_output ? 0 : -8,
@@ -622,6 +621,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)static void nsec_printout (int id,int nr,struct perf_evsel *evsel,double avg) { +FILE *output = stat_config.output;double msecs = avg /1e6 ;const char *fmt_v, *fmt_n;char name[25 ];
@@ -658,6 +658,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)static void abs_printout (int id,int nr,struct perf_evsel *evsel,double avg) { +FILE *output = stat_config.output;double sc = evsel->scale;const char *fmt;int cpu =cpu_map__id_to_cpu (id);
@@ -697,6 +698,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)static void print_aggr (char *prefix) { +FILE *output = stat_config.output;struct perf_evsel *counter;int cpu, cpu2, s, s2, id, nr;double uval;
@@ -765,6 +767,7 @@ static void print_aggr(char *prefix)static void print_aggr_thread (struct perf_evsel *counter,char *prefix) { +FILE *output = stat_config.output;int nthreads =thread_map__nr (counter->threads);int ncpus =cpu_map__nr (counter->cpus);int cpu, thread;
@@ -803,6 +806,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;double avg =avg_stats (&ps->res_stats[0 ]);int scaled = counter->counts->scaled;
@@ -854,6 +858,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)*/ static void print_counter (struct perf_evsel *counter,char *prefix) { +FILE *output = stat_config.output;u64 ena, run, val;double uval;int cpu;
@@ -908,6 +913,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)static void print_interval (char *prefix,struct timespec *ts) { +FILE *output = stat_config.output;static int num_print_interval;sprintf (prefix,"%6lu.%09lu%s" , ts->tv_sec, ts->tv_nsec, csv_sep);
@@ -938,6 +944,7 @@ static void print_interval(char *prefix, struct timespec *ts)static void print_header (int argc,const char **argv) { +FILE *output = stat_config.output;int i;fflush (stdout);
@@ -967,6 +974,8 @@ static void print_header(int argc, const char **argv)static void print_footer (void ) { +FILE *output = stat_config.output; +if (!null_run)fprintf (output,"\n" ); fprintf(output, " %17.9f seconds time elapsed",
@@ -1013,7 +1022,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)if (!interval && !csv_output)print_footer (); -fflush (output); +fflush (stat_config.output); }static volatile int signr =-1 ;
@@ -1322,6 +1331,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) };int status = -EINVAL , run_idx;const char *mode; +FILE *output = stderr;setlocale (LC_ALL ,"" );
@@ -1332,7 +1342,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) argc =parse_options (argc, argv, options, stat_usage,PARSE_OPT_STOP_AT_NON_OPTION ); - output = stderr;if (output_name &&strcmp (output_name,"-" )) output =NULL ;
@@ -1369,6 +1378,8 @@ 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" ))
tools/perf/util/stat.h +1 -0
@@ -53,6 +53,7 @@ struct perf_counts {struct perf_stat_config {enum aggr_mode aggr_mode;bool scale; +FILE *output; }; static inline struct perf_counts_values*
Jiri Olsa
reviewerPATCH 5/47 perf stat: Move interval into struct perf_stat_config
In reply to Jiri OlsaMoving interval into struct perf_stat_config. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 14 +++++++++----- tools/perf/util/stat.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-)
tools/perf/builtin-stat.c +9 -5
@@ -113,7 +113,6 @@ static bool group = false;static const char *pre_cmd =NULL ;static const char *post_cmd =NULL ;static bool sync_run = false; -static unsigned int interval =0 ;static unsigned int initial_delay =0 ;static unsigned int unit_width =4 ;/* strlen("unit") */ static bool forever = false;
@@ -404,6 +403,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *infstatic int __run_perf_stat (int argc,const char **argv) { +int interval = stat_config.interval;char msg[512 ];unsigned long long t0, t1;struct perf_evsel *counter;
@@ -646,7 +646,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (evsel->cgrp)fprintf (output,"%s%s" , csv_sep, evsel->cgrp->name); -if (csv_output || interval) +if (csv_output || stat_config.interval)return ;if (perf_evsel__match (evsel,SOFTWARE ,SW_TASK_CLOCK ))
@@ -689,7 +689,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (evsel->cgrp)fprintf (output,"%s%s" , csv_sep, evsel->cgrp->name); -if (csv_output || interval) +if (csv_output || stat_config.interval)return ; perf_stat__print_shadow_stats(output, evsel, avg, cpu,
@@ -990,6 +990,7 @@ static void print_footer(void)static void print_counters (struct timespec *ts,int argc,const char **argv) { +int interval = stat_config.interval;struct perf_evsel *counter;char buf[64 ], *prefix =NULL ;
@@ -1029,7 +1030,7 @@ static volatile int signr = -1;static void skip_signal (int signo) { -if ((child_pid ==-1 ) || interval) +if ((child_pid ==-1 ) || stat_config.interval) done =1 ; signr = signo;
@@ -1313,7 +1314,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "command to run prior to the measured command"),OPT_STRING (0 ,"post" , &post_cmd,"command" ,"command to run after to the measured command" ), -OPT_UINTEGER ('I' ,"interval-print" , &interval, +OPT_UINTEGER ('I' ,"interval-print" , &stat_config.interval,"print counts at regular interval in ms (>= 100)" ),OPT_SET_UINT (0 ,"per-socket" , &stat_config.aggr_mode, "aggregate counts per processor socket", AGGR_SOCKET),
@@ -1332,6 +1333,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)int status = -EINVAL , run_idx;const char *mode;FILE *output = stderr; +unsigned int interval;setlocale (LC_ALL ,"" );
@@ -1342,6 +1344,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) argc =parse_options (argc, argv, options, stat_usage,PARSE_OPT_STOP_AT_NON_OPTION ); + interval = stat_config.interval; +if (output_name &&strcmp (output_name,"-" )) output =NULL ;
tools/perf/util/stat.h +1 -0
@@ -54,6 +54,7 @@ struct perf_stat_config {enum aggr_mode aggr_mode;bool scale;FILE *output; +unsigned int interval; }; static inline struct perf_counts_values*
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Move 'interval' into struct perf_stat_config
perf stat: Move 'interval' into struct perf_stat_config
Commit-ID: ec0d3d1fd292adb80372193c03d859e9cbefd367 Gitweb: http://git.kernel.org/tip/ec0d3d1fd292adb80372193c03d859e9cbefd367 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:25 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 6 Aug 2015 16:03:04 -0300
perf stat: Move 'interval' into struct perf_stat_config
Moving 'interval' into struct perf_stat_config. The point is to centralize the base stat config so it could be used localy together with other stat routines in other parts of perf code.
--- tools/perf/builtin-stat.c | 14 +++++++++----- tools/perf/util/stat.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-)
tools/perf/builtin-stat.c +9 -5
@@ -113,7 +113,6 @@ static bool group = false;static const char *pre_cmd =NULL ;static const char *post_cmd =NULL ;static bool sync_run = false; -static unsigned int interval =0 ;static unsigned int initial_delay =0 ;static unsigned int unit_width =4 ;/* strlen("unit") */ static bool forever = false;
@@ -404,6 +403,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *infstatic int __run_perf_stat (int argc,const char **argv) { +int interval = stat_config.interval;char msg[512 ];unsigned long long t0, t1;struct perf_evsel *counter;
@@ -646,7 +646,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (evsel->cgrp)fprintf (output,"%s%s" , csv_sep, evsel->cgrp->name); -if (csv_output || interval) +if (csv_output || stat_config.interval)return ;if (perf_evsel__match (evsel,SOFTWARE ,SW_TASK_CLOCK ))
@@ -689,7 +689,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)if (evsel->cgrp)fprintf (output,"%s%s" , csv_sep, evsel->cgrp->name); -if (csv_output || interval) +if (csv_output || stat_config.interval)return ; perf_stat__print_shadow_stats(output, evsel, avg, cpu,
@@ -990,6 +990,7 @@ static void print_footer(void)static void print_counters (struct timespec *ts,int argc,const char **argv) { +int interval = stat_config.interval;struct perf_evsel *counter;char buf[64 ], *prefix =NULL ;
@@ -1029,7 +1030,7 @@ static volatile int signr = -1;static void skip_signal (int signo) { -if ((child_pid ==-1 ) || interval) +if ((child_pid ==-1 ) || stat_config.interval) done =1 ; signr = signo;
@@ -1313,7 +1314,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "command to run prior to the measured command"),OPT_STRING (0 ,"post" , &post_cmd,"command" ,"command to run after to the measured command" ), -OPT_UINTEGER ('I' ,"interval-print" , &interval, +OPT_UINTEGER ('I' ,"interval-print" , &stat_config.interval,"print counts at regular interval in ms (>= 100)" ),OPT_SET_UINT (0 ,"per-socket" , &stat_config.aggr_mode, "aggregate counts per processor socket", AGGR_SOCKET),
@@ -1332,6 +1333,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)int status = -EINVAL , run_idx;const char *mode;FILE *output = stderr; +unsigned int interval;setlocale (LC_ALL ,"" );
@@ -1342,6 +1344,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) argc =parse_options (argc, argv, options, stat_usage,PARSE_OPT_STOP_AT_NON_OPTION ); + interval = stat_config.interval; +if (output_name &&strcmp (output_name,"-" )) output =NULL ;
tools/perf/util/stat.h +1 -0
@@ -54,6 +54,7 @@ struct perf_stat_config {enum aggr_mode aggr_mode;bool scale;FILE *output; +unsigned int interval; }; static inline struct perf_counts_values*
Jiri Olsa
reviewerPATCH 6/47 perf stat: Pass struct perf_stat_config into process_counter
In reply to Jiri OlsaPassing struct perf_stat_config into process_counter, so we could make process_counter global and use it from other places.
--- tools/perf/builtin-stat.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)
tools/perf/builtin-stat.c +16 -13
@@ -216,7 +216,8 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) }static int -process_counter_values (struct perf_evsel *evsel,int cpu,int thread, +process_counter_values (struct perf_stat_config *config,struct perf_evsel *evsel, +int cpu,int thread,struct perf_counts_values *count) {struct perf_counts_values *aggr = &evsel->counts->aggr;
@@ -231,20 +232,20 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (skip) count = &zero; -switch (stat_config.aggr_mode) { +switch (config->aggr_mode) {case AGGR_THREAD :case AGGR_CORE :case AGGR_SOCKET :case AGGR_NONE :if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count); -perf_counts_values__scale (count, stat_config.scale,NULL ); -if (stat_config.aggr_mode ==AGGR_NONE ) +perf_counts_values__scale (count, config->scale,NULL ); +if (config->aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL : aggr->val += count->val; -if (stat_config.scale) { +if (config->scale) { aggr->ena += count->ena; aggr->run += count->run; }
@@ -255,7 +256,8 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,return 0 ; } -static int process_counter_maps (struct perf_evsel *counter) +static int process_counter_maps (struct perf_stat_config *config, +struct perf_evsel *counter) {int nthreads =thread_map__nr (counter->threads);int ncpus =perf_evsel__nr_cpus (counter);
@@ -266,7 +268,7 @@ static int process_counter_maps(struct perf_evsel *counter)for (thread =0 ; thread < nthreads; thread++) {for (cpu =0 ; cpu < ncpus; cpu++) { -if (process_counter_values (counter, cpu, thread, +if (process_counter_values (config, counter, cpu, thread,perf_counts (counter->counts, cpu, thread)))return -1 ; }
@@ -275,7 +277,8 @@ static int process_counter_maps(struct perf_evsel *counter)return 0 ; } -static int process_counter (struct perf_evsel *counter) +static int 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;
@@ -288,22 +291,22 @@ static int process_counter(struct perf_evsel *counter)if (counter->per_pkg)zero_per_pkg (counter); - ret =process_counter_maps (counter); + ret =process_counter_maps (&stat_config, counter);if (ret)return ret; -if (stat_config.aggr_mode !=AGGR_GLOBAL ) +if (config->aggr_mode !=AGGR_GLOBAL )return 0 ;if (!counter->snapshot)perf_evsel__compute_deltas (counter,-1 ,-1 , aggr); -perf_counts_values__scale (aggr, stat_config.scale, &counter->counts->scaled); +perf_counts_values__scale (aggr, config->scale, &counter->counts->scaled);for (i =0 ; i <3 ; i++)update_stats (&ps->res_stats[i], count[i]);if (verbose) { -fprintf (stat_config.output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" , +fprintf (config->output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" ,perf_evsel__name (counter), count[0 ], count[1 ], count[2 ]); }
@@ -352,7 +355,7 @@ static void read_counters(bool close_counters)if (read_counter (counter))pr_warning ("failed to read counter %s\n" , counter->name); -if (process_counter (counter)) +if (process_counter (&stat_config, counter))pr_warning ("failed to process counter %s\n" , counter->name);if (close_counters) {
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Pass 'struct perf_stat_config' into process_counter()
perf stat: Pass 'struct perf_stat_config' into process_counter()
Commit-ID: 5e5fe748bec771a810b1f44ec9c19e4b92685246 Gitweb: http://git.kernel.org/tip/5e5fe748bec771a810b1f44ec9c19e4b92685246 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:26 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 6 Aug 2015 16:07:36 -0300
perf stat: Pass 'struct perf_stat_config' into process_counter()
Passing 'struct perf_stat_config' into process_counter(), so that we can make process_counter() non static and use it from other places.
--- tools/perf/builtin-stat.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)
tools/perf/builtin-stat.c +16 -13
@@ -216,7 +216,8 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) }static int -process_counter_values (struct perf_evsel *evsel,int cpu,int thread, +process_counter_values (struct perf_stat_config *config,struct perf_evsel *evsel, +int cpu,int thread,struct perf_counts_values *count) {struct perf_counts_values *aggr = &evsel->counts->aggr;
@@ -231,20 +232,20 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,if (skip) count = &zero; -switch (stat_config.aggr_mode) { +switch (config->aggr_mode) {case AGGR_THREAD :case AGGR_CORE :case AGGR_SOCKET :case AGGR_NONE :if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count); -perf_counts_values__scale (count, stat_config.scale,NULL ); -if (stat_config.aggr_mode ==AGGR_NONE ) +perf_counts_values__scale (count, config->scale,NULL ); +if (config->aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;case AGGR_GLOBAL : aggr->val += count->val; -if (stat_config.scale) { +if (config->scale) { aggr->ena += count->ena; aggr->run += count->run; }
@@ -255,7 +256,8 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,return 0 ; } -static int process_counter_maps (struct perf_evsel *counter) +static int process_counter_maps (struct perf_stat_config *config, +struct perf_evsel *counter) {int nthreads =thread_map__nr (counter->threads);int ncpus =perf_evsel__nr_cpus (counter);
@@ -266,7 +268,7 @@ static int process_counter_maps(struct perf_evsel *counter)for (thread =0 ; thread < nthreads; thread++) {for (cpu =0 ; cpu < ncpus; cpu++) { -if (process_counter_values (counter, cpu, thread, +if (process_counter_values (config, counter, cpu, thread,perf_counts (counter->counts, cpu, thread)))return -1 ; }
@@ -275,7 +277,8 @@ static int process_counter_maps(struct perf_evsel *counter)return 0 ; } -static int process_counter (struct perf_evsel *counter) +static int 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;
@@ -288,22 +291,22 @@ static int process_counter(struct perf_evsel *counter)if (counter->per_pkg)zero_per_pkg (counter); - ret =process_counter_maps (counter); + ret =process_counter_maps (&stat_config, counter);if (ret)return ret; -if (stat_config.aggr_mode !=AGGR_GLOBAL ) +if (config->aggr_mode !=AGGR_GLOBAL )return 0 ;if (!counter->snapshot)perf_evsel__compute_deltas (counter,-1 ,-1 , aggr); -perf_counts_values__scale (aggr, stat_config.scale, &counter->counts->scaled); +perf_counts_values__scale (aggr, config->scale, &counter->counts->scaled);for (i =0 ; i <3 ; i++)update_stats (&ps->res_stats[i], count[i]);if (verbose) { -fprintf (stat_config.output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" , +fprintf (config->output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" ,perf_evsel__name (counter), count[0 ], count[1 ], count[2 ]); }
@@ -352,7 +355,7 @@ static void read_counters(bool close_counters)if (read_counter (counter))pr_warning ("failed to read counter %s\n" , counter->name); -if (process_counter (counter)) +if (process_counter (&stat_config, counter))pr_warning ("failed to process counter %s\n" , counter->name);if (close_counters) {
Jiri Olsa
reviewerPATCH 7/47 perf stat: Move counter processing code into stat object
In reply to Jiri OlsaMoving counter processing code into stat object
as perf_stat__process_counter.
--- tools/perf/builtin-stat.c | 141 +--------------------------------------------- tools/perf/util/stat.c | 139 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 3 + 3 files changed, 143 insertions(+), 140 deletions(-)
tools/perf/builtin-stat.c +1 -140
@@ -179,145 +179,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)return 0 ; } -static void zero_per_pkg (struct perf_evsel *counter) -{ -if (counter->per_pkg_mask) -memset (counter->per_pkg_mask,0 ,MAX_NR_CPUS ); -} - -static int check_per_pkg (struct perf_evsel *counter,int cpu,bool *skip) -{ -unsigned long *mask = counter->per_pkg_mask; -struct cpu_map *cpus =perf_evsel__cpus (counter); -int s; - - *skip = false; - -if (!counter->per_pkg) -return 0 ; - -if (cpu_map__empty (cpus)) -return 0 ; - -if (!mask) { - mask =zalloc (MAX_NR_CPUS ); -if (!mask) -return -ENOMEM ; - - counter->per_pkg_mask = mask; - } - - s =cpu_map__get_socket (cpus, cpu); -if (s <0 ) -return -1 ; - - *skip =test_and_set_bit (s, mask) ==1 ; -return 0 ; -} - -static int -process_counter_values (struct perf_stat_config *config,struct perf_evsel *evsel, -int cpu,int thread, -struct perf_counts_values *count) -{ -struct perf_counts_values *aggr = &evsel->counts->aggr; -static struct perf_counts_values zero; -bool skip = false; - -if (check_per_pkg (evsel, cpu, &skip)) { -pr_err ("failed to read per-pkg counter\n" ); -return -1 ; - } - -if (skip) - count = &zero; - -switch (config->aggr_mode) { -case AGGR_THREAD : -case AGGR_CORE : -case AGGR_SOCKET : -case AGGR_NONE : -if (!evsel->snapshot) -perf_evsel__compute_deltas (evsel, cpu, thread, count); -perf_counts_values__scale (count, config->scale,NULL ); -if (config->aggr_mode ==AGGR_NONE ) -perf_stat__update_shadow_stats (evsel, count->values, cpu); -break ; -case AGGR_GLOBAL : - aggr->val += count->val; -if (config->scale) { - aggr->ena += count->ena; - aggr->run += count->run; - } -default : -break ; - } - -return 0 ; -} - -static int process_counter_maps (struct perf_stat_config *config, -struct perf_evsel *counter) -{ -int nthreads =thread_map__nr (counter->threads); -int ncpus =perf_evsel__nr_cpus (counter); -int cpu, thread; - -if (counter->system_wide) - nthreads =1 ; - -for (thread =0 ; thread < nthreads; thread++) { -for (cpu =0 ; cpu < ncpus; cpu++) { -if (process_counter_values (config, counter, cpu, thread, -perf_counts (counter->counts, cpu, thread))) -return -1 ; - } - } - -return 0 ; -} - -static int 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; -u64 *count = counter->counts->aggr.values; -int i, ret; - - aggr->val = aggr->ena = aggr->run =0 ; -init_stats (ps->res_stats); - -if (counter->per_pkg) -zero_per_pkg (counter); - - ret =process_counter_maps (&stat_config, counter); -if (ret) -return ret; - -if (config->aggr_mode !=AGGR_GLOBAL ) -return 0 ; - -if (!counter->snapshot) -perf_evsel__compute_deltas (counter,-1 ,-1 , aggr); -perf_counts_values__scale (aggr, config->scale, &counter->counts->scaled); - -for (i =0 ; i <3 ; i++) -update_stats (&ps->res_stats[i], count[i]); - -if (verbose) { -fprintf (config->output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" , -perf_evsel__name (counter), count[0 ], count[1 ], count[2 ]); - } - -/* -* Save the full runtime - to allow normalization during printout: -*/ -perf_stat__update_shadow_stats (counter, count,0 ); - -return 0 ; -} -/* * Read out the results of a single counter: * do not aggregate counts across CPUs in system-wide mode
@@ -355,7 +216,7 @@ static void read_counters(bool close_counters)if (read_counter (counter))pr_warning ("failed to read counter %s\n" , counter->name); -if (process_counter (&stat_config, counter)) +if (perf_stat_process_counter (&stat_config, counter))pr_warning ("failed to process counter %s\n" , counter->name);if (close_counters) {
tools/perf/util/stat.c +139 -0
142 lines not on this page · raw message
tools/perf/util/stat.h +3 -0
@@ -116,4 +116,7 @@ int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw);int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw);void perf_evlist__free_stats (struct perf_evlist *evlist);void perf_evlist__reset_stats (struct perf_evlist *evlist); + +int perf_stat_process_counter (struct perf_stat_config *config, +struct perf_evsel *counter);#endif
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Move counter processing code into stat object
perf stat: Move counter processing code into stat object
Commit-ID: f80010eb230b94e8d9cf5bf83373a097fb5b2dcc Gitweb: http://git.kernel.org/tip/f80010eb230b94e8d9cf5bf83373a097fb5b2dcc Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:27 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 6 Aug 2015 16:08:16 -0300
perf stat: Move counter processing code into stat object
Moving counter processing code into stat object as perf_stat__process_counter.
--- tools/perf/builtin-stat.c | 141 +--------------------------------------------- tools/perf/util/stat.c | 139 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 3 + 3 files changed, 143 insertions(+), 140 deletions(-)
tools/perf/builtin-stat.c +1 -140
@@ -179,145 +179,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)return 0 ; } -static void zero_per_pkg (struct perf_evsel *counter) -{ -if (counter->per_pkg_mask) -memset (counter->per_pkg_mask,0 ,MAX_NR_CPUS ); -} - -static int check_per_pkg (struct perf_evsel *counter,int cpu,bool *skip) -{ -unsigned long *mask = counter->per_pkg_mask; -struct cpu_map *cpus =perf_evsel__cpus (counter); -int s; - - *skip = false; - -if (!counter->per_pkg) -return 0 ; - -if (cpu_map__empty (cpus)) -return 0 ; - -if (!mask) { - mask =zalloc (MAX_NR_CPUS ); -if (!mask) -return -ENOMEM ; - - counter->per_pkg_mask = mask; - } - - s =cpu_map__get_socket (cpus, cpu); -if (s <0 ) -return -1 ; - - *skip =test_and_set_bit (s, mask) ==1 ; -return 0 ; -} - -static int -process_counter_values (struct perf_stat_config *config,struct perf_evsel *evsel, -int cpu,int thread, -struct perf_counts_values *count) -{ -struct perf_counts_values *aggr = &evsel->counts->aggr; -static struct perf_counts_values zero; -bool skip = false; - -if (check_per_pkg (evsel, cpu, &skip)) { -pr_err ("failed to read per-pkg counter\n" ); -return -1 ; - } - -if (skip) - count = &zero; - -switch (config->aggr_mode) { -case AGGR_THREAD : -case AGGR_CORE : -case AGGR_SOCKET : -case AGGR_NONE : -if (!evsel->snapshot) -perf_evsel__compute_deltas (evsel, cpu, thread, count); -perf_counts_values__scale (count, config->scale,NULL ); -if (config->aggr_mode ==AGGR_NONE ) -perf_stat__update_shadow_stats (evsel, count->values, cpu); -break ; -case AGGR_GLOBAL : - aggr->val += count->val; -if (config->scale) { - aggr->ena += count->ena; - aggr->run += count->run; - } -default : -break ; - } - -return 0 ; -} - -static int process_counter_maps (struct perf_stat_config *config, -struct perf_evsel *counter) -{ -int nthreads =thread_map__nr (counter->threads); -int ncpus =perf_evsel__nr_cpus (counter); -int cpu, thread; - -if (counter->system_wide) - nthreads =1 ; - -for (thread =0 ; thread < nthreads; thread++) { -for (cpu =0 ; cpu < ncpus; cpu++) { -if (process_counter_values (config, counter, cpu, thread, -perf_counts (counter->counts, cpu, thread))) -return -1 ; - } - } - -return 0 ; -} - -static int 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; -u64 *count = counter->counts->aggr.values; -int i, ret; - - aggr->val = aggr->ena = aggr->run =0 ; -init_stats (ps->res_stats); - -if (counter->per_pkg) -zero_per_pkg (counter); - - ret =process_counter_maps (&stat_config, counter); -if (ret) -return ret; - -if (config->aggr_mode !=AGGR_GLOBAL ) -return 0 ; - -if (!counter->snapshot) -perf_evsel__compute_deltas (counter,-1 ,-1 , aggr); -perf_counts_values__scale (aggr, config->scale, &counter->counts->scaled); - -for (i =0 ; i <3 ; i++) -update_stats (&ps->res_stats[i], count[i]); - -if (verbose) { -fprintf (config->output,"%s: %" PRIu64" %" PRIu64" %" PRIu64"\n" , -perf_evsel__name (counter), count[0 ], count[1 ], count[2 ]); - } - -/* -* Save the full runtime - to allow normalization during printout: -*/ -perf_stat__update_shadow_stats (counter, count,0 ); - -return 0 ; -} -/* * Read out the results of a single counter: * do not aggregate counts across CPUs in system-wide mode
@@ -355,7 +216,7 @@ static void read_counters(bool close_counters)if (read_counter (counter))pr_warning ("failed to read counter %s\n" , counter->name); -if (process_counter (&stat_config, counter)) +if (perf_stat_process_counter (&stat_config, counter))pr_warning ("failed to process counter %s\n" , counter->name);if (close_counters) {
tools/perf/util/stat.c +139 -0
142 lines not on this page · raw message
tools/perf/util/stat.h +3 -0
@@ -116,4 +116,7 @@ int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw);int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw);void perf_evlist__free_stats (struct perf_evlist *evlist);void perf_evlist__reset_stats (struct perf_evlist *evlist); + +int perf_stat_process_counter (struct perf_stat_config *config, +struct perf_evsel *counter);#endif
Jiri Olsa
reviewerPATCH 8/47 perf tools: Use bool instead of target argument in perf_evlist__propagate_maps
In reply to Jiri OlsaWe need only bool info wether user defined her own set of cpus. Switching target argument to bool so it could be used from places without target object defined in following patches.
--- tools/perf/util/evlist.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/util/evlist.c +4 -4
@@ -1102,7 +1102,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, }static int perf_evlist__propagate_maps (struct perf_evlist *evlist, -struct target *target) +bool has_user_cpus) {struct perf_evsel *evsel;
@@ -1111,10 +1111,10 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,* We already have cpus for evsel (via PMU sysfs) so * keep it, if there's no target cpu list defined. */ -if (evsel->cpus && target->cpu_list) +if (evsel->cpus && has_user_cpus)cpu_map__put (evsel->cpus); -if (!evsel->cpus || target->cpu_list) +if (!evsel->cpus || has_user_cpus) evsel->cpus =cpu_map__get (evlist->cpus); evsel->threads =thread_map__get (evlist->threads);
@@ -1142,7 +1142,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return perf_evlist__propagate_maps (evlist, target); +return perf_evlist__propagate_maps (evlist, !!target->cpu_list); out_delete_threads:thread_map__put (evlist->threads);
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf evlist: Use bool instead of target argument in propagate_maps()
perf evlist: Use bool instead of target argument in propagate_maps()
Commit-ID: 52361ff093c807464f5a32a587a370b360bd399a Gitweb: http://git.kernel.org/tip/52361ff093c807464f5a32a587a370b360bd399a Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:28 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 21 Jul 2015 14:34:07 -0300
perf evlist: Use bool instead of target argument in propagate_maps()
We need only bool info wether user defined her own set of cpus.
Switching target argument to bool so it could be used from places without target object defined in following patches.
--- tools/perf/util/evlist.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/util/evlist.c +4 -4
@@ -1102,7 +1102,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, }static int perf_evlist__propagate_maps (struct perf_evlist *evlist, -struct target *target) +bool has_user_cpus) {struct perf_evsel *evsel;
@@ -1111,10 +1111,10 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,* We already have cpus for evsel (via PMU sysfs) so * keep it, if there's no target cpu list defined. */ -if (evsel->cpus && target->cpu_list) +if (evsel->cpus && has_user_cpus)cpu_map__put (evsel->cpus); -if (!evsel->cpus || target->cpu_list) +if (!evsel->cpus || has_user_cpus) evsel->cpus =cpu_map__get (evlist->cpus); evsel->threads =thread_map__get (evlist->threads);
@@ -1142,7 +1142,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return perf_evlist__propagate_maps (evlist, target); +return perf_evlist__propagate_maps (evlist, !!target->cpu_list); out_delete_threads:thread_map__put (evlist->threads);
Jiri Olsa
reviewerPATCH 9/47 perf tools: Tolerate NULL maps in perf_evlist__propagate_maps
In reply to Jiri OlsaTolerating NULL maps in perf_evlist__propagate_maps, so we dont need to pass evlist with both cpus and threads maps defined.
--- tools/perf/util/evlist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +2 -1
@@ -1119,7 +1119,8 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist, evsel->threads =thread_map__get (evlist->threads); -if (!evsel->cpus || !evsel->threads) +if ((evlist->cpus && !evsel->cpus) || + (evlist->threads && !evsel->threads))return -ENOMEM ; }
Signature · 1 line
2.4.3
Re: [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps
Em Tue, Jul 21, 2015 at 02:31:29PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
Tolerating NULL maps in
perf_evlist__propagate_maps, so we dont need to pass evlist with both cpus and threads maps defined.
Applied
Quoted 22 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/evlist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)tools/perf/util/evlist.c +2
-1@@ -1119,7 +1119,8 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist, evsel->threads =thread_map__get (evlist->threads); -if (!evsel->cpus || !evsel->threads) +if ((evlist->cpus && !evsel->cpus) || + (evlist->threads && !evsel->threads))return -ENOMEM ; }Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf evlist: Tolerate NULL maps in propagate_maps
In reply to Jiri Olsaperf evlist: Tolerate NULL maps in propagate_maps
Commit-ID: 0e5ffb317d7f861c309b0ab679ed2f59e9f72adf Gitweb: http://git.kernel.org/tip/0e5ffb317d7f861c309b0ab679ed2f59e9f72adf Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:29 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 21 Jul 2015 14:34:07 -0300
perf evlist: Tolerate NULL maps in propagate_maps
Tolerating NULL maps in perf_evlist__propagate_maps, so we dont need to pass evlist with both cpus and threads maps defined.
--- tools/perf/util/evlist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +2 -1
@@ -1119,7 +1119,8 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist, evsel->threads =thread_map__get (evlist->threads); -if (!evsel->cpus || !evsel->threads) +if ((evlist->cpus && !evsel->cpus) || + (evlist->threads && !evsel->threads))return -ENOMEM ; }
Jiri Olsa
reviewerPATCH 10/47 perf tools: Force perf_evlist__set_maps to propagate maps through events
In reply to Jiri OlsaForcing perf_evlist__set_maps to propagate maps through events, so cpu/thread maps get set within evlist.
--- tools/perf/util/evlist.c | 17 +++++++++++++++++ tools/perf/util/evlist.h | 11 +++-------- 2 files changed, 20 insertions(+), 8 deletions(-)
tools/perf/util/evlist.c +17 -0
@@ -1151,6 +1151,23 @@ out_delete_threads:return -1 ; } +int perf_evlist__set_maps (struct perf_evlist *evlist, +struct cpu_map *cpus, +struct thread_map *threads) +{ +if (evlist->cpus) +cpu_map__put (evlist->cpus); + + evlist->cpus = cpus; + +if (evlist->threads) +thread_map__put (evlist->threads); + + evlist->threads = threads; + +return perf_evlist__propagate_maps (evlist, false); +} +int perf_evlist__apply_filters (struct perf_evlist *evlist,struct perf_evsel **err_evsel) {struct perf_evsel *evsel;
tools/perf/util/evlist.h +3 -8
@@ -152,14 +152,9 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,void perf_evlist__set_selected (struct perf_evlist *evlist,struct perf_evsel *evsel); -static inline void perf_evlist__set_maps (struct perf_evlist *evlist, -struct cpu_map *cpus, -struct thread_map *threads) -{ - evlist->cpus = cpus; - evlist->threads = threads; -} - +int perf_evlist__set_maps (struct perf_evlist *evlist, +struct cpu_map *cpus, +struct thread_map *threads);int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target);int perf_evlist__apply_filters (struct perf_evlist *evlist,struct perf_evsel **err_evsel);
Signature · 1 line
2.4.3
Re: [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events
Em Tue, Jul 21, 2015 at 02:31:30PM +0200, Jiri Olsa escreveu:
Quoted 2 lines
Forcing
perf_evlist__set_mapsto propagate maps through events, so cpu/thread maps get set within evlist.
Applied
Quoted 59 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/evlist.c | 17 +++++++++++++++++ tools/perf/util/evlist.h | 11 +++-------- 2 files changed, 20 insertions(+), 8 deletions(-)tools/perf/util/evlist.c +17
-0@@ -1151,6 +1151,23 @@ out_delete_threads:return -1 ; } +int perf_evlist__set_maps (struct perf_evlist *evlist, +struct cpu_map *cpus, +struct thread_map *threads) +{ +if (evlist->cpus) +cpu_map__put (evlist->cpus); + + evlist->cpus = cpus; + +if (evlist->threads) +thread_map__put (evlist->threads); + + evlist->threads = threads; + +return perf_evlist__propagate_maps (evlist, false); +} +int perf_evlist__apply_filters (struct perf_evlist *evlist,struct perf_evsel **err_evsel) {struct perf_evsel *evsel;tools/perf/util/evlist.h +3
-8@@ -152,14 +152,9 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,void perf_evlist__set_selected (struct perf_evlist *evlist,struct perf_evsel *evsel); -static inline void perf_evlist__set_maps (struct perf_evlist *evlist, -struct cpu_map *cpus, -struct thread_map *threads) -{ - evlist->cpus = cpus; - evlist->threads = threads; -} - +int perf_evlist__set_maps (struct perf_evlist *evlist, +struct cpu_map *cpus, +struct thread_map *threads);int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target);int perf_evlist__apply_filters (struct perf_evlist *evlist,struct perf_evsel **err_evsel);Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf evlist: Force perf_evlist__set_maps to propagate maps through events
In reply to Jiri Olsaperf evlist: Force perf_evlist__set_maps to propagate maps through events
Commit-ID: 3de5cfb04435b82aa427d0285df996ba73d2f426 Gitweb: http://git.kernel.org/tip/3de5cfb04435b82aa427d0285df996ba73d2f426 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:30 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 21 Jul 2015 14:25:12 -0300
perf evlist: Force perf_evlist__set_maps to propagate maps through events
Forcing perf_evlist__set_maps to propagate maps through events, so cpu/thread maps get set within evlist.
--- tools/perf/util/evlist.c | 17 +++++++++++++++++ tools/perf/util/evlist.h | 11 +++-------- 2 files changed, 20 insertions(+), 8 deletions(-)
tools/perf/util/evlist.c +17 -0
@@ -1150,6 +1150,23 @@ out_delete_threads:return -1 ; } +int perf_evlist__set_maps (struct perf_evlist *evlist, +struct cpu_map *cpus, +struct thread_map *threads) +{ +if (evlist->cpus) +cpu_map__put (evlist->cpus); + + evlist->cpus = cpus; + +if (evlist->threads) +thread_map__put (evlist->threads); + + evlist->threads = threads; + +return perf_evlist__propagate_maps (evlist, false); +} +int perf_evlist__apply_filters (struct perf_evlist *evlist,struct perf_evsel **err_evsel) {struct perf_evsel *evsel;
tools/perf/util/evlist.h +3 -8
@@ -152,14 +152,9 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,void perf_evlist__set_selected (struct perf_evlist *evlist,struct perf_evsel *evsel); -static inline void perf_evlist__set_maps (struct perf_evlist *evlist, -struct cpu_map *cpus, -struct thread_map *threads) -{ - evlist->cpus = cpus; - evlist->threads = threads; -} - +int perf_evlist__set_maps (struct perf_evlist *evlist, +struct cpu_map *cpus, +struct thread_map *threads);int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target);int perf_evlist__apply_filters (struct perf_evlist *evlist,struct perf_evsel **err_evsel);
Jiri Olsa
reviewerPATCH 11/47 perf tools: Use argv style storage for cmdline feature data
In reply to Jiri OlsaWe will reuse argv style data in following change to display counters header showing monitored command line.
--- tools/perf/util/header.c | 35 ++++++++++++++++++++--------------- tools/perf/util/header.h | 1 + tools/perf/util/session.c | 1 + 3 files changed, 22 insertions(+), 15 deletions(-)
tools/perf/util/header.c +20 -15
@@ -923,17 +923,13 @@ static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, FILE *fp) {int nr, i; -char *str; nr = ph->env.nr_cmdline; - str = ph->env.cmdline;fprintf (fp,"# cmdline : " ); -for (i =0 ; i < nr; i++) { -fprintf (fp,"%s " , str); - str +=strlen (str) +1 ; - } +for (i =0 ; i < nr; i++) +fprintf (fp,"%s " , ph->env.cmdline_argv[i]);fputc ('\n' , fp); }
@@ -1541,14 +1537,13 @@ process_event_desc(struct perf_file_section *section __maybe_unused,return 0 ; } -static int process_cmdline (struct perf_file_section *section__maybe_unused , +static int process_cmdline (struct perf_file_section *section,struct perf_header *ph,int fd,void *data__maybe_unused ) {ssize_t ret; -char *str; -u32 nr, i; -struct strbuf sb; +char *str, *cmdline =NULL , **argv =NULL ; +u32 nr, i, len =0 ; ret =readn (fd, &nr,sizeof (nr));if (ret !=sizeof (nr))
@@ -1558,22 +1553,32 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused, nr =bswap_32 (nr); ph->env.nr_cmdline = nr; -strbuf_init (&sb,128 ); + + cmdline =zalloc (section->size + nr +1 ); +if (!cmdline) +return -1 ; + + argv =zalloc (sizeof (char *) * (nr +1 )); +if (!argv) + goto error;for (i =0 ; i < nr; i++) { str =do_read_string (fd, ph);if (!str) goto error; -/* include a NULL character at the end */ -strbuf_add (&sb, str,strlen (str) +1 ); + argv[i] = cmdline + len; +memcpy (argv[i], str,strlen (str) +1 ); + len +=strlen (str) +1 ;free (str); } - ph->env.cmdline =strbuf_detach (&sb,NULL ); + ph->env.cmdline = cmdline; + ph->env.cmdline_argv = (const char **) argv;return 0 ; error: -strbuf_release (&sb); +free (argv); +free (cmdline);return -1 ; }
tools/perf/util/header.h +1 -0
@@ -84,6 +84,7 @@ struct perf_session_env {int nr_pmu_mappings;int nr_groups;char *cmdline; +const char **cmdline_argv;char *sibling_cores;char *sibling_threads;char *numa_nodes;
tools/perf/util/session.c +1 -0
@@ -180,6 +180,7 @@ static void perf_session_env__delete(struct perf_session_env *env)zfree (&env->cpuid);zfree (&env->cmdline); +zfree (&env->cmdline_argv);zfree (&env->sibling_cores);zfree (&env->sibling_threads);zfree (&env->numa_nodes);
Signature · 1 line
2.4.3
Re: [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data
Em Tue, Jul 21, 2015 at 02:31:31PM +0200, Jiri Olsa escreveu:
Quoted 2 lines
We will reuse argv style data in following change to display counters header showing monitored command line.
Applied
Quoted 114 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/header.c | 35 ++++++++++++++++++++--------------- tools/perf/util/header.h | 1 + tools/perf/util/session.c | 1 + 3 files changed, 22 insertions(+), 15 deletions(-)tools/perf/util/header.c +20
-15@@ -923,17 +923,13 @@ static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, FILE *fp) {int nr, i; -char *str; nr = ph->env.nr_cmdline; - str = ph->env.cmdline;fprintf (fp,"# cmdline : " ); -for (i =0 ; i < nr; i++) { -fprintf (fp,"%s " , str); - str +=strlen (str) +1 ; - } +for (i =0 ; i < nr; i++) +fprintf (fp,"%s " , ph->env.cmdline_argv[i]);fputc ('\n' , fp); }@@ -1541,14 +1537,13 @@ process_event_desc(struct perf_file_section *section __maybe_unused,return 0 ; } -static int process_cmdline (struct perf_file_section *section__maybe_unused , +static int process_cmdline (struct perf_file_section *section,struct perf_header *ph,int fd,void *data__maybe_unused ) {ssize_t ret; -char *str; -u32 nr, i; -struct strbuf sb; +char *str, *cmdline =NULL , **argv =NULL ; +u32 nr, i, len =0 ; ret =readn (fd, &nr,sizeof (nr));if (ret !=sizeof (nr))@@ -1558,22 +1553,32 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused, nr =bswap_32 (nr); ph->env.nr_cmdline = nr; -strbuf_init (&sb,128 ); + + cmdline =zalloc (section->size + nr +1 ); +if (!cmdline) +return -1 ; + + argv =zalloc (sizeof (char *) * (nr +1 )); +if (!argv) + goto error;for (i =0 ; i < nr; i++) { str =do_read_string (fd, ph);if (!str) goto error; -/* include a NULL character at the end */ -strbuf_add (&sb, str,strlen (str) +1 ); + argv[i] = cmdline + len; +memcpy (argv[i], str,strlen (str) +1 ); + len +=strlen (str) +1 ;free (str); } - ph->env.cmdline =strbuf_detach (&sb,NULL ); + ph->env.cmdline = cmdline; + ph->env.cmdline_argv = (const char **) argv;return 0 ; error: -strbuf_release (&sb); +free (argv); +free (cmdline);return -1 ; }tools/perf/util/header.h +1
-0@@ -84,6 +84,7 @@ struct perf_session_env {int nr_pmu_mappings;int nr_groups;char *cmdline; +const char **cmdline_argv;char *sibling_cores;char *sibling_threads;char *numa_nodes;tools/perf/util/session.c +1
-0@@ -180,6 +180,7 @@ static void perf_session_env__delete(struct perf_session_env *env)zfree (&env->cpuid);zfree (&env->cmdline); +zfree (&env->cmdline_argv);zfree (&env->sibling_cores);zfree (&env->sibling_threads);zfree (&env->numa_nodes);Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf header: Use argv style storage for cmdline feature data
In reply to Jiri Olsaperf header: Use argv style storage for cmdline feature data
Commit-ID: 768dd3f3a6af25730ed1eec458e47a3c481bc3e5 Gitweb: http://git.kernel.org/tip/768dd3f3a6af25730ed1eec458e47a3c481bc3e5 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 21 Jul 2015 14:31:31 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 21 Jul 2015 14:34:08 -0300
perf header: Use argv style storage for cmdline feature data
We will reuse argv style data in following change to display counters header showing monitored command line.
--- tools/perf/util/header.c | 35 ++++++++++++++++++++--------------- tools/perf/util/header.h | 1 + tools/perf/util/session.c | 1 + 3 files changed, 22 insertions(+), 15 deletions(-)
tools/perf/util/header.c +20 -15
@@ -923,17 +923,13 @@ static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, FILE *fp) {int nr, i; -char *str; nr = ph->env.nr_cmdline; - str = ph->env.cmdline;fprintf (fp,"# cmdline : " ); -for (i =0 ; i < nr; i++) { -fprintf (fp,"%s " , str); - str +=strlen (str) +1 ; - } +for (i =0 ; i < nr; i++) +fprintf (fp,"%s " , ph->env.cmdline_argv[i]);fputc ('\n' , fp); }
@@ -1541,14 +1537,13 @@ process_event_desc(struct perf_file_section *section __maybe_unused,return 0 ; } -static int process_cmdline (struct perf_file_section *section__maybe_unused , +static int process_cmdline (struct perf_file_section *section,struct perf_header *ph,int fd,void *data__maybe_unused ) {ssize_t ret; -char *str; -u32 nr, i; -struct strbuf sb; +char *str, *cmdline =NULL , **argv =NULL ; +u32 nr, i, len =0 ; ret =readn (fd, &nr,sizeof (nr));if (ret !=sizeof (nr))
@@ -1558,22 +1553,32 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused, nr =bswap_32 (nr); ph->env.nr_cmdline = nr; -strbuf_init (&sb,128 ); + + cmdline =zalloc (section->size + nr +1 ); +if (!cmdline) +return -1 ; + + argv =zalloc (sizeof (char *) * (nr +1 )); +if (!argv) + goto error;for (i =0 ; i < nr; i++) { str =do_read_string (fd, ph);if (!str) goto error; -/* include a NULL character at the end */ -strbuf_add (&sb, str,strlen (str) +1 ); + argv[i] = cmdline + len; +memcpy (argv[i], str,strlen (str) +1 ); + len +=strlen (str) +1 ;free (str); } - ph->env.cmdline =strbuf_detach (&sb,NULL ); + ph->env.cmdline = cmdline; + ph->env.cmdline_argv = (const char **) argv;return 0 ; error: -strbuf_release (&sb); +free (argv); +free (cmdline);return -1 ; }
tools/perf/util/header.h +1 -0
@@ -84,6 +84,7 @@ struct perf_session_env {int nr_pmu_mappings;int nr_groups;char *cmdline; +const char **cmdline_argv;char *sibling_cores;char *sibling_threads;char *numa_nodes;
tools/perf/util/session.c +1 -0
@@ -180,6 +180,7 @@ static void perf_session_env__delete(struct perf_session_env *env)zfree (&env->cpuid);zfree (&env->cmdline); +zfree (&env->cmdline_argv);zfree (&env->sibling_cores);zfree (&env->sibling_threads);zfree (&env->numa_nodes);
Jiri Olsa
reviewerPATCH 12/47 perf tools: Add thread_map event
In reply to Jiri OlsaAdding thread_map event to pass/store thread maps.
--- 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(-)
tools/perf/util/event.c +1 -0
@@ -35,6 +35,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)
tools/perf/util/event.h +13 -0
@@ -225,6 +225,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 };
@@ -348,6 +349,17 @@ struct itrace_start_event {u32 pid, 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;
@@ -369,6 +381,7 @@ union perf_event {struct auxtrace_error_event auxtrace_error;struct aux_event aux;struct itrace_start_event itrace_start; +struct thread_map_event thread_map; };void perf_event__print_totals (void );
tools/perf/util/session.c +26 -0
@@ -311,6 +311,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 )
@@ -359,6 +369,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);
@@ -641,6 +664,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, };
@@ -1163,6 +1187,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 ; }
tools/perf/util/tool.h +2 -1
@@ -54,7 +54,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;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 13/47 perf tools: Add thread_map event sythesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_thread_map2 function to sythesize struct thread_map.
--- tools/perf/tests/builtin-test.c | 4 ++++ 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, 74 insertions(+)
tools/perf/tests/builtin-test.c +4 -0
@@ -175,6 +175,10 @@ static struct test { .func = test__thread_map, }, { + .desc = "Test thread map synthesize", + .func = test__thread_map_synthesize, + }, + { .func = NULL, }, };
tools/perf/tests/tests.h +1 -0
@@ -62,6 +62,7 @@ int test__fdarray__filter(void);int test__fdarray__add (void );int test__kmod_path__parse (void );int test__thread_map (void ); +int test__thread_map_synthesize (void );#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/tests/thread-map.c +29 -0
@@ -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 ; +}
tools/perf/util/event.c +36 -0
@@ -698,6 +698,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;
tools/perf/util/event.h +4 -0
@@ -399,6 +399,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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 14/47 perf tools: Add thread_map__new_event function
In reply to Jiri OlsaIntroducing thread_map__new_event function to create struct thread_map object from thread_map event.
--- 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(+)
tools/perf/tests/thread-map.c +14 -0
@@ -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 ; }
tools/perf/util/thread_map.c +27 -0
@@ -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)
@@ -407,3 +408,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; +}
tools/perf/util/thread_map.h +3 -0
@@ -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);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 15/47 perf tools: Add cpu_map event
In reply to Jiri OlsaAdding cpu_map event to pass/store cpu maps.
--- 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(-)
tools/perf/util/event.c +1 -0
@@ -36,6 +36,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)
tools/perf/util/event.h +8 -0
@@ -226,6 +226,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 };
@@ -360,6 +361,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;
@@ -382,6 +389,7 @@ union perf_event {struct aux_event aux;struct itrace_start_event itrace_start;struct thread_map_event thread_map; +struct cpu_map_event cpu_map; };void perf_event__print_totals (void );
tools/perf/util/session.c +25 -0
@@ -321,6 +321,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 )
@@ -371,6 +380,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);
@@ -665,6 +687,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, };
@@ -1189,6 +1212,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 ; }
tools/perf/util/tool.h +2 -1
@@ -55,7 +55,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;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 16/47 perf tools: Add cpu_map event synthesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_cpu_map function to sythesize struct cpu_map.
--- 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
tools/perf/tests/Build +1 -0
@@ -32,6 +32,7 @@ perf-y += sample-parsing.o perf-y += parse-no-sample-id-all.o perf-y += kmod-path.o perf-y += thread-map.o +perf-y += cpumap.o perf-$(CONFIG_X86) += perf-time-to-tsc.o
tools/perf/tests/builtin-test.c +4 -0
@@ -179,6 +179,10 @@ static struct test { .func = test__thread_map_synthesize, }, { + .desc = "Test cpu map synthesize", + .func = test__cpu_map_synthesize, + }, + { .func = NULL, }, };
tools/perf/tests/cpumap.c new file +29 -0
@@ -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 ; +}
tools/perf/tests/tests.h +1 -0
@@ -63,6 +63,7 @@ int test__fdarray__add(void);int test__kmod_path__parse (void );int test__thread_map (void );int test__thread_map_synthesize (void ); +int test__cpu_map_synthesize (void );#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +28 -0
@@ -735,6 +735,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;
tools/perf/util/event.h +5 -0
@@ -396,6 +396,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,
@@ -411,6 +412,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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 17/47 perf tools: Add cpu_map__new_event function
In reply to Jiri OlsaIntroducing cpu_map__new_event function to create
struct cpu_map object from cpu_map event.
--- tools/perf/tests/cpumap.c | 10 ++++++++++ tools/perf/util/cpumap.c | 27 +++++++++++++++++++++++++++ tools/perf/util/cpumap.h | 3 +++ 3 files changed, 40 insertions(+)
tools/perf/tests/cpumap.c +10 -0
@@ -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 ; }
tools/perf/util/cpumap.c +27 -0
@@ -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;
tools/perf/util/cpumap.h +3 -0
@@ -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 (struct cpu_map *map,int idx);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 18/47 perf tools: Add stat config event
In reply to Jiri OlsaAdding stat config event to pass/store stat config data, so report tools (report/script) know how to interpret stat data.
--- 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(-)
tools/perf/util/event.c +1 -0
@@ -37,6 +37,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)
tools/perf/util/event.h +20 -0
@@ -227,6 +227,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 };
@@ -367,6 +368,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;
@@ -390,6 +409,7 @@ union perf_event {struct itrace_start_event itrace_start;struct thread_map_event thread_map;struct cpu_map_event cpu_map; +struct stat_config_event stat_config; };void perf_event__print_totals (void );
tools/perf/util/session.c +24 -0
@@ -330,6 +330,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 )
@@ -382,6 +391,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);
@@ -688,6 +709,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, };
@@ -1214,6 +1236,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 ; }
tools/perf/util/tool.h +2 -1
@@ -56,7 +56,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;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 19/47 perf tools: Add stat config event synthesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_stat_config function to sythesize 'struct perf_stat_config'.
Storing stat config in form of tag-value pairs in a believe it'll sort out future version issues.
--- 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 | 39 ++++++++++++++++++++++++++++++ tools/perf/util/event.h | 5 ++++ 6 files changed, 103 insertions(+) create mode 100644 tools/perf/tests/stat.c
tools/perf/tests/Build +1 -0
@@ -33,6 +33,7 @@ perf-y += parse-no-sample-id-all.o perf-y += kmod-path.o perf-y += thread-map.o perf-y += cpumap.o +perf-y += stat.o perf-$(CONFIG_X86) += perf-time-to-tsc.o
tools/perf/tests/builtin-test.c +4 -0
@@ -183,6 +183,10 @@ static struct test { .func = test__cpu_map_synthesize, }, { + .desc = "Test stat config synthesize", + .func = test__synthesize_stat_config, + }, + { .func = NULL, }, };
tools/perf/tests/stat.c new file +53 -0
53 lines not on this page · raw message
tools/perf/tests/tests.h +1 -0
@@ -64,6 +64,7 @@ int test__kmod_path__parse(void);int test__thread_map (void );int test__thread_map_synthesize (void );int test__cpu_map_synthesize (void ); +int test__synthesize_stat_config (void );#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +39 -0
@@ -10,6 +10,7 @@#include "thread.h" #include "thread_map.h" #include "symbol/kallsyms.h" +#include "asm/bug.h" static const char *perf_event__names[] = { [0 ] ="TOTAL" ,
@@ -764,6 +765,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;
tools/perf/util/event.h +5 -0
@@ -417,6 +417,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,
@@ -443,6 +444,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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 20/47 perf tools: Add stat config event read function
In reply to Jiri OlsaIntroducing perf_event__read_stat_config function to read struct perf_stat_config object data from stat config event.
--- tools/perf/tests/stat.c | 6 ++++++ tools/perf/util/event.c | 24 ++++++++++++++++++++++++ tools/perf/util/event.h | 2 ++ 3 files changed, 32 insertions(+)
tools/perf/tests/stat.c +6 -0
@@ -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 ; }
tools/perf/util/event.c +24 -0
@@ -803,6 +803,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;
tools/perf/util/event.h +2 -0
@@ -448,6 +448,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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 21/47 perf tools: Add stat event
In reply to Jiri OlsaAdding stat event to store 'struct perf_counter_values' for given event/cpu/thread.
--- 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(-)
tools/perf/util/event.c +1 -0
@@ -39,6 +39,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)
tools/perf/util/event.h +19 -0
@@ -228,6 +228,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 };
@@ -386,6 +387,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;
@@ -410,6 +428,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 );
tools/perf/util/session.c +25 -1
@@ -311,7 +311,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,
@@ -339,6 +338,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 )
@@ -393,6 +401,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);
@@ -710,6 +731,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, };
@@ -1238,6 +1260,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 ; }
tools/perf/util/tool.h +2 -1
@@ -57,7 +57,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;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 22/47 perf tools: Add stat event synthesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_stat function to
synthesize 'struct stat_event'.
--- tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/stat.c | 40 +++++++++++++++++++++++++++++++++++----- tools/perf/tests/tests.h | 1 + tools/perf/util/event.c | 22 ++++++++++++++++++++++ tools/perf/util/event.h | 7 ++++++- 5 files changed, 68 insertions(+), 6 deletions(-)
tools/perf/tests/builtin-test.c +4 -0
@@ -187,6 +187,10 @@ static struct test { .func = test__synthesize_stat_config, }, { + .desc = "Test stat synthesize", + .func = test__synthesize_stat, + }, + { .func = NULL, }, };
tools/perf/tests/stat.c +35 -5
@@ -18,10 +18,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 +53,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 ; }
tools/perf/tests/tests.h +1 -0
@@ -65,6 +65,7 @@ int test__thread_map(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(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +22 -0
@@ -804,6 +804,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) {
tools/perf/util/event.h +6 -1
@@ -437,6 +437,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,
@@ -469,7 +470,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);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 23/47 perf tools: Add stat event read function
In reply to Jiri OlsaIntroducing perf_event__process_stat_event function to process 'struct perf_stat' data from stat event.
--- tools/perf/util/stat.c | 23 +++++++++++++++++++++++ tools/perf/util/stat.h | 6 ++++++ 2 files changed, 29 insertions(+)
tools/perf/util/stat.c +23 -0
@@ -377,3 +377,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 ; +}
tools/perf/util/stat.h +6 -0
@@ -119,4 +119,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
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 24/47 perf tools: Add stat round event
In reply to Jiri OlsaAdding stat round event to be stored afer each stat interval round, so report tools (report/script) get notified and process interval data.
--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 7 +++++++ tools/perf/util/session.c | 20 ++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 30 insertions(+), 1 deletion(-)
tools/perf/util/event.c +1 -0
@@ -40,6 +40,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)
tools/perf/util/event.h +7 -0
@@ -229,6 +229,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 };
@@ -404,6 +405,11 @@ struct stat_event { }; }; +struct stat_round_event { +struct perf_event_header header; +u64 time; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -429,6 +435,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 );
tools/perf/util/session.c +20 -0
@@ -347,6 +347,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 )
@@ -403,6 +412,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,12 @@ 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.time =bswap_64 (event->stat_round.time); +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);
@@ -732,6 +749,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, };
@@ -1262,6 +1280,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 ; }
tools/perf/util/tool.h +2 -1
@@ -58,7 +58,8 @@ struct perf_tool { thread_map, cpu_map, stat_config, - stat; + stat, + stat_round;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 25/47 perf tools: Add stat round event synthesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_stat_round function to synthesize 'struct stat_round_event'.
--- tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/stat.c | 19 +++++++++++++++++++ tools/perf/tests/tests.h | 2 ++ tools/perf/util/event.c | 16 ++++++++++++++++ tools/perf/util/event.h | 4 ++++ 5 files changed, 45 insertions(+)
tools/perf/tests/builtin-test.c +4 -0
@@ -191,6 +191,10 @@ static struct test { .func = test__synthesize_stat, }, { + .desc = "Test stat round synthesize", + .func = test__synthesize_stat_round, + }, + { .func = NULL, }, };
tools/perf/tests/stat.c +19 -0
@@ -87,3 +87,22 @@ 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 ); +return 0 ; +} + +int test__synthesize_stat_round (void ) +{ +TEST_ASSERT_VAL ("failed to synthesize stat_config" , + !perf_event__synthesize_stat_round (NULL ,0xdeadbeef , process_stat_round_event,NULL )); + +return 0 ; +}
tools/perf/tests/tests.h +2 -0
@@ -66,6 +66,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(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +16 -0
@@ -827,6 +827,22 @@ 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, +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; + +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) {
tools/perf/util/event.h +4 -0
@@ -482,6 +482,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, +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);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 26/47 perf tools: Introduce stat feature
In reply to Jiri OlsaIntroducing 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.
--- tools/perf/builtin-record.c | 2 ++ tools/perf/util/header.c | 14 ++++++++++++++ tools/perf/util/header.h | 1 + 3 files changed, 17 insertions(+)
tools/perf/builtin-record.c +2 -0
@@ -449,6 +449,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;
tools/perf/util/header.c +14 -0
@@ -883,6 +883,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) {
@@ -1166,6 +1173,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) {
@@ -1899,6 +1912,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 {
tools/perf/util/header.h +1 -0
@@ -31,6 +31,7 @@ enum {HEADER_PMU_MAPPINGS ,HEADER_GROUP_DESC ,HEADER_AUXTRACE , +HEADER_STAT ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 27/47 perf tools: Move id_offset out of struct perf_evsel union
In reply to Jiri OlsaBecause following stat patches use id_offset together with priv pointer.
--- tools/perf/util/evsel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/evsel.h +1 -1
@@ -59,9 +59,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;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 28/47 perf stat record: Add record command
In reply to Jiri OlsaAdd 'perf stat record' command support. It creates simple (header only) perf.data file ATM.
--- tools/perf/Documentation/perf-stat.txt | 12 ++++++ tools/perf/builtin-stat.c | 74 +++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-stat.txt +12 -0
@@ -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=::
@@ -158,6 +161,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 --------
tools/perf/builtin-stat.c +72 -2
116 lines not on this page · raw message
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 29/47 perf stat record: Initialize record features
In reply to Jiri OlsaDisabling all non stat related features.
--- tools/perf/builtin-stat.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
tools/perf/builtin-stat.c +15 -0
@@ -1150,6 +1150,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;
@@ -1172,6 +1185,8 @@ static int __cmd_record(int argc, const char **argv)if (stat_record.file.is_pipe)return -EINVAL ; +init_features (session); + session->evlist = evsel_list; stat_record.session = session; stat_record.enabled = true;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 30/47 perf stat record: Synthesize stat record data
In reply to Jiri OlsaSynthesizing needed stat record data for report/script:
- cpu/thread maps
- stat config
--- tools/perf/builtin-stat.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
tools/perf/builtin-stat.c +48 -0
@@ -190,6 +190,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 (&stat_record.file, event, event->header.size) <0 ) { +pr_err ("failed to write perf data, error: %m\n" ); +return -1 ; + } + + stat_record.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
@@ -276,6 +290,36 @@ 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_stat_config (NULL , &stat_config, + process_synthesized_event,NULL ); +if (err <0 ) { +pr_err ("Couldn't synthesize config.\n" ); +return 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; + } + +return 0 ; +} +static int __run_perf_stat (int argc,const char **argv) {int interval = stat_config.interval;
@@ -356,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; }/*
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 31/47 perf stat record: Store events IDs in perf data file
In reply to Jiri OlsaStore event IDs in evlist object so it get stored
into perf.data file.
--- 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(-)
tools/perf/builtin-stat.c +35 -0
@@ -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)) {
tools/perf/util/evlist.c +3 -3
@@ -496,9 +496,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 */
tools/perf/util/evlist.h +3 -0
@@ -94,6 +94,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);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 32/47 perf stat record: Add pipe support for record command
In reply to Jiri OlsaAllowing storing stat record data into pipe, so report tools (report/script) could read data directly from record.
--- tools/perf/builtin-stat.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-)
tools/perf/builtin-stat.c +28 -11
@@ -290,7 +290,7 @@ 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;
@@ -301,6 +301,15 @@ static int perf_stat_synthesize_config(void)return err; } +if (is_pipe) { + err =perf_event__synthesize_attrs (NULL , stat_record.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 ? stat_record.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 (&stat_record.file); - err =perf_session__write_header (stat_record.session, evsel_list, - fd, false); +if (is_pipe) { + err =perf_header__write_pipe (perf_data_file__fd (&stat_record.file)); + }else { + err =perf_session__write_header (stat_record.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; }
@@ -961,6 +976,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 && stat_record.file.is_pipe) +return ; +if (interval)print_interval (prefix = buf, ts);else
@@ -1264,10 +1283,6 @@ static int __cmd_record(int argc, const char **argv)return -1 ; } -/* No pipe support ATM */ -if (stat_record.file.is_pipe) -return -EINVAL ; -init_features (session); session->evlist = evsel_list;
@@ -1534,8 +1549,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)if (STAT_RECORD ) {int fd =perf_data_file__fd (&stat_record.file); - stat_record.session->header.data_size += stat_record.bytes_written; -perf_session__write_header (stat_record.session, evsel_list, fd, true); +if (!stat_record.file.is_pipe) { + stat_record.session->header.data_size += stat_record.bytes_written; +perf_session__write_header (stat_record.session, evsel_list, fd, true); + }perf_session__delete (stat_record.session); }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 33/47 perf stat record: Write stat events on record
In reply to Jiri OlsaWriting stat events on 'perf stat record' at the time we read counter values from kernel.
--- tools/perf/builtin-stat.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
tools/perf/builtin-stat.c +19 -0
@@ -204,6 +204,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
@@ -227,6 +239,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 ; + } + } } }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 34/47 perf stat record: Write stat round events on record
In reply to Jiri OlsaWriting stat round events on 'perf stat record' for each interval round. In non interval mode we store round event after the last stat event.
--- tools/perf/builtin-stat.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
tools/perf/builtin-stat.c +17 -0
@@ -204,6 +204,13 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,return 0 ; } +static int write_stat_round_event (u64 time) +{ +return perf_event__synthesize_stat_round (NULL , time, + process_synthesized_event, +NULL ); +} +#define SID (e, x, y) xyarray__entry(e->sample_id, x, y) static int
@@ -279,6 +286,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)) +pr_err ("failed to write stat round event\n" ); + } +print_counters (&rs,0 ,NULL ); }
@@ -1568,6 +1580,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)if (STAT_RECORD ) {int fd =perf_data_file__fd (&stat_record.file); +if (!interval) { +if (write_stat_round_event (0 )) +pr_err ("failed to write stat round event\n" ); + } +if (!stat_record.file.is_pipe) { stat_record.session->header.data_size += stat_record.bytes_written;perf_session__write_header (stat_record.session, evsel_list, fd, true);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 35/47 perf stat report: Add report command
In reply to Jiri OlsaAdding 'perf stat report' command support. ATM it only processes attr events and display nothing.
--- tools/perf/Documentation/perf-stat.txt | 12 ++++++++ tools/perf/builtin-stat.c | 54 +++++++++++++++++++++++++++++++--- tools/perf/util/session.c | 3 ++ 3 files changed, 65 insertions(+), 4 deletions(-)
tools/perf/Documentation/perf-stat.txt +12 -0
@@ -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:
@@ -169,6 +173,14 @@ Stores stat data into perf data file. --output file:: Output file name. +STAT RECORD +----------- +Reads and reports stat data from perf data file. + +-i file:: +--input file:: +Input file name. + EXAMPLES --------
tools/perf/builtin-stat.c +50 -4
90 lines not on this page · raw message
tools/perf/util/session.c +3 -0
@@ -36,6 +36,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 ;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 36/47 perf stat report: Process cpu/threads maps
In reply to Jiri OlsaAdding processing of cpu/threads maps. Configuring session's evlist with these maps.
--- tools/perf/builtin-stat.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
tools/perf/builtin-stat.c +59 -0
@@ -142,6 +142,9 @@ static struct perf_stat_config stat_config = {struct perf_stat_cmd {struct perf_tool tool; +bool allocated; +struct cpu_map *cpus; +struct thread_map *threads; }; static inline void diff_timespec(struct timespec *r, struct timespec *a,
@@ -1328,6 +1331,60 @@ static int __cmd_record(int argc, const char **argv)return argc; } +static int set_maps (struct perf_stat_cmd *stat) +{ +if (!stat->cpus || !stat->threads) +return 0 ; + +if (WARN_ONCE (stat->allocated,"stats double allocation\n" )) +return -EINVAL ; + +if (perf_evlist__set_maps (evsel_list, stat->cpus, stat->threads) || +perf_evlist__alloc_stats (evsel_list, true)) +return -ENOMEM ; + + stat->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_cmd *stat = container_of(tool, struct perf_stat_cmd, 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_cmd *stat = container_of(tool, struct perf_stat_cmd, tool); + +if (stat->cpus) { +pr_warning ("Extra cpu map event, ignoring.\n" ); +return 0 ; + } + + stat->cpus =cpu_map__new_event (&event->cpu_map); +if (!stat->cpus) +return -ENOMEM ; + +return set_maps (stat); +} +static const char *const report_usage[] = {"perf stat report [<options>]" ,NULL ,
@@ -1346,6 +1403,8 @@ static int __cmd_report(int argc, const char **argv)struct perf_stat_cmd stat = { .tool = { .attr = perf_event__process_attr, + .thread_map = process_thread_map_event, + .cpu_map = process_cpu_map_event, }, };int ret;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 37/47 perf stat report: Process stat config event
In reply to Jiri OlsaAdding processing of stat config event and initialize stat_config object.
--- tools/perf/builtin-stat.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
tools/perf/builtin-stat.c +10 -0
@@ -1331,6 +1331,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_cmd *stat) {if (!stat->cpus || !stat->threads)
@@ -1403,6 +1412,7 @@ static int __cmd_report(int argc, const char **argv)struct perf_stat_cmd stat = { .tool = { .attr = perf_event__process_attr, + .stat_config = process_stat_config_event, .thread_map = process_thread_map_event, .cpu_map = process_cpu_map_event, },
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 38/47 perf stat report: Process stat and stat round events
In reply to Jiri OlsaAdding processing of stat and stat round events.
--- tools/perf/builtin-stat.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
tools/perf/builtin-stat.c +25 -0
@@ -1331,6 +1331,29 @@ 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 (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,
@@ -1412,6 +1435,8 @@ static int __cmd_report(int argc, const char **argv)struct perf_stat_cmd stat = { .tool = { .attr = perf_event__process_attr, + .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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 39/47 perf stat report: Move csv_sep initialization before report command
In reply to Jiri OlsaSo we have csv_sep properly initialized before
report command leg.
--- tools/perf/builtin-stat.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
tools/perf/builtin-stat.c +7 -7
@@ -1546,6 +1546,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 )
@@ -1593,13 +1600,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 */
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 40/47 perf script: Check output fields only for samples
In reply to Jiri OlsaThere's no need to check sampling output fields
for events without perf_event_attr::sample_type
field set.
--- tools/perf/builtin-script.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/builtin-script.c +4 -1
@@ -650,7 +650,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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 41/47 perf script: Process cpu/threads maps
In reply to Jiri OlsaAdding processing of cpu/threads maps. Configuring session's evlist with these maps.
--- tools/perf/builtin-script.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
tools/perf/builtin-script.c +65 -0
@@ -17,7 +17,10 @@#include "util/sort.h" #include "util/data.h" #include "util/auxtrace.h" +#include "util/cpumap.h" +#include "util/thread_map.h" #include <linux/bitmap.h> +#include "asm/bug.h" static char const *script_name;static char const *generate_script_lang;
@@ -623,6 +626,9 @@ struct perf_script {struct perf_session *session;bool show_task_events;bool show_mmap_events; +bool allocated; +struct cpu_map *cpus; +struct thread_map *threads; }; static int process_attr(struct perf_tool *tool, union perf_event *event,
@@ -1535,6 +1541,62 @@ static int have_cmd(int argc, const char **argv)return 0 ; } +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 ; + +if (perf_evlist__set_maps (evlist, script->cpus, script->threads) || +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;
@@ -1563,6 +1625,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, },
@@ -1892,6 +1956,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)
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 42/47 perf script: Process stat config event
In reply to Jiri OlsaAdding processing of stat config event and initialize stat_config object.
--- tools/perf/builtin-script.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
tools/perf/builtin-script.c +11 -0
@@ -19,6 +19,7 @@#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"
@@ -33,6 +34,7 @@ static bool system_wide;static bool print_flags;static const char *cpu_list; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); +static struct perf_stat_config stat_config;enum perf_output_field {PERF_OUTPUT_COMM =1U <<0 ,
@@ -1541,6 +1543,14 @@ static int have_cmd(int argc, const char **argv)return 0 ; } +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;
@@ -1625,6 +1635,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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 43/47 perf script: Add process_stat/process_stat_interval scripting interface
In reply to Jiri OlsaPython and perl scripting code will define those
callbacks and get stat data.
--- tools/perf/util/trace-event.h | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/trace-event.h +4 -0
@@ -63,6 +63,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;
@@ -73,6 +74,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); };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 44/47 perf script: Add stat default handlers
In reply to Jiri OlsaImplement struct scripting_ops::(process_stat|process_stat_interval) handlers - calling scripting handlers from stat events handlers.
--- tools/perf/builtin-script.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
tools/perf/builtin-script.c +31 -0
@@ -199,6 +199,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 );
@@ -533,6 +536,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 )
@@ -561,6 +572,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, };
@@ -1543,6 +1556,22 @@ static int have_cmd(int argc, const char **argv)return 0 ; } +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 )
@@ -1635,6 +1664,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,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 45/47 perf script: Display stat events by default
In reply to Jiri OlsaIf no script is specified for stat data, display
stat events in raw form.
--- tools/perf/builtin-script.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-)
tools/perf/builtin-script.c +33 -2
@@ -537,9 +537,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 ) { }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 46/47 perf script: Add python support for stat events
In reply to Jiri OlsaAdd support to get stat events data in perf python scripts.
--- .../util/scripting-engines/trace-event-python.c | 113 +++++++++++++++++++-- 1 file changed, 107 insertions(+), 6 deletions(-)
tools/perf/util/scripting-engines/trace-event-python.c +107 -6
@@ -41,6 +41,8 @@#include "../thread-stack.h" #include "../trace-event.h" #include "../machine.h" +#include "thread_map.h" +#include "cpumap.h" PyMODINIT_FUNC initperf_trace_context (void );
@@ -858,6 +860,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__" );
@@ -1200,10 +1299,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, };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH 47/47 perf script: Add stat-cpi.py script
In reply to Jiri Olsa--- tools/perf/scripts/python/stat-cpi.py | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tools/perf/scripts/python/stat-cpi.py
tools/perf/scripts/python/stat-cpi.py new file +74 -0
@@ -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)
Signature · 1 line
2.4.3
Quoted 7 lines · Jiri Olsa
hi,
sending RFC on another attempt for stat scripting.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
Quoted 8 lines
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 eventsBasically 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.
I suspect there is some overlap with Kan's patchkit to put uncore data into perf.data too.
The basic direction seems good just from reading the intro (haven't read the code so far). I've been thinking about doing something similar to do native topdown support in perf. This would require evaluating formulas which are depending on the CPU.
-Andi
Quoted 13 lines · Andi Kleen
Quoted 12 lines · Jiri Olsa
hi,
sending RFC on another attempt for stat scripting.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=2This 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
Quoted 6 lines
Quoted 3 lines
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.
I suspect there is some overlap with Kan's patchkit to put uncore data into perf.data too.
hum, haven't seen this, was it posted already?
jirka
Quoted 15 lines · Andi Kleen
Quoted 13 lines · Jiri Olsa
Quoted 12 lines
hi,
sending RFC on another attempt for stat scripting.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=2This 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
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
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.
I suspect there is some overlap with Kan's patchkit to put uncore data into perf.data too.
hum, haven't seen this, was it posted already?
Not yet.
But I think the proposal is different as yours.
It intends to regularly read (10-20ms interval) counter during perf sampling. So I modified the perf record, added a timer to read counter regularly, and wrote the delta results into perf.data.
We want to do that is because we can read memory bandwidth from uncore event during cpu PMU event is sampling. The sophisticated bandwidth analysis requires fine granularity.
We cannot use sample read, because we need stable interval.
We tried to run perf record and perf stat together by script. But the script way have various issue and complex to parses the output.
So I propose to change the perf record and regularly write the counter value into perf.data
I will send them to review soon.
Thanks,
Kan
Arnaldo Carvalho de Melo
maintainerEm Tue, Jul 21, 2015 at 02:31:20PM +0200, Jiri Olsa escreveu:
Quoted 11 lines
hi,
sending RFC on another attempt for stat scripting.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=2This 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
Applied the first 11, some in a previous pull req, the ones moving stuff to perf_stat_config now, but the 12nd fails, please check when I get these merged by Ingo.
Also do you intend to do some rework on this due to the conversation with Kan? The ones I merged are good anyway, merged.
Thanks,
- Arnaldo
Quoted 8 lines · Arnaldo Carvalho de Melo
Em Tue, Jul 21, 2015 at 02:31:20PM +0200, Jiri Olsa escreveu:
Quoted 7 lines
hi,
sending RFC on another attempt for stat scripting.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
Quoted 8 lines
Quoted 4 lines
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 eventsApplied the first 11, some in a previous pull req, the ones moving stuff to
perf_stat_confignow, but the 12nd fails, please check when I get these merged by Ingo.
thanks
Quoted 3 lines
Also do you intend to do some rework on this due to the conversation with Kan? The ones I merged are good anyway, merged.
Kan still did not send his code.. I'll send new version with review comments and with some enhancements soon
jirka
Arnaldo Carvalho de Melo
maintainerEm Fri, Aug 07, 2015 at 09:45:56AM +0200, Jiri Olsa escreveu:
Quoted 5 lines · Arnaldo Carvalho de Melo
Quoted 3 lines
Applied the first 11, some in a previous pull req, the ones moving stuff to
perf_stat_confignow, but the 12nd fails, please check when I get these merged by Ingo.
Quoted 7 lines
thanks
Quoted 2 lines
Also do you intend to do some rework on this due to the conversation with Kan? The ones I merged are good anyway, merged.
Kan still did not send his code.. I'll send new version with review comments and with some enhancements soon
Ok, this is all in tip.git now, BTW.
- Arnaldo