perf stat: Add scripting support
Jiri Olsa
reviewerv4 cover perf stat: Add scripting support
hi,
sending another version of stat scripting.
v4 changes:
- added attr update event for event's cpumask
- forbig aggregation on task workloads
- some minor reorders and changelog fixes
v3 changes:
- added attr update event to handle unit,scale,name for event it fixed the uncore_imc_1/cas_count_read/ record/report
- perf report -D now displays stat related events
- some minor and changelog fixes
v2 changes:
- rebased to latest Arnaldo's perf/core
- patches 1 to 11 already merged in
- added --per-core/--per-socket/-A options for perf stat report command to allow custom aggregation in stat report, please check new examples below
- couple changelogs changes
The initial attempt defined its own formula lang and allowed triggering user's script on the end of the stat command:
http://marc.info/?l=linux-kernel&m=136742146322273&w=2
This patchset abandons the idea of new formula language and rather adds support to:
- store stat data into perf.data file
- add python support to process stat events
Basically it allows to store stat data into perf.data and post process it with python scripts in a similar way we do for sampling data.
The stat data are stored in new stat, stat-round, stat-config user events.
stat - stored for each read syscall of the counter
stat round - stored for each interval or end of the command invocation stat config - stores all the config information needed to process data
so report tool could restore the same output as record
The python script can now define 'stat__<eventname>_<modifier>' functions to get stat events data and 'stat__interval' to get stat-round data.
See CPI script example in scripts/python/stat-cpi.py.
Also available in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/stat_script
thanks,
jirka
Examples:
- To record data for command stat workload:
$ perf stat record kill ...
Performance counter stats for 'kill':
0.372007 task-clock (msec) # 0.613 CPUs utilized
3 context-switches # 0.008 M/sec
0 cpu-migrations # 0.000 K/sec
62 page-faults # 0.167 M/sec
1,129,973 cycles # 3.038 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
813,313 instructions # 0.72 insns per cycle
166,161 branches # 446.661 M/sec
8,747 branch-misses # 5.26% of all branches 0.000607287 seconds time elapsed
- To report perf stat data:
$ perf stat report
Performance counter stats for '/home/jolsa/bin/perf stat record kill':
0.372007 task-clock (msec) # inf CPUs utilized
3 context-switches # 0.008 M/sec
0 cpu-migrations # 0.000 K/sec
62 page-faults # 0.167 M/sec
1,129,973 cycles # 3.038 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
813,313 instructions # 0.72 insns per cycle
166,161 branches # 446.661 M/sec
8,747 branch-misses # 5.26% of all branches 0.000000000 seconds time elapsed
- To store system-wide period stat data:
$ perf stat -e cycles:u,instructions:u -a -I 1000 record
# time counts unit events
1.000265471 462,311,482 cycles:u (100.00%)
1.000265471 590,037,440 instructions:u
2.000483453 722,532,336 cycles:u (100.00%)
2.000483453 848,678,197 instructions:u
3.000759876 75,990,880 cycles:u (100.00%)
3.000759876 86,187,813 instructions:u
^C 3.213960893 85,329,533 cycles:u (100.00%)
3.213960893 135,954,296 instructions:u - To report perf stat data:
$ perf stat report
# time counts unit events
1.000265471 462,311,482 cycles:u (100.00%)
1.000265471 590,037,440 instructions:u
2.000483453 722,532,336 cycles:u (100.00%)
2.000483453 848,678,197 instructions:u
3.000759876 75,990,880 cycles:u (100.00%)
3.000759876 86,187,813 instructions:u
3.213960893 85,329,533 cycles:u (100.00%)
3.213960893 135,954,296 instructions:u - To run stat-cpi.py script over perf.data:
$ perf script -s scripts/python/stat-cpi.py
1.000265: cpu -1, thread -1 -> cpi 0.783529 (462311482/590037440)
2.000483: cpu -1, thread -1 -> cpi 0.851362 (722532336/848678197)
3.000760: cpu -1, thread -1 -> cpi 0.881689 (75990880/86187813)
3.213961: cpu -1, thread -1 -> cpi 0.627634 (85329533/135954296)- To pipe data from stat to stat-cpi script:
$ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf script -s scripts/python/stat-cpi.py
1.000192: cpu 0, thread -1 -> cpi 0.739535 (23921908/32347236)
2.000376: cpu 0, thread -1 -> cpi 1.663482 (2519340/1514498)
3.000621: cpu 0, thread -1 -> cpi 1.396308 (16162767/11575362)
4.000700: cpu 0, thread -1 -> cpi 1.092246 (20077258/18381624)
5.000867: cpu 0, thread -1 -> cpi 0.473816 (45157586/95306156)
6.001034: cpu 0, thread -1 -> cpi 0.532792 (43701668/82023818)
7.001195: cpu 0, thread -1 -> cpi 1.122059 (29890042/26638561)- Raw script stat data output:
$ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf --no-pager script
CPU THREAD VAL ENA RUN TIME EVENT
0 -1 12302059 1000811347 1000810712 1000198821 cycles:u
0 -1 2565362 1000823218 1000823218 1000198821 instructions:u
0 -1 14453353 1000812704 1000812704 2000382283 cycles:u
0 -1 4600932 1000799342 1000799342 2000382283 instructions:u
0 -1 15245106 1000774425 1000774425 3000538255 cycles:u
0 -1 2624324 1000769310 1000769310 3000538255 instructions:u- To display different aggregation in report:
$ perf stat -e cycles -a -I 1000 record sleep 3
# time counts unit events
1.000223609 703,427,617 cycles
2.000443651 609,975,307 cycles
3.000569616 668,479,597 cycles
3.000735323 1,155,816 cycles $ perf stat report
# time counts unit events
1.000223609 703,427,617 cycles
2.000443651 609,975,307 cycles
3.000569616 668,479,597 cycles
3.000735323 1,155,816 cycles $ perf stat report --per-core
# time core cpus counts unit events
1.000223609 S0-C0 2 327,612,412 cycles
1.000223609 S0-C1 2 375,815,205 cycles
2.000443651 S0-C0 2 287,462,177 cycles
2.000443651 S0-C1 2 322,513,130 cycles
3.000569616 S0-C0 2 271,571,908 cycles
3.000569616 S0-C1 2 396,907,689 cycles
3.000735323 S0-C0 2 694,977 cycles
3.000735323 S0-C1 2 460,839 cycles $ perf stat report --per-socket
# time socket cpus counts unit events
1.000223609 S0 4 703,427,617 cycles
2.000443651 S0 4 609,975,307 cycles
3.000569616 S0 4 668,479,597 cycles
3.000735323 S0 4 1,155,816 cycles $ perf stat report -A
# time CPU counts unit events
1.000223609 CPU0 205,431,505 cycles
1.000223609 CPU1 122,180,907 cycles
1.000223609 CPU2 176,649,682 cycles
1.000223609 CPU3 199,165,523 cycles
2.000443651 CPU0 148,447,922 cycles
2.000443651 CPU1 139,014,255 cycles
2.000443651 CPU2 204,436,559 cycles
2.000443651 CPU3 118,076,571 cycles
3.000569616 CPU0 149,788,954 cycles
3.000569616 CPU1 121,782,954 cycles
3.000569616 CPU2 247,277,700 cycles
3.000569616 CPU3 149,629,989 cycles
3.000735323 CPU0 269,675 cycles
3.000735323 CPU1 425,302 cycles
3.000735323 CPU2 364,169 cycles
3.000735323 CPU3 96,670 cycles ---
Jiri Olsa (57):
perf tools: Add thread_map event
perf tools: Add thread_map event sythesize function
perf tools: Add thread_map__new_event function
perf tools: Add perf_event__fprintf_thread_map function perf tools: Add cpu_map event
perf tools: Add cpu_map event synthesize function
perf tools: Add cpu_map__empty_new function
perf tools: Add cpu_map__new_event function
perf tools: Add perf_event__fprintf_cpu_map function
perf tools: Add stat config event
perf tools: Add stat config event synthesize function
perf tools: Add stat config event read function
perf tools: Add stat event
perf tools: Add stat event synthesize function
perf tools: Add stat event read function
perf tools: Add stat round event
perf tools: Add stat round event synthesize function
perf tools: Add stat events fprintf functions
perf tools: Add attr_update event
perf tools: Add attr_update event unit type
perf tools: Add attr_update event scale type
perf tools: Add attr_update event name type
perf tools: Add attr_update event cpus type
perf tools: Add perf_event__fprintf_attr_update function perf report: Display newly added events in raw dump
perf tools: Introduce stat feature
perf tools: Move id_offset out of struct perf_evsel union perf stat: Rename perf_stat struct into perf_stat_evsel perf stat: Add AGGR_UNSET mode
perf stat record: Add record command
perf stat record: Initialize record features
perf stat record: Synthesize stat record data
perf stat record: Store events IDs in perf data file
perf stat record: Add pipe support for record command
perf stat record: Write stat events on record
perf stat record: Write stat round events on record
perf stat record: Do not allow record with multiple runs mode perf stat record: Synthesize attr update events
perf tools: Make cpu_map__build_map global
perf tools: Add data arg to cpu_map__build_map callback perf stat report: Cache aggregated map entries in extra cpumap perf stat report: Add report command
perf stat report: Process cpu/threads maps
perf stat report: Process stat config event
perf stat report: Add support to initialize aggr_map from file perf stat report: Process stat and stat round events
perf stat report: Process attr update events
perf stat report: Move csv_sep initialization before report command perf stat report: Allow to override aggr_mode
perf script: Check output fields only for samples
perf script: Process cpu/threads maps
perf script: Process stat config event
perf script: Add process_stat/process_stat_interval scripting interface perf script: Add stat default handlers
perf script: Display stat events by default
perf script: Add python support for stat events
perf script: Add stat-cpi.py script
tools/perf/Documentation/perf-stat.txt | 34 ++ tools/perf/builtin-record.c | 2 + tools/perf/builtin-script.c | 144 ++++- tools/perf/builtin-stat.c | 662 ++++++++++++++++++++- tools/perf/scripts/python/stat-cpi.py | 74 +++ tools/perf/tests/Build | 3 + tools/perf/tests/attr_update.c | 118 ++++ tools/perf/tests/builtin-test.c | 24 + tools/perf/tests/cpumap.c | 91 +++ tools/perf/tests/stat.c | 111 ++++ tools/perf/tests/tests.h | 7 + tools/perf/tests/thread-map.c | 43 ++ tools/perf/tests/topology.c | 4 +- tools/perf/util/cpumap.c | 76 ++- tools/perf/util/cpumap.h | 9 +- tools/perf/util/event.c | 308 ++++++++++ tools/perf/util/event.h | 151 ++++- tools/perf/util/evlist.c | 6 +- tools/perf/util/evlist.h | 3 + tools/perf/util/evsel.h | 2 +- tools/perf/util/header.c | 205 +++++++ tools/perf/util/header.h | 17 + .../util/scripting-engines/trace-event-python.c | 114 +++- tools/perf/util/session.c | 189 ++++++ tools/perf/util/stat.c | 75 ++- tools/perf/util/stat.h | 13 +- tools/perf/util/thread_map.c | 27 + tools/perf/util/thread_map.h | 3 + tools/perf/util/tool.h | 8 +- tools/perf/util/trace-event.h | 4 + 30 files changed, 2478 insertions(+), 49 deletions(-) create mode 100644 tools/perf/scripts/python/stat-cpi.py create mode 100644 tools/perf/tests/attr_update.c create mode 100644 tools/perf/tests/cpumap.c create mode 100644 tools/perf/tests/stat.c
Jiri Olsa
reviewerPATCH v4 1/57 perf tools: Add thread_map event
Adding thread_map event to pass/store thread maps
as data in pipe/perf.data.
Storing thread ID along with the standard comm[16] thread name string.
--- 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
@@ -37,6 +37,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO", [PERF_RECORD_AUXTRACE] = "AUXTRACE", [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", + [PERF_RECORD_THREAD_MAP] = "THREAD_MAP", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +13 -0
@@ -226,6 +226,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_AUXTRACE_INFO =70 ,PERF_RECORD_AUXTRACE =71 ,PERF_RECORD_AUXTRACE_ERROR =72 , +PERF_RECORD_THREAD_MAP =73 , PERF_RECORD_HEADER_MAX };
@@ -356,6 +357,17 @@ struct context_switch_event {u32 next_prev_tid; }; +struct thread_map_data_event { +u64 pid; +char comm[16 ]; +}; + +struct thread_map_event { +struct perf_event_header header; +u64 nr; +struct thread_map_data_event data[]; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -378,6 +390,7 @@ union perf_event {struct aux_event aux;struct itrace_start_event itrace_start;struct context_switch_event context_switch; +struct thread_map_event thread_map; };void perf_event__print_totals (void );
tools/perf/util/session.c +26 -0
@@ -296,6 +296,16 @@ int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,return 0 ; } + +static +int process_event_thread_map_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )
@@ -346,6 +356,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->auxtrace = process_event_auxtrace_stub;if (tool->auxtrace_error ==NULL ) tool->auxtrace_error = process_event_auxtrace_error_stub; +if (tool->thread_map ==NULL ) + tool->thread_map = process_event_thread_map_stub; }static void swap_sample_id_all (union perf_event *event,void *data)
@@ -616,6 +628,17 @@ static void perf_event__auxtrace_error_swap(union perf_event *event, event->auxtrace_error.ip =bswap_64 (event->auxtrace_error.ip); } +static void perf_event__thread_map_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ +unsigned i; + + event->thread_map.nr =bswap_64 (event->thread_map.nr); + +for (i =0 ; i < event->thread_map.nr; i++) + event->thread_map.data[i].pid =bswap_64 (event->thread_map.data[i].pid); +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);
@@ -643,6 +666,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, + [PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap, [PERF_RECORD_HEADER_MAX] = NULL, };
@@ -1179,6 +1203,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,case PERF_RECORD_AUXTRACE_ERROR :perf_session__auxtrace_error_inc (session, event);return tool->auxtrace_error (tool, event, session); +case PERF_RECORD_THREAD_MAP : +return tool->thread_map (tool, event, session);default :return -EINVAL ; }
tools/perf/util/tool.h +2 -1
@@ -55,7 +55,8 @@ struct perf_tool {event_op2 build_id, id_index, auxtrace_info, - auxtrace_error; + auxtrace_error, + thread_map;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 2/57 perf tools: Add thread_map event sythesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_thread_map2 function to synthesize struct thread_map.
The perf_event__synthesize_thread_map name is already taken for synthesizing complete threads data (comm/mmap/fork).
--- 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
@@ -166,6 +166,10 @@ static struct test generic_tests[] = { .func = test_session_topology, }, { + .desc = "Test thread map synthesize", + .func = test__thread_map_synthesize, + }, + { .func = NULL, }, };
tools/perf/tests/tests.h +1 -0
@@ -67,6 +67,7 @@ int test__kmod_path__parse(void);int test__thread_map (void );int test__llvm (void );int test_session_topology (void ); +int test__thread_map_synthesize (void );#if defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
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
@@ -700,6 +700,42 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,return err; } +int perf_event__synthesize_thread_map2 (struct perf_tool *tool, +struct thread_map *threads, +perf_event__handler_t process, +struct machine *machine) +{ +union perf_event *event; +int i, err, size; + + size =sizeof (event->thread_map); + size += threads->nr *sizeof (event->thread_map.data[0 ]); + + event =zalloc (size); +if (!event) +return -ENOMEM ; + + event->header.type =PERF_RECORD_THREAD_MAP ; + event->header.size = size; + event->thread_map.nr = threads->nr; + +for (i =0 ; i < threads->nr; i++) { +struct thread_map_data_event *data = &event->thread_map.data[i]; +char *comm =thread_map__comm (threads, i); + +if (!comm) + comm = (char *)"" ; + + data->pid =thread_map__pid (threads, i); +strncpy ((char *) &data->comm, comm,sizeof (data->comm)); + } + + err =process (tool, event,NULL , machine); + +free (event); +return err; +} +size_t perf_event__fprintf_comm (union perf_event *event,FILE *fp) {const char *s;
tools/perf/util/event.h +4 -0
@@ -408,6 +408,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,perf_event__handler_t process, struct machine *machine, bool mmap_data, unsigned int proc_map_timeout); +int perf_event__synthesize_thread_map2 (struct perf_tool *tool, +struct thread_map *threads, +perf_event__handler_t process, +struct machine *machine); int perf_event__synthesize_threads(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine, bool mmap_data,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 3/57 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)
@@ -408,3 +409,29 @@ void thread_map__read_comms(struct thread_map *threads)for (i =0 ; i < threads->nr; ++i)comm_init (threads, i); } + +static void thread_map__copy_event (struct thread_map *threads, +struct thread_map_event *event) +{ +unsigned i; + + threads->nr = (int ) event->nr; + +for (i =0 ; i < event->nr; i++) { +thread_map__set_pid (threads, i, (pid_t ) event->data[i].pid); + threads->map[i].comm =strndup (event->data[i].comm,16 ); + } + +atomic_set (&threads->refcnt,1 ); +} + +struct thread_map *thread_map__new_event (struct thread_map_event *event) +{ +struct thread_map *threads; + + threads =thread_map__alloc (event->nr); +if (threads) +thread_map__copy_event (threads, event); + +return threads; +}
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 v4 4/57 perf tools: Add perf_event__fprintf_thread_map function
In reply to Jiri OlsaTo display thread_map event for raw dump.
--- tools/perf/util/event.c | 16 ++++++++++++++++ tools/perf/util/event.h | 1 + 2 files changed, 17 insertions(+)
tools/perf/util/event.c +16 -0
@@ -820,6 +820,22 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) event->mmap2.filename); } +size_t perf_event__fprintf_thread_map (union perf_event *event,FILE *fp) +{ +struct thread_map *threads =thread_map__new_event (&event->thread_map); +size_t ret; + + ret =fprintf (fp," nr: " ); + +if (threads) + ret +=thread_map__fprintf (threads, fp); +else + ret +=fprintf (fp,"failed to get threads from event\n" ); + +thread_map__put (threads); +return ret; +} + int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample,
tools/perf/util/event.h +1 -0
@@ -516,6 +516,7 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);size_t perf_event__fprintf_aux (union perf_event *event,FILE *fp);size_t perf_event__fprintf_itrace_start (union perf_event *event,FILE *fp);size_t perf_event__fprintf_switch (union perf_event *event,FILE *fp); +size_t perf_event__fprintf_thread_map (union perf_event *event,FILE *fp);size_t perf_event__fprintf (union perf_event *event,FILE *fp); u64 kallsyms__get_function_start(const char *kallsyms_filename,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 5/57 perf tools: Add cpu_map event
In reply to Jiri OlsaAdding cpu_map event to pass/store cpu maps as data in pipe/perf.data.
We store maps in 2 formats:
- list of cpus
- mask of cpus
The format that takes less space is selected transparently in following patch.
The interface is made generic, so we could add cpumap event data into another event in following patches.
--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 28 ++++++++++++++++++++++++++ tools/perf/util/session.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 81 insertions(+), 1 deletion(-)
tools/perf/util/event.c +1 -0
@@ -38,6 +38,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_AUXTRACE] = "AUXTRACE", [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", [PERF_RECORD_THREAD_MAP] = "THREAD_MAP", + [PERF_RECORD_CPU_MAP] = "CPU_MAP", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +28 -0
@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_AUXTRACE =71 ,PERF_RECORD_AUXTRACE_ERROR =72 ,PERF_RECORD_THREAD_MAP =73 , +PERF_RECORD_CPU_MAP =74 , PERF_RECORD_HEADER_MAX };
@@ -271,6 +272,32 @@ struct events_stats {u32 nr_proc_map_timeout; }; +enum { +PERF_CPU_MAP__CPUS =0 , +PERF_CPU_MAP__MASK =1 , +}; + +struct cpu_map_data_cpus { +u64 nr; +u64 cpu[]; +}; + +struct cpu_map_data_mask { +u64 nr; +u64 long_size; +unsigned long mask[]; +}; + +struct cpu_map_data { +u64 type; +char data[]; +}; + +struct cpu_map_event { +struct perf_event_header header; +struct cpu_map_data data; +}; +struct attr_event {struct perf_event_header header;struct perf_event_attr attr;
@@ -391,6 +418,7 @@ union perf_event {struct itrace_start_event itrace_start;struct context_switch_event context_switch;struct thread_map_event thread_map; +struct cpu_map_event cpu_map; };void perf_event__print_totals (void );
tools/perf/util/session.c +50 -0
80 lines not on this page · raw message
tools/perf/util/tool.h +2 -1
@@ -56,7 +56,8 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, - thread_map; + thread_map, + cpu_map;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
2.4.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 05/57] perf tools: Add cpu_map event
Em Fri, Oct 16, 2015 at 12:40:40PM +0200, Jiri Olsa escreveu:
Quoted 7 lines
Adding
cpu_mapevent to pass/store cpu maps as data in pipe/perf.data.We store maps in 2 formats:
- list of cpus
- mask of cpus
Quoted 6 lines
The format that takes less space is selected transparently in following patch.
The interface is made generic, so we could add cpumap event data into another event in following patches.
Hey, perf_event_header.size is u16, so max is 65535, which with each cpu taking 8 bytes... We this we can't support > ~8190 CPUs with PERF_CPU_MAP__CPUS.
Do we really need to use u64 for each CPU entry?
- Arnaldo
Quoted 179 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 28 ++++++++++++++++++++++++++ tools/perf/util/session.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 81 insertions(+), 1 deletion(-)tools/perf/util/event.c +1
-0@@ -38,6 +38,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_AUXTRACE] = "AUXTRACE", [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", [PERF_RECORD_THREAD_MAP] = "THREAD_MAP", + [PERF_RECORD_CPU_MAP] = "CPU_MAP", };const char *perf_event__name (unsigned int id)tools/perf/util/event.h +28
-0@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_AUXTRACE =71 ,PERF_RECORD_AUXTRACE_ERROR =72 ,PERF_RECORD_THREAD_MAP =73 , +PERF_RECORD_CPU_MAP =74 , PERF_RECORD_HEADER_MAX };@@ -271,6 +272,32 @@ struct events_stats {u32 nr_proc_map_timeout; }; +enum { +PERF_CPU_MAP__CPUS =0 , +PERF_CPU_MAP__MASK =1 , +}; + +struct cpu_map_data_cpus { +u64 nr; +u64 cpu[]; +}; + +struct cpu_map_data_mask { +u64 nr; +u64 long_size; +unsigned long mask[]; +}; + +struct cpu_map_data { +u64 type; +char data[]; +}; + +struct cpu_map_event { +struct perf_event_header header; +struct cpu_map_data data; +}; +struct attr_event {struct perf_event_header header;struct perf_event_attr attr;@@ -391,6 +418,7 @@ union perf_event {struct itrace_start_event itrace_start;struct context_switch_event context_switch;struct thread_map_event thread_map; +struct cpu_map_event cpu_map; };void perf_event__print_totals (void );tools/perf/util/session.c +50
-0@@ -306,6 +306,15 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static +int process_event_cpu_map_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )@@ -358,6 +367,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->auxtrace_error = process_event_auxtrace_error_stub;if (tool->thread_map ==NULL ) tool->thread_map = process_event_thread_map_stub; +if (tool->cpu_map ==NULL ) + tool->cpu_map = process_event_cpu_map_stub; }static void swap_sample_id_all (union perf_event *event,void *data)@@ -639,6 +650,42 @@ 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 ) +{ +struct cpu_map_data *data = &event->cpu_map.data; +struct cpu_map_data_cpus *cpus; +struct cpu_map_data_mask *mask; +unsigned i; + + data->type =bswap_64 (data->type); + +switch (data->type) { +case PERF_CPU_MAP__CPUS : + cpus = (struct cpu_map_data_cpus *) data->data; + + cpus->nr =bswap_64 (cpus->nr); + +for (i =0 ; i < cpus->nr; i++) + cpus->cpu[i] =bswap_64 (cpus->cpu[i]); +break ; +case PERF_CPU_MAP__MASK : + mask = (struct cpu_map_data_mask *) data->data; + + mask->nr =bswap_64 (mask->nr); + mask->long_size =bswap_64 (mask->long_size); + +switch (mask->long_size) { +case 4 :mem_bswap_32 (&mask->mask, mask->nr);break ; +case 8 :mem_bswap_64 (&mask->mask, mask->nr);break ; +default : +pr_err ("cpu_map swap: unsupported long size\n" ); + } +default : +break ; + } +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);@@ -667,6 +714,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, [PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap, + [PERF_RECORD_CPU_MAP] = perf_event__cpu_map_swap, [PERF_RECORD_HEADER_MAX] = NULL, };@@ -1205,6 +1253,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@@ -56,7 +56,8 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, - thread_map; + thread_map, + cpu_map;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;Signature · 1 line
2.4.3
Re: [PATCH 05/57] perf tools: Add cpu_map event
Quoted 15 lines · Arnaldo Carvalho de Melo
Em Fri, Oct 16, 2015 at 12:40:40PM +0200, Jiri Olsa escreveu:
Quoted 7 lines
Adding
cpu_mapevent to pass/store cpu maps as data in pipe/perf.data.We store maps in 2 formats:
- list of cpus
- mask of cpusQuoted 6 lines
The format that takes less space is selected transparently in following patch.
The interface is made generic, so we could add cpumap event data into another event in following patches.
Quoted 5 lines
Hey, perf_event_header.size is u16, so max is 65535, which with each cpu taking 8 bytes... We this we can't support > ~8190 CPUs with
PERF_CPU_MAP__CPUS.Do we really need to use u64 for each CPU entry?
64 bits for cpu number should be ok for future ;-)
as I stated above there are 2 ways to save cpu map
- list od cpus
- mask of cpus
and the one taking less bytes is chosen.. but I agree 8 bytes for cpu number is little too much.. will change
jirka
Quoted 182 lines
- Arnaldo
Quoted 179 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 28 ++++++++++++++++++++++++++ tools/perf/util/session.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 81 insertions(+), 1 deletion(-)tools/perf/util/event.c +1
-0@@ -38,6 +38,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_AUXTRACE] = "AUXTRACE", [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", [PERF_RECORD_THREAD_MAP] = "THREAD_MAP", + [PERF_RECORD_CPU_MAP] = "CPU_MAP", };const char *perf_event__name (unsigned int id)tools/perf/util/event.h +28
-0@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_AUXTRACE =71 ,PERF_RECORD_AUXTRACE_ERROR =72 ,PERF_RECORD_THREAD_MAP =73 , +PERF_RECORD_CPU_MAP =74 , PERF_RECORD_HEADER_MAX };@@ -271,6 +272,32 @@ struct events_stats {u32 nr_proc_map_timeout; }; +enum { +PERF_CPU_MAP__CPUS =0 , +PERF_CPU_MAP__MASK =1 , +}; + +struct cpu_map_data_cpus { +u64 nr; +u64 cpu[]; +}; + +struct cpu_map_data_mask { +u64 nr; +u64 long_size; +unsigned long mask[]; +}; + +struct cpu_map_data { +u64 type; +char data[]; +}; + +struct cpu_map_event { +struct perf_event_header header; +struct cpu_map_data data; +}; +struct attr_event {struct perf_event_header header;struct perf_event_attr attr;@@ -391,6 +418,7 @@ union perf_event {struct itrace_start_event itrace_start;struct context_switch_event context_switch;struct thread_map_event thread_map; +struct cpu_map_event cpu_map; };void perf_event__print_totals (void );tools/perf/util/session.c +50
-0@@ -306,6 +306,15 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static +int process_event_cpu_map_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )@@ -358,6 +367,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->auxtrace_error = process_event_auxtrace_error_stub;if (tool->thread_map ==NULL ) tool->thread_map = process_event_thread_map_stub; +if (tool->cpu_map ==NULL ) + tool->cpu_map = process_event_cpu_map_stub; }static void swap_sample_id_all (union perf_event *event,void *data)@@ -639,6 +650,42 @@ 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 ) +{ +struct cpu_map_data *data = &event->cpu_map.data; +struct cpu_map_data_cpus *cpus; +struct cpu_map_data_mask *mask; +unsigned i; + + data->type =bswap_64 (data->type); + +switch (data->type) { +case PERF_CPU_MAP__CPUS : + cpus = (struct cpu_map_data_cpus *) data->data; + + cpus->nr =bswap_64 (cpus->nr); + +for (i =0 ; i < cpus->nr; i++) + cpus->cpu[i] =bswap_64 (cpus->cpu[i]); +break ; +case PERF_CPU_MAP__MASK : + mask = (struct cpu_map_data_mask *) data->data; + + mask->nr =bswap_64 (mask->nr); + mask->long_size =bswap_64 (mask->long_size); + +switch (mask->long_size) { +case 4 :mem_bswap_32 (&mask->mask, mask->nr);break ; +case 8 :mem_bswap_64 (&mask->mask, mask->nr);break ; +default : +pr_err ("cpu_map swap: unsupported long size\n" ); + } +default : +break ; + } +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);@@ -667,6 +714,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, [PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap, + [PERF_RECORD_CPU_MAP] = perf_event__cpu_map_swap, [PERF_RECORD_HEADER_MAX] = NULL, };@@ -1205,6 +1253,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@@ -56,7 +56,8 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, - thread_map; + thread_map, + cpu_map;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 6/57 perf tools: Add cpu_map event synthesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_cpu_map function to synthesize struct cpu_map.
Added generic interface:
cpu_map_data__alloc
cpu_map_data__synthesize
to make the cpu_map synthesizing usable for other events.
--- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++ tools/perf/tests/cpumap.c | 71 ++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/event.c | 131 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/event.h | 8 +++ 6 files changed, 216 insertions(+) create mode 100644 tools/perf/tests/cpumap.c
tools/perf/tests/Build +1 -0
@@ -33,6 +33,7 @@ perf-y += kmod-path.o perf-y += thread-map.o perf-y += llvm.o perf-y += topology.o +perf-y += cpumap.o ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
tools/perf/tests/builtin-test.c +4 -0
@@ -170,6 +170,10 @@ static struct test generic_tests[] = { .func = test__thread_map_synthesize, }, { + .desc = "Test cpu map synthesize", + .func = test__cpu_map_synthesize, + }, + { .func = NULL, }, };
tools/perf/tests/cpumap.c new file +71 -0
71 lines not on this page · raw message
tools/perf/tests/tests.h +1 -0
@@ -68,6 +68,7 @@ int test__thread_map(void);int test__llvm (void );int test_session_topology (void );int test__thread_map_synthesize (void ); +int test__cpu_map_synthesize (void );#if defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +131 -0
137 lines not on this page · raw message
tools/perf/util/event.h +8 -0
@@ -425,6 +425,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,
@@ -440,6 +441,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,
@@ -550,4 +555,7 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp);u64 kallsyms__get_function_start (const char *kallsyms_filename,const char *symbol_name); +void *cpu_map_data__alloc (struct cpu_map *map,size_t *size,u64 *type,int *max); +void cpu_map_data__synthesize (struct cpu_map_data *data,struct cpu_map *map, +u64 type,int max);#endif /* __PERF_RECORD_H */
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 7/57 perf tools: Add cpu_map__empty_new function
In reply to Jiri OlsaAdding cpu_map__empty_new interface to create empty cpumap with given size. The cpumap entries are initialized with -1.
It'll be used for caching cpu_map in following patches.
--- tools/perf/util/cpumap.c | 17 +++++++++++++++++ tools/perf/util/cpumap.h | 1 + 2 files changed, 18 insertions(+)
tools/perf/util/cpumap.c +17 -0
@@ -203,6 +203,23 @@ struct cpu_map *cpu_map__dummy_new(void)return cpus; } +struct cpu_map *cpu_map__empty_new (int nr) +{ +struct cpu_map *cpus =malloc (sizeof (*cpus) +sizeof (int ) * nr); + +if (cpus !=NULL ) { +int i; + + cpus->nr = nr; +for (i =0 ; i < nr; i++) + cpus->map[i] =-1 ; + +atomic_set (&cpus->refcnt,1 ); + } + +return cpus; +} +static void cpu_map__delete (struct cpu_map *map) {if (map) {
tools/perf/util/cpumap.h +1 -0
@@ -15,6 +15,7 @@ struct cpu_map { };struct cpu_map *cpu_map__new (const char *cpu_list); +struct cpu_map *cpu_map__empty_new (int nr);struct cpu_map *cpu_map__dummy_new (void );struct cpu_map *cpu_map__read (FILE *file);size_t cpu_map__fprintf (struct cpu_map *map,FILE *fp);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 8/57 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 | 28 ++++++++++++++++++++++++---- tools/perf/util/cpumap.c | 42 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/cpumap.h | 1 + 3 files changed, 67 insertions(+), 4 deletions(-)
tools/perf/tests/cpumap.c +24 -4
@@ -6,11 +6,12 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,struct perf_sample *sample__maybe_unused , struct machine *machine __maybe_unused) { - struct cpu_map_event *map = &event->cpu_map; + struct cpu_map_event *map_event = &event->cpu_map;struct cpu_map_data_mask *mask;struct cpu_map_data *data; +struct cpu_map *map; - data = &map->data; + data = &map_event->data;TEST_ASSERT_VAL ("wrong type" , data->type ==PERF_CPU_MAP__MASK );
@@ -23,6 +24,17 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,TEST_ASSERT_VAL ("wrong cpu" ,test_bit (4 , mask->mask));TEST_ASSERT_VAL ("wrong cpu" ,test_bit (5 , mask->mask));TEST_ASSERT_VAL ("wrong cpu" ,test_bit (6 , mask->mask)); + + map =cpu_map__new_data (data); +TEST_ASSERT_VAL ("wrong nr" , map->nr ==6 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[0 ] ==1 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[1 ] ==2 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[2 ] ==3 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[3 ] ==4 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[4 ] ==5 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[5 ] ==6 ); +TEST_ASSERT_VAL ("wrong refcnt" ,atomic_read (&map->refcnt) ==1 ); +cpu_map__put (map);return 0 ; }
@@ -31,11 +43,12 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,struct perf_sample *sample__maybe_unused , struct machine *machine __maybe_unused) { - struct cpu_map_event *map = &event->cpu_map; + struct cpu_map_event *map_event = &event->cpu_map;struct cpu_map_data_cpus *cpus;struct cpu_map_data *data; +struct cpu_map *map; - data = &map->data; + data = &map_event->data;TEST_ASSERT_VAL ("wrong type" , data->type ==PERF_CPU_MAP__CPUS );
@@ -44,6 +57,13 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,TEST_ASSERT_VAL ("wrong nr" , cpus->nr ==2 );TEST_ASSERT_VAL ("wrong cpu" , cpus->cpu[0 ] ==1 );TEST_ASSERT_VAL ("wrong cpu" , cpus->cpu[1 ] ==256 ); + + map =cpu_map__new_data (data); +TEST_ASSERT_VAL ("wrong nr" , map->nr ==2 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[0 ] ==1 ); +TEST_ASSERT_VAL ("wrong cpu" , map->map[1 ] ==256 ); +TEST_ASSERT_VAL ("wrong refcnt" ,atomic_read (&map->refcnt) ==1 ); +cpu_map__put (map);return 0 ; }
tools/perf/util/cpumap.c +42 -0
54 lines not on this page · raw message
tools/perf/util/cpumap.h +1 -0
@@ -17,6 +17,7 @@ struct cpu_map {struct cpu_map *cpu_map__new (const char *cpu_list);struct cpu_map *cpu_map__empty_new (int nr);struct cpu_map *cpu_map__dummy_new (void ); +struct cpu_map *cpu_map__new_data (struct cpu_map_data *data);struct cpu_map *cpu_map__read (FILE *file);size_t cpu_map__fprintf (struct cpu_map *map,FILE *fp);int cpu_map__get_socket_id (int cpu);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 9/57 perf tools: Add perf_event__fprintf_cpu_map function
In reply to Jiri OlsaTo display cpu_map event for raw dump.
--- tools/perf/util/event.c | 16 ++++++++++++++++ tools/perf/util/event.h | 1 + 2 files changed, 17 insertions(+)
tools/perf/util/event.c +16 -0
@@ -968,6 +968,22 @@ size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)return ret; } +size_t perf_event__fprintf_cpu_map (union perf_event *event,FILE *fp) +{ +struct cpu_map *cpus =cpu_map__new_data (&event->cpu_map.data); +size_t ret; + + ret =fprintf (fp," nr: " ); + +if (cpus) + ret +=cpu_map__fprintf (cpus, fp); +else + ret +=fprintf (fp,"failed to get cpumap from event\n" ); + +cpu_map__put (cpus); +return ret; +} + int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample,
tools/perf/util/event.h +1 -0
@@ -550,6 +550,7 @@ size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);size_t perf_event__fprintf_itrace_start (union perf_event *event,FILE *fp);size_t perf_event__fprintf_switch (union perf_event *event,FILE *fp);size_t perf_event__fprintf_thread_map (union perf_event *event,FILE *fp); +size_t perf_event__fprintf_cpu_map (union perf_event *event,FILE *fp);size_t perf_event__fprintf (union perf_event *event,FILE *fp); u64 kallsyms__get_function_start(const char *kallsyms_filename,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 10/57 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.
The config data are stored in 'tag|value' way to allow easy extension and backward compatibility.
--- 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
@@ -39,6 +39,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", [PERF_RECORD_THREAD_MAP] = "THREAD_MAP", [PERF_RECORD_CPU_MAP] = "CPU_MAP", + [PERF_RECORD_STAT_CONFIG] = "STAT_CONFIG", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +20 -0
@@ -228,6 +228,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_AUXTRACE_ERROR =72 ,PERF_RECORD_THREAD_MAP =73 ,PERF_RECORD_CPU_MAP =74 , +PERF_RECORD_STAT_CONFIG =75 , PERF_RECORD_HEADER_MAX };
@@ -395,6 +396,24 @@ struct thread_map_event {struct thread_map_data_event data[]; }; +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;
@@ -419,6 +438,7 @@ union perf_event {struct context_switch_event context_switch;struct thread_map_event thread_map;struct cpu_map_event cpu_map; +struct stat_config_event stat_config; };void perf_event__print_totals (void );
tools/perf/util/session.c +24 -0
@@ -315,6 +315,15 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static +int process_event_stat_config_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )
@@ -369,6 +378,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->thread_map = process_event_thread_map_stub;if (tool->cpu_map ==NULL ) tool->cpu_map = process_event_cpu_map_stub; +if (tool->stat_config ==NULL ) + tool->stat_config = process_event_stat_config_stub; }static void swap_sample_id_all (union perf_event *event,void *data)
@@ -686,6 +697,16 @@ static void perf_event__cpu_map_swap(union perf_event *event, } } +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);
@@ -715,6 +736,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, };
@@ -1255,6 +1277,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
@@ -57,7 +57,8 @@ struct perf_tool { auxtrace_info, auxtrace_error, thread_map, - cpu_map; + cpu_map, + stat_config;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 11/57 perf tools: Add stat config event synthesize function
In reply to Jiri OlsaIntroduce perf_event__synthesize_stat_config function to synthesize 'struct perf_stat_config'.
Storing stat config in form of tag-value pairs in a believe it'll sort out future version issues.
--- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/stat.c | 53 +++++++++++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/event.c | 40 +++++++++++++++++++++++++++++++ tools/perf/util/event.h | 5 ++++ 6 files changed, 104 insertions(+) create mode 100644 tools/perf/tests/stat.c
tools/perf/tests/Build +1 -0
@@ -34,6 +34,7 @@ perf-y += thread-map.o perf-y += llvm.o perf-y += topology.o perf-y += cpumap.o +perf-y += stat.o ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
tools/perf/tests/builtin-test.c +4 -0
@@ -174,6 +174,10 @@ static struct test generic_tests[] = { .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
@@ -69,6 +69,7 @@ int test__llvm(void);int test_session_topology (void );int test__thread_map_synthesize (void );int test__cpu_map_synthesize (void ); +int test__synthesize_stat_config (void );#if defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +40 -0
@@ -10,6 +10,8 @@#include "thread.h" #include "thread_map.h" #include "symbol/kallsyms.h" +#include "asm/bug.h" +#include "stat.h" static const char *perf_event__names[] = { [0 ] ="TOTAL" ,
@@ -869,6 +871,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
@@ -446,6 +446,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,
@@ -472,6 +473,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 v4 12/57 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
@@ -909,6 +909,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
@@ -477,6 +477,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 v4 13/57 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 | 25 +++++++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 47 insertions(+), 1 deletion(-)
tools/perf/util/event.c +1 -0
@@ -42,6 +42,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_THREAD_MAP] = "THREAD_MAP", [PERF_RECORD_CPU_MAP] = "CPU_MAP", [PERF_RECORD_STAT_CONFIG] = "STAT_CONFIG", + [PERF_RECORD_STAT] = "STAT", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +19 -0
@@ -229,6 +229,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_THREAD_MAP =73 ,PERF_RECORD_CPU_MAP =74 ,PERF_RECORD_STAT_CONFIG =75 , +PERF_RECORD_STAT =76 , PERF_RECORD_HEADER_MAX };
@@ -414,6 +415,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;
@@ -439,6 +457,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 -0
@@ -324,6 +324,15 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static int process_stat_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *perf_session +__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )
@@ -380,6 +389,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)
@@ -707,6 +718,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);
@@ -737,6 +759,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, };
@@ -1279,6 +1302,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
@@ -58,7 +58,8 @@ struct perf_tool { auxtrace_error, thread_map, cpu_map, - stat_config; + stat_config, + stat;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 14/57 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 | 41 ++++++++++++++++++++++++++++++++++++----- tools/perf/tests/tests.h | 1 + tools/perf/util/event.c | 22 ++++++++++++++++++++++ tools/perf/util/event.h | 7 ++++++- 5 files changed, 69 insertions(+), 6 deletions(-)
tools/perf/tests/builtin-test.c +4 -0
@@ -178,6 +178,10 @@ static struct test generic_tests[] = { .func = test__synthesize_stat_config, }, { + .desc = "Test stat synthesize", + .func = test__synthesize_stat, + }, + { .func = NULL, }, };
tools/perf/tests/stat.c +36 -5
59 lines not on this page · raw message
tools/perf/tests/tests.h +1 -0
@@ -70,6 +70,7 @@ int test_session_topology(void);int test__thread_map_synthesize (void );int test__cpu_map_synthesize (void );int test__synthesize_stat_config (void ); +int test__synthesize_stat (void );#if defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +22 -0
@@ -910,6 +910,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
@@ -466,6 +466,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,
@@ -498,7 +499,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 v4 15/57 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
@@ -340,3 +340,26 @@ int perf_stat_process_counter(struct perf_stat_config *config,return 0 ; } + +int perf_event__process_stat_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session) +{ +struct perf_counts_values count; +struct stat_event *stat = &event->stat; +struct perf_evsel *counter; + + count.val = stat->val; + count.ena = stat->ena; + count.run = stat->run; + + counter =perf_evlist__id2evsel (session->evlist, stat->id); +if (!counter) { +pr_err ("Failed to resolve counter for stat event.\n" ); +return -EINVAL ; + } + + *perf_counts (counter->counts, stat->cpu, stat->thread) = count; + counter->supported = true; +return 0 ; +}
tools/perf/util/stat.h +6 -0
@@ -89,4 +89,10 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist);int perf_stat_process_counter (struct perf_stat_config *config,struct perf_evsel *counter); +struct perf_tool ; +union perf_event ; +struct perf_session ; +int perf_event__process_stat_event (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session);#endif
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 16/57 perf tools: Add stat round event
In reply to Jiri OlsaAdding stat round event to be stored after 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 | 13 +++++++++++++ tools/perf/util/session.c | 21 +++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 37 insertions(+), 1 deletion(-)
tools/perf/util/event.c +1 -0
@@ -43,6 +43,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_CPU_MAP] = "CPU_MAP", [PERF_RECORD_STAT_CONFIG] = "STAT_CONFIG", [PERF_RECORD_STAT] = "STAT", + [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +13 -0
@@ -230,6 +230,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_CPU_MAP =74 ,PERF_RECORD_STAT_CONFIG =75 ,PERF_RECORD_STAT =76 , +PERF_RECORD_STAT_ROUND =77 , PERF_RECORD_HEADER_MAX };
@@ -432,6 +433,17 @@ struct stat_event { }; }; +enum { +PERF_STAT_ROUND_TYPE__INTERVAL =0 , +PERF_STAT_ROUND_TYPE__FINAL =1 , +}; + +struct stat_round_event { +struct perf_event_header header; +u64 type; +u64 time; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -458,6 +470,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 +21 -0
@@ -333,6 +333,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 )
@@ -391,6 +400,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)
@@ -729,6 +740,13 @@ static void perf_event__stat_swap(union perf_event *event, event->stat.run =bswap_64 (event->stat.run); } +static void perf_event__stat_round_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ + event->stat_round.type =bswap_64 (event->stat_round.type); + event->stat_round.time =bswap_64 (event->stat_round.time); +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);
@@ -760,6 +778,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, };
@@ -1304,6 +1323,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
@@ -59,7 +59,8 @@ struct perf_tool { thread_map, cpu_map, stat_config, - stat; + stat, + stat_round;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 17/57 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 | 21 +++++++++++++++++++++ tools/perf/tests/tests.h | 2 ++ tools/perf/util/event.c | 17 +++++++++++++++++ tools/perf/util/event.h | 4 ++++ 5 files changed, 48 insertions(+)
tools/perf/tests/builtin-test.c +4 -0
@@ -182,6 +182,10 @@ static struct test generic_tests[] = { .func = test__synthesize_stat, }, { + .desc = "Test stat round synthesize", + .func = test__synthesize_stat_round, + }, + { .func = NULL, }, };
tools/perf/tests/stat.c +21 -0
@@ -88,3 +88,24 @@ int test__synthesize_stat(void)return 0 ; } + +static int process_stat_round_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_sample *sample__maybe_unused , +struct machine *machine__maybe_unused ) +{ +struct stat_round_event *stat_round = &event->stat_round; + +TEST_ASSERT_VAL ("wrong time" , stat_round->time ==0xdeadbeef ); +TEST_ASSERT_VAL ("wrong type" , stat_round->type ==PERF_STAT_ROUND_TYPE__INTERVAL ); +return 0 ; +} + +int test__synthesize_stat_round (void ) +{ +TEST_ASSERT_VAL ("failed to synthesize stat_config" , + !perf_event__synthesize_stat_round (NULL ,0xdeadbeef ,PERF_STAT_ROUND_TYPE__INTERVAL , + process_stat_round_event,NULL )); + +return 0 ; +}
tools/perf/tests/tests.h +2 -0
@@ -71,6 +71,8 @@ int test__thread_map_synthesize(void);int test__cpu_map_synthesize (void );int test__synthesize_stat_config (void );int test__synthesize_stat (void ); +int test__synthesize_stat_round (void ); +#if defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/util/event.c +17 -0
@@ -933,6 +933,23 @@ int perf_event__synthesize_stat(struct perf_tool *tool,return process (tool, (union perf_event *) &event,NULL , machine); } +int perf_event__synthesize_stat_round (struct perf_tool *tool, +u64 time,u64 type, +perf_event__handler_t process, +struct machine *machine) +{ +struct stat_round_event event; + + event.header.type =PERF_RECORD_STAT_ROUND ; + event.header.size =sizeof (event); + event.header.misc =0 ; + + event.time = time; + event.type = type; + +return process (tool, (union perf_event *) &event,NULL , machine); +} +void perf_event__read_stat_config (struct perf_stat_config *config,struct stat_config_event *event) {
tools/perf/util/event.h +4 -0
@@ -517,6 +517,10 @@ int perf_event__synthesize_stat(struct perf_tool *tool,struct perf_counts_values *count, perf_event__handler_t process, struct machine *machine); +int perf_event__synthesize_stat_round (struct perf_tool *tool, +u64 time,u64 type, +perf_event__handler_t process, +struct machine *machine);int perf_event__synthesize_modules (struct perf_tool *tool,perf_event__handler_t process,struct machine *machine);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 18/57 perf tools: Add stat events fprintf functions
In reply to Jiri OlsaIntroducing following functions to display stat events for raw dump.
perf_event__fprintf_stat
perf_event__fprintf_stat_round
perf_event__fprintf_stat_config
--- tools/perf/util/stat.c | 39 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 4 ++++ 2 files changed, 43 insertions(+)
tools/perf/util/stat.c +39 -0
@@ -363,3 +363,42 @@ int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused, counter->supported = true;return 0 ; } + +size_t perf_event__fprintf_stat (union perf_event *event,FILE *fp) +{ +struct stat_event *stat = (struct stat_event *) event; +size_t ret; + + ret =fprintf (fp,"\n... id %" PRIu64", cpu %d, thread %d\n" , + stat->id, stat->cpu, stat->thread); + ret +=fprintf (fp,"... value %" PRIu64", enabled %" PRIu64", running %" PRIu64"\n" , + stat->val, stat->ena, stat->run); + +return ret; +} + +size_t perf_event__fprintf_stat_round (union perf_event *event,FILE *fp) +{ +struct stat_round_event *round = (struct stat_round_event *) event; +size_t ret; + + ret =fprintf (fp,"\n... time %" PRIu64", type %s\n" , round->time, + round->type ==PERF_STAT_ROUND_TYPE__FINAL ?"FINAL" :"INTERVAL" ); + +return ret; +} + +size_t perf_event__fprintf_stat_config (union perf_event *event,FILE *fp) +{ +struct perf_stat_config sc; +size_t ret; + +perf_event__read_stat_config (&sc, &event->stat_config); + + ret =fprintf (fp,"\n" ); + ret +=fprintf (fp,"... aggr_mode %d\n" , sc.aggr_mode); + ret +=fprintf (fp,"... scale %d\n" , sc.scale); + ret +=fprintf (fp,"... interval %u\n" , sc.interval); + +return ret; +}
tools/perf/util/stat.h +4 -0
@@ -95,4 +95,8 @@ struct perf_session;int perf_event__process_stat_event (struct perf_tool *tool,union perf_event *event,struct perf_session *session); + +size_t perf_event__fprintf_stat (union perf_event *event,FILE *fp); +size_t perf_event__fprintf_stat_round (union perf_event *event,FILE *fp); +size_t perf_event__fprintf_stat_config (union perf_event *event,FILE *fp);#endif
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 19/57 perf tools: Add attr_update event
In reply to Jiri OlsaIt'll server as base event for additional event attributes details, that are not part of the attr event.
At the moment this event is just dummy one without specific functionality. The type value will distinguish the update event details. It comes in following patches.
The idea for this event is to be extensible for any update that attr event might need in the future.
--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 10 ++++++++++ tools/perf/util/header.c | 20 ++++++++++++++++++++ tools/perf/util/header.h | 3 +++ tools/perf/util/session.c | 21 +++++++++++++++++++++ tools/perf/util/tool.h | 1 + 6 files changed, 56 insertions(+)
tools/perf/util/event.c +1 -0
@@ -44,6 +44,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT_CONFIG] = "STAT_CONFIG", [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", + [PERF_RECORD_HEADER_ATTR_UPDATE] = "ATTR_UPDATE", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +10 -0
@@ -231,6 +231,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT_CONFIG =75 ,PERF_RECORD_STAT =76 ,PERF_RECORD_STAT_ROUND =77 , +PERF_RECORD_HEADER_ATTR_UPDATE =78 , PERF_RECORD_HEADER_MAX };
@@ -307,6 +308,14 @@ struct attr_event {u64 id[]; }; +struct attr_update_event { +struct perf_event_header header; +u64 type; +u64 id; + +char data[]; +}; +#define MAX_EVENT_NAME 64struct perf_trace_event_type {
@@ -456,6 +465,7 @@ union perf_event {struct throttle_event throttle;struct sample_event sample;struct attr_event attr; +struct attr_update_event attr_update;struct event_type_event event_type;struct tracing_data_event tracing_data;struct build_id_event build_id;
tools/perf/util/header.c +20 -0
@@ -2745,6 +2745,26 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,return 0 ; } +int perf_event__process_attr_update (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_evlist **pevlist) +{ +struct attr_update_event *ev = &event->attr_update; +struct perf_evlist *evlist; +struct perf_evsel *evsel; + +if (!pevlist || *pevlist ==NULL ) +return -EINVAL ; + + evlist = *pevlist; + + evsel =perf_evlist__id2evsel (evlist, ev->id); +if (evsel ==NULL ) +return -EINVAL ; + +return 0 ; +} +int perf_event__synthesize_tracing_data (struct perf_tool *tool,int fd,struct perf_evlist *evlist,perf_event__handler_t process)
tools/perf/util/header.h +3 -0
@@ -107,6 +107,9 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, perf_event__handler_t process);int perf_event__process_attr (struct perf_tool *tool,union perf_event *event,struct perf_evlist **pevlist); +int perf_event__process_attr_update (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_evlist **pevlist); int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct perf_evlist *evlist,
tools/perf/util/session.c +21 -0
@@ -205,6 +205,15 @@ static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static int process_event_synth_attr_update_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_evlist **pevlist +__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} + static int process_event_sample_stub(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused,
@@ -374,6 +383,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->unthrottle = process_event_stub;if (tool->attr ==NULL ) tool->attr = process_event_synth_attr_stub; +if (tool->attr_update ==NULL ) + tool->attr_update = process_event_synth_attr_update_stub;if (tool->tracing_data ==NULL ) tool->tracing_data = process_event_synth_tracing_data_stub;if (tool->build_id ==NULL )
@@ -625,6 +636,13 @@ static void perf_event__hdr_attr_swap(union perf_event *event,mem_bswap_64 (event->attr.id, size); } +static void perf_event__hdr_attr_update_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ + event->attr_update.type =bswap_64 (event->attr_update.type); + event->attr_update.id =bswap_64 (event->attr_update.id); +} +static void perf_event__event_type_swap (union perf_event *event,bool sample_id_all__maybe_unused ) {
@@ -779,6 +797,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT_CONFIG] = perf_event__stat_config_swap, [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, + [PERF_RECORD_HEADER_ATTR_UPDATE] = perf_event__hdr_attr_update_swap, [PERF_RECORD_HEADER_MAX] = NULL, };
@@ -1290,6 +1309,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,perf_session__set_comm_exec (session); }return err; +case PERF_RECORD_HEADER_ATTR_UPDATE : +return tool->attr_update (tool, event, &session->evlist);case PERF_RECORD_HEADER_EVENT_TYPE :/* * Depreceated, but we need to handle it for sake
tools/perf/util/tool.h +1 -0
@@ -50,6 +50,7 @@ struct perf_tool { throttle, unthrottle;event_attr_op attr; +event_attr_op attr_update;event_op2 tracing_data;event_oe finished_round; event_op2 build_id,
Signature · 1 line
2.4.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 19/57] perf tools: Add attr_update event
Em Fri, Oct 16, 2015 at 12:40:54PM +0200, Jiri Olsa escreveu:
Quoted 9 lines
It'll server as base event for additional event attributes details, that are not part of the attr event.
At the moment this event is just dummy one without specific functionality. The type value will distinguish the update event details. It comes in following patches.
The idea for this event is to be extensible for any update that attr event might need in the future.
"Update"? Found it confusing, how about calling it "add event attribute", because that is what this is doing, adding attributes, like "unit" (Joules, MiB, nsec, etc), "scale", etc.
- Arnaldo
Quoted 177 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 10 ++++++++++ tools/perf/util/header.c | 20 ++++++++++++++++++++ tools/perf/util/header.h | 3 +++ tools/perf/util/session.c | 21 +++++++++++++++++++++ tools/perf/util/tool.h | 1 + 6 files changed, 56 insertions(+)tools/perf/util/event.c +1
-0@@ -44,6 +44,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT_CONFIG] = "STAT_CONFIG", [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", + [PERF_RECORD_HEADER_ATTR_UPDATE] = "ATTR_UPDATE", };const char *perf_event__name (unsigned int id)tools/perf/util/event.h +10
-0@@ -231,6 +231,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT_CONFIG =75 ,PERF_RECORD_STAT =76 ,PERF_RECORD_STAT_ROUND =77 , +PERF_RECORD_HEADER_ATTR_UPDATE =78 , PERF_RECORD_HEADER_MAX };@@ -307,6 +308,14 @@ struct attr_event {u64 id[]; }; +struct attr_update_event { +struct perf_event_header header; +u64 type; +u64 id; + +char data[]; +}; +#define MAX_EVENT_NAME 64struct perf_trace_event_type {@@ -456,6 +465,7 @@ union perf_event {struct throttle_event throttle;struct sample_event sample;struct attr_event attr; +struct attr_update_event attr_update;struct event_type_event event_type;struct tracing_data_event tracing_data;struct build_id_event build_id;tools/perf/util/header.c +20
-0@@ -2745,6 +2745,26 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,return 0 ; } +int perf_event__process_attr_update (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_evlist **pevlist) +{ +struct attr_update_event *ev = &event->attr_update; +struct perf_evlist *evlist; +struct perf_evsel *evsel; + +if (!pevlist || *pevlist ==NULL ) +return -EINVAL ; + + evlist = *pevlist; + + evsel =perf_evlist__id2evsel (evlist, ev->id); +if (evsel ==NULL ) +return -EINVAL ; + +return 0 ; +} +int perf_event__synthesize_tracing_data (struct perf_tool *tool,int fd,struct perf_evlist *evlist,perf_event__handler_t process)tools/perf/util/header.h +3
-0@@ -107,6 +107,9 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, perf_event__handler_t process);int perf_event__process_attr (struct perf_tool *tool,union perf_event *event,struct perf_evlist **pevlist); +int perf_event__process_attr_update (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_evlist **pevlist); int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct perf_evlist *evlist,tools/perf/util/session.c +21
-0@@ -205,6 +205,15 @@ static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static int process_event_synth_attr_update_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_evlist **pevlist +__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} + static int process_event_sample_stub(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused,@@ -374,6 +383,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->unthrottle = process_event_stub;if (tool->attr ==NULL ) tool->attr = process_event_synth_attr_stub; +if (tool->attr_update ==NULL ) + tool->attr_update = process_event_synth_attr_update_stub;if (tool->tracing_data ==NULL ) tool->tracing_data = process_event_synth_tracing_data_stub;if (tool->build_id ==NULL )@@ -625,6 +636,13 @@ static void perf_event__hdr_attr_swap(union perf_event *event,mem_bswap_64 (event->attr.id, size); } +static void perf_event__hdr_attr_update_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ + event->attr_update.type =bswap_64 (event->attr_update.type); + event->attr_update.id =bswap_64 (event->attr_update.id); +} +static void perf_event__event_type_swap (union perf_event *event,bool sample_id_all__maybe_unused ) {@@ -779,6 +797,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT_CONFIG] = perf_event__stat_config_swap, [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, + [PERF_RECORD_HEADER_ATTR_UPDATE] = perf_event__hdr_attr_update_swap, [PERF_RECORD_HEADER_MAX] = NULL, };@@ -1290,6 +1309,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,perf_session__set_comm_exec (session); }return err; +case PERF_RECORD_HEADER_ATTR_UPDATE : +return tool->attr_update (tool, event, &session->evlist);case PERF_RECORD_HEADER_EVENT_TYPE :/* * Depreceated, but we need to handle it for sake tools/perf/util/tool.h +1
-0@@ -50,6 +50,7 @@ struct perf_tool { throttle, unthrottle;event_attr_op attr; +event_attr_op attr_update;event_op2 tracing_data;event_oe finished_round; event_op2 build_id,Signature · 1 line
2.4.3
Re: [PATCH 19/57] perf tools: Add attr_update event
Quoted 8 lines · Arnaldo Carvalho de Melo
Em Fri, Oct 16, 2015 at 12:40:54PM +0200, Jiri Olsa escreveu:
Quoted 7 lines
It'll server as base event for additional event attributes details, that are not part of the attr event.
At the moment this event is just dummy one without specific functionality. The type value will distinguish the update event details. It comes in following patches.
Quoted 6 lines
Quoted 2 lines
The idea for this event is to be extensible for any update that attr event might need in the future.
"Update"? Found it confusing, how about calling it "add event attribute", because that is what this is doing, adding attributes, like "unit" (Joules, MiB, nsec, etc), "scale", etc.
well, we have PERF_RECORD_HEADER_ATTR event based on which the event is created.. so PERF_RECORD_HEADER_ATTR_UPDATE seemed like good choice.. anyway, how about:
PERF_RECORD_ADD_EVENT_ATTR
PERF_RECORD_EVENT_ATTR
PERF_RECORD_EVENT_UPDATE
jirka
Re: [PATCH 19/57] perf tools: Add attr_update event
Quoted 16 lines · Jiri Olsa
Quoted 8 lines · Arnaldo Carvalho de Melo
Em Fri, Oct 16, 2015 at 12:40:54PM +0200, Jiri Olsa escreveu:
Quoted 7 lines
It'll server as base event for additional event attributes details, that are not part of the attr event.
At the moment this event is just dummy one without specific functionality. The type value will distinguish the update event details. It comes in following patches.
Quoted 6 lines
Quoted 2 lines
The idea for this event is to be extensible for any update that attr event might need in the future.
"Update"? Found it confusing, how about calling it "add event attribute", because that is what this is doing, adding attributes, like "unit" (Joules, MiB, nsec, etc), "scale", etc.
Quoted 7 lines
well, we have
PERF_RECORD_HEADER_ATTRevent based on which the event is created.. soPERF_RECORD_HEADER_ATTR_UPDATEseemed like good choice.. anyway, how about:
PERF_RECORD_ADD_EVENT_ATTR
PERF_RECORD_EVENT_ATTR
PERF_RECORD_EVENT_UPDATE
choosing the PERF_RECORD_EVENT_UPDATE for next version..
jirka
Jiri Olsa
reviewerPATCH v4 20/57 perf tools: Add attr_update event unit type
In reply to Jiri OlsaAdding unit type attr update event, that stores/transfer events unit name. The unit name is part of the perf stat output data.
--- tools/perf/tests/Build | 1 + tools/perf/tests/attr_update.c | 42 +++++++++++++++++++++++++++++++++++++++ tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/tests.h | 1 + tools/perf/util/event.h | 5 +++++ tools/perf/util/header.c | 44 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 3 +++ 7 files changed, 100 insertions(+) create mode 100644 tools/perf/tests/attr_update.c
tools/perf/tests/Build +1 -0
@@ -35,6 +35,7 @@ perf-y += llvm.o perf-y += topology.o perf-y += cpumap.o perf-y += stat.o +perf-y += attr_update.o ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
tools/perf/tests/attr_update.c new file +42 -0
42 lines not on this page · raw message
tools/perf/tests/builtin-test.c +4 -0
@@ -186,6 +186,10 @@ static struct test generic_tests[] = { .func = test__synthesize_stat_round, }, { + .desc = "Test attr update synthesize", + .func = test__attr_update, + }, + { .func = NULL, }, };
tools/perf/tests/tests.h +1 -0
@@ -72,6 +72,7 @@ int test__cpu_map_synthesize(void);int test__synthesize_stat_config (void );int test__synthesize_stat (void );int test__synthesize_stat_round (void ); +int test__attr_update (void );#if defined(__arm__) || defined(__aarch64__)
tools/perf/util/event.h +5 -0
@@ -308,6 +308,11 @@ struct attr_event {u64 id[]; }; + +enum { +PERF_ATTR_UPDATE__UNIT =0 , +}; +struct attr_update_event {struct perf_event_header header;u64 type;
tools/perf/util/header.c +44 -0
56 lines not on this page · raw message
tools/perf/util/header.h +3 -0
@@ -105,6 +105,9 @@ int perf_event__synthesize_attr(struct perf_tool *tool,int perf_event__synthesize_attrs (struct perf_tool *tool,struct perf_session *session,perf_event__handler_t process); +int perf_event__synthesize_attr_update_unit (struct perf_tool *tool, +struct perf_evsel *evsel, +perf_event__handler_t process);int perf_event__process_attr (struct perf_tool *tool,union perf_event *event,struct perf_evlist **pevlist); int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 21/57 perf tools: Add attr_update event scale type
In reply to Jiri OlsaAdding scale type attr update event, that stores/transfer events scale value. The PMU events can define the scale value which is used to multiply events data.
--- tools/perf/tests/attr_update.c | 21 +++++++++++++++++++++ tools/perf/util/event.h | 5 +++++ tools/perf/util/header.c | 26 ++++++++++++++++++++++++++ tools/perf/util/header.h | 3 +++ 4 files changed, 55 insertions(+)
tools/perf/tests/attr_update.c +21 -0
@@ -18,6 +18,22 @@ static int process_event_unit(struct perf_tool *tool __maybe_unused,return 0 ; } +static int process_event_scale (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_sample *sample__maybe_unused , +struct machine *machine__maybe_unused ) +{ +struct attr_update_event *ev = (struct attr_update_event *) event; +struct attr_update_event_scale *ev_data; + + ev_data = (struct attr_update_event_scale *) ev->data; + +TEST_ASSERT_VAL ("wrong id" , ev->id ==123 ); +TEST_ASSERT_VAL ("wrong id" , ev->type ==PERF_ATTR_UPDATE__SCALE ); +TEST_ASSERT_VAL ("wrong scale" , ev_data->scale =0.123 ); +return 0 ; +} +int test__attr_update (void ) {struct perf_evlist *evlist;
@@ -38,5 +54,10 @@ int test__attr_update(void)TEST_ASSERT_VAL ("failed to synthesize attr update unit" , !perf_event__synthesize_attr_update_unit (NULL , evsel, process_event_unit)); + evsel->scale =0.123 ; + +TEST_ASSERT_VAL ("failed to synthesize attr update scale" , + !perf_event__synthesize_attr_update_scale (NULL , evsel, process_event_scale)); +return 0 ; }
tools/perf/util/event.h +5 -0
@@ -311,6 +311,11 @@ struct attr_event {enum {PERF_ATTR_UPDATE__UNIT =0 , +PERF_ATTR_UPDATE__SCALE =1 , +}; + +struct attr_update_event_scale { +double scale; };struct attr_update_event {
tools/perf/util/header.c +26 -0
@@ -2723,6 +2723,27 @@ perf_event__synthesize_attr_update_unit(struct perf_tool *tool,return err; } +int +perf_event__synthesize_attr_update_scale (struct perf_tool *tool, +struct perf_evsel *evsel, +perf_event__handler_t process) +{ +struct attr_update_event *ev; +struct attr_update_event_scale *ev_data; +int err; + + ev =attr_update_event__alloc (sizeof (*ev_data),PERF_ATTR_UPDATE__SCALE , evsel->id[0 ]); +if (ev ==NULL ) +return -ENOMEM ; + + ev_data = (struct attr_update_event_scale *) ev->data; + ev_data->scale = evsel->scale; + err =process (tool, (union perf_event *) ev,NULL ,NULL ); +free (ev); +return err; +} + +int perf_event__synthesize_attrs (struct perf_tool *tool,struct perf_session *session,perf_event__handler_t process)
@@ -2787,6 +2808,7 @@ int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused, struct perf_evlist **pevlist) {struct attr_update_event *ev = &event->attr_update; +struct attr_update_event_scale *ev_scale;struct perf_evlist *evlist;struct perf_evsel *evsel;
@@ -2802,6 +2824,10 @@ int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,switch (ev->type) {case PERF_ATTR_UPDATE__UNIT : evsel->unit =strdup (ev->data); +break ; +case PERF_ATTR_UPDATE__SCALE : + ev_scale = (struct attr_update_event_scale *) ev->data; + evsel->scale = ev_scale->scale;default :break ; }
tools/perf/util/header.h +3 -0
@@ -108,6 +108,9 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,int perf_event__synthesize_attr_update_unit (struct perf_tool *tool,struct perf_evsel *evsel,perf_event__handler_t process); +int perf_event__synthesize_attr_update_scale (struct perf_tool *tool, +struct perf_evsel *evsel, +perf_event__handler_t process);int perf_event__process_attr (struct perf_tool *tool,union perf_event *event,struct perf_evlist **pevlist); int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 22/57 perf tools: Add attr_update event name type
In reply to Jiri OlsaAdding name type attr update event, that stores/transfer events name. Event's name is stored within perf.data's EVENT_DESC feature, but we don't have if we get report data from pipe.
--- tools/perf/tests/attr_update.c | 25 +++++++++++++++++++++++++ tools/perf/util/event.h | 1 + tools/perf/util/header.c | 21 +++++++++++++++++++++ tools/perf/util/header.h | 3 +++ 4 files changed, 50 insertions(+)
tools/perf/tests/attr_update.c +25 -0
@@ -34,10 +34,30 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused,return 0 ; } +struct event_name { +struct perf_tool tool; +const char *name; +}; + +static int process_event_name (struct perf_tool *tool, +union perf_event *event, +struct perf_sample *sample__maybe_unused , +struct machine *machine__maybe_unused ) +{ + struct event_name *tmp = container_of(tool, struct event_name, tool); +struct attr_update_event *ev = (struct attr_update_event *) event; + +TEST_ASSERT_VAL ("wrong id" , ev->id ==123 ); +TEST_ASSERT_VAL ("wrong id" , ev->type ==PERF_ATTR_UPDATE__NAME ); +TEST_ASSERT_VAL ("wrong name" , !strcmp (ev->data, tmp->name)); +return 0 ; +} +int test__attr_update (void ) {struct perf_evlist *evlist;struct perf_evsel *evsel; +struct event_name tmp; evlist =perf_evlist__new_default ();TEST_ASSERT_VAL ("failed to get evlist" , evlist);
@@ -59,5 +79,10 @@ int test__attr_update(void)TEST_ASSERT_VAL ("failed to synthesize attr update scale" , !perf_event__synthesize_attr_update_scale (NULL , evsel, process_event_scale)); + tmp.name =perf_evsel__name (evsel); + +TEST_ASSERT_VAL ("failed to synthesize attr update name" , + !perf_event__synthesize_attr_update_name (&tmp.tool, evsel, process_event_name)); +return 0 ; }
tools/perf/util/event.h +1 -0
@@ -312,6 +312,7 @@ struct attr_event {enum {PERF_ATTR_UPDATE__UNIT =0 ,PERF_ATTR_UPDATE__SCALE =1 , +PERF_ATTR_UPDATE__NAME =2 , };struct attr_update_event_scale {
tools/perf/util/header.c +21 -0
@@ -2743,6 +2743,24 @@ perf_event__synthesize_attr_update_scale(struct perf_tool *tool,return err; } +int +perf_event__synthesize_attr_update_name (struct perf_tool *tool, +struct perf_evsel *evsel, +perf_event__handler_t process) +{ +struct attr_update_event *ev; +size_t len =strlen (evsel->name); +int err; + + ev =attr_update_event__alloc (len +1 ,PERF_ATTR_UPDATE__NAME , evsel->id[0 ]); +if (ev ==NULL ) +return -ENOMEM ; + +strncpy (ev->data, evsel->name, len); + err =process (tool, (union perf_event *) ev,NULL ,NULL ); +free (ev); +return err; +} int perf_event__synthesize_attrs(struct perf_tool *tool, struct perf_session *session,
@@ -2825,6 +2843,9 @@ int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,case PERF_ATTR_UPDATE__UNIT : evsel->unit =strdup (ev->data);break ; +case PERF_ATTR_UPDATE__NAME : + evsel->name =strdup (ev->data); +break ;case PERF_ATTR_UPDATE__SCALE : ev_scale = (struct attr_update_event_scale *) ev->data; evsel->scale = ev_scale->scale;
tools/perf/util/header.h +3 -0
@@ -111,6 +111,9 @@ int perf_event__synthesize_attr_update_unit(struct perf_tool *tool,int perf_event__synthesize_attr_update_scale (struct perf_tool *tool,struct perf_evsel *evsel,perf_event__handler_t process); +int perf_event__synthesize_attr_update_name (struct perf_tool *tool, +struct perf_evsel *evsel, +perf_event__handler_t process);int perf_event__process_attr (struct perf_tool *tool,union perf_event *event,struct perf_evlist **pevlist); int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 23/57 perf tools: Add attr_update event cpus type
In reply to Jiri OlsaAdding cpumask attr update event, that stores/transfer cpumask for event.
--- tools/perf/tests/attr_update.c | 30 ++++++++++++++++++++++++++++++ tools/perf/util/event.h | 5 +++++ tools/perf/util/header.c | 42 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 3 +++ 4 files changed, 80 insertions(+)
tools/perf/tests/attr_update.c +30 -0
@@ -53,6 +53,30 @@ static int process_event_name(struct perf_tool *tool,return 0 ; } +static int process_event_cpus (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_sample *sample__maybe_unused , +struct machine *machine__maybe_unused ) +{ +struct attr_update_event *ev = (struct attr_update_event *) event; +struct attr_update_event_cpus *ev_data; +struct cpu_map *map; + + ev_data = (struct attr_update_event_cpus *) ev->data; + + map =cpu_map__new_data (&ev_data->cpus); + +TEST_ASSERT_VAL ("wrong id" , ev->id ==123 ); +TEST_ASSERT_VAL ("wrong type" , ev->type ==PERF_ATTR_UPDATE__CPUS ); +TEST_ASSERT_VAL ("wrong cpus" , map->nr ==3 ); +TEST_ASSERT_VAL ("wrong cpus" , map->map[0 ] ==1 ); +TEST_ASSERT_VAL ("wrong cpus" , map->map[1 ] ==2 ); +TEST_ASSERT_VAL ("wrong cpus" , map->map[2 ] ==3 ); +cpu_map__put (map); +return 0 ; +} + +int test__attr_update (void ) {struct perf_evlist *evlist;
@@ -84,5 +108,11 @@ int test__attr_update(void)TEST_ASSERT_VAL ("failed to synthesize attr update name" , !perf_event__synthesize_attr_update_name (&tmp.tool, evsel, process_event_name)); + evsel->own_cpus =cpu_map__new ("1,2,3" ); + +TEST_ASSERT_VAL ("failed to synthesize attr update cpus" , + !perf_event__synthesize_attr_update_cpus (&tmp.tool, evsel, process_event_cpus)); + +cpu_map__put (evsel->own_cpus);return 0 ; }
tools/perf/util/event.h +5 -0
@@ -313,6 +313,11 @@ enum {PERF_ATTR_UPDATE__UNIT =0 ,PERF_ATTR_UPDATE__SCALE =1 ,PERF_ATTR_UPDATE__NAME =2 , + PERF_ATTR_UPDATE__CPUS = 3, +}; + +struct attr_update_event_cpus { +struct cpu_map_data cpus; }; struct attr_update_event_scale {
tools/perf/util/header.c +42 -0
62 lines not on this page · raw message
tools/perf/util/header.h +3 -0
@@ -114,6 +114,9 @@ int perf_event__synthesize_attr_update_scale(struct perf_tool *tool,int perf_event__synthesize_attr_update_name (struct perf_tool *tool,struct perf_evsel *evsel,perf_event__handler_t process); +int perf_event__synthesize_attr_update_cpus (struct perf_tool *tool, +struct perf_evsel *evsel, +perf_event__handler_t process);int perf_event__process_attr (struct perf_tool *tool,union perf_event *event,struct perf_evlist **pevlist); int perf_event__process_attr_update(struct perf_tool *tool __maybe_unused,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 24/57 perf tools: Add perf_event__fprintf_attr_update function
In reply to Jiri OlsaTo display attr_update event for raw dump.
--- tools/perf/util/header.c | 38 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 1 + 2 files changed, 39 insertions(+)
tools/perf/util/header.c +38 -0
@@ -2793,6 +2793,44 @@ perf_event__synthesize_attr_update_cpus(struct perf_tool *tool,return err; } +size_t perf_event__fprintf_attr_update (union perf_event *event,FILE *fp) +{ +struct attr_update_event *ev = &event->attr_update; +struct attr_update_event_scale *ev_scale; +struct attr_update_event_cpus *ev_cpus; +struct cpu_map *map; +size_t ret; + + ret =fprintf (fp,"\n... id: %" PRIu64"\n" , ev->id); + +switch (ev->type) { +case PERF_ATTR_UPDATE__SCALE : + ev_scale = (struct attr_update_event_scale *) ev->data; + ret +=fprintf (fp,"... scale: %f\n" , ev_scale->scale); +break ; +case PERF_ATTR_UPDATE__UNIT : + ret +=fprintf (fp,"... unit: %s\n" , ev->data); +break ; +case PERF_ATTR_UPDATE__NAME : + ret +=fprintf (fp,"... name: %s\n" , ev->data); +break ; +case PERF_ATTR_UPDATE__CPUS : + ev_cpus = (struct attr_update_event_cpus *) ev->data; + ret +=fprintf (fp,"... " ); + + map =cpu_map__new_data (&ev_cpus->cpus); +if (map) + ret +=cpu_map__fprintf (map, fp); +else + ret +=fprintf (fp,"failed to get cpus\n" ); +break ; +default : + ret +=fprintf (fp,"... unknown type\n" ); +break ; + } + +return ret; +} int perf_event__synthesize_attrs(struct perf_tool *tool, struct perf_session *session,
tools/perf/util/header.h +1 -0
@@ -122,6 +122,7 @@ int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,int perf_event__process_attr_update (struct perf_tool *tool__maybe_unused ,union perf_event *event,struct perf_evlist **pevlist); +size_t perf_event__fprintf_attr_update (union perf_event *event,FILE *fp); int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct perf_evlist *evlist,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 25/57 perf report: Display newly added events in raw dump
In reply to Jiri OlsaThe 'perf report -D' command will now display dump and detailed output for newly added events:
attr_update
thread_map
cpu_map
stat
stat_config
stat_round
--- tools/perf/util/session.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
tools/perf/util/session.c +19 -0
@@ -17,6 +17,7 @@#include "asm/bug.h" #include "auxtrace.h" #include "thread-stack.h" +#include "stat.h" static int perf_session__deliver_event(struct perf_session *session, union perf_event *event,
@@ -210,6 +211,9 @@ static int process_event_synth_attr_update_stub(struct perf_tool *tool __maybe_ustruct perf_evlist **pevlist __maybe_unused) { +if (dump_trace) +perf_event__fprintf_attr_update (event, stdout); +dump_printf (": unhandled!\n" );return 0 ; }
@@ -311,6 +315,9 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,union perf_event *event__maybe_unused , struct perf_session *session __maybe_unused) { + if (dump_trace) + perf_event__fprintf_thread_map(event, stdout); + dump_printf(": unhandled!\n");return 0 ; }
@@ -320,6 +327,9 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,union perf_event *event__maybe_unused , struct perf_session *session __maybe_unused) { + if (dump_trace) + perf_event__fprintf_cpu_map(event, stdout); + dump_printf(": unhandled!\n");return 0 ; }
@@ -329,6 +339,9 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,union perf_event *event__maybe_unused , struct perf_session *session __maybe_unused) { + if (dump_trace) + perf_event__fprintf_stat_config(event, stdout); + dump_printf(": unhandled!\n");return 0 ; }
@@ -338,6 +351,9 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,struct perf_session *perf_session __maybe_unused) { +if (dump_trace) +perf_event__fprintf_stat (event, stdout); +dump_printf (": unhandled!\n" );return 0 ; }
@@ -347,6 +363,9 @@ static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,struct perf_session *perf_session __maybe_unused) { +if (dump_trace) +perf_event__fprintf_stat_round (event, stdout); +dump_printf (": unhandled!\n" );return 0 ; }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 26/57 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.
In future it might be used to store version of the stat storage system we used.
--- 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
@@ -451,6 +451,8 @@ static void record__init_features(struct record *rec)if (!rec->opts.full_auxtrace)perf_header__clear_feat (&session->header,HEADER_AUXTRACE ); + +perf_header__clear_feat (&session->header,HEADER_STAT ); }static volatile int workload_exec_errno;
tools/perf/util/header.c +14 -0
@@ -868,6 +868,13 @@ static int write_auxtrace(int fd, struct perf_header *h,return err; } +static int write_stat (int fd__maybe_unused , +struct perf_header *h__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +return 0 ; +} +static void print_hostname (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) {
@@ -1159,6 +1166,12 @@ static void print_auxtrace(struct perf_header *ph __maybe_unused,fprintf (fp,"# contains AUX area data (e.g. instruction trace)\n" ); } +static void print_stat (struct perf_header *ph__maybe_unused , +int fd__maybe_unused ,FILE *fp) +{ +fprintf (fp,"# contains stat data\n" ); +} +static void print_pmu_mappings (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) {
@@ -1948,6 +1961,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {FEAT_OPP (HEADER_PMU_MAPPINGS , pmu_mappings),FEAT_OPP (HEADER_GROUP_DESC , group_desc),FEAT_OPP (HEADER_AUXTRACE , auxtrace), + FEAT_OPA(HEADER_STAT, stat), }; struct header_print_data {
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 v4 27/57 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
@@ -90,9 +90,9 @@ struct perf_evsel {double scale;const char *unit;struct event_format *tp_format; +off_t id_offset;union {void *priv; -off_t id_offset;u64 db_id; };struct cgroup_sel *cgrp;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 28/57 perf stat: Rename perf_stat struct into perf_stat_evsel
In reply to Jiri OlsaIt's used as the perf_evsel::priv data, so the name suits better. Also we'll need the perf_stat name free for more generic struct.
--- tools/perf/builtin-stat.c | 4 ++-- tools/perf/util/stat.c | 10 +++++----- tools/perf/util/stat.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/builtin-stat.c +2 -2
@@ -434,7 +434,7 @@ static void print_noise_pct(double total, double avg)static void print_noise (struct perf_evsel *evsel,double avg) { -struct perf_stat *ps; +struct perf_stat_evsel *ps;if (run_count ==1 )return ;
@@ -671,7 +671,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)static void print_counter_aggr (struct perf_evsel *counter,char *prefix) {FILE *output = stat_config.output; -struct perf_stat *ps = counter->priv; +struct perf_stat_evsel *ps = counter->priv;double avg =avg_stats (&ps->res_stats[0 ]);int scaled = counter->counts->scaled;double uval;
tools/perf/util/stat.c +5 -5
@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg)bool __perf_evsel_stat__is (struct perf_evsel *evsel,enum perf_stat_evsel_id id) { -struct perf_stat *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->priv;return ps->id == id; }
@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {void perf_stat_evsel_id_init (struct perf_evsel *evsel) { -struct perf_stat *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->priv;int i;/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) {int i; -struct perf_stat *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->priv;for (i =0 ; i <3 ; i++)init_stats (&ps->res_stats[i]);
@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)int perf_evsel__alloc_stat_priv (struct perf_evsel *evsel) { - evsel->priv =zalloc (sizeof (struct perf_stat )); + evsel->priv =zalloc (sizeof (struct perf_stat_evsel ));if (evsel->priv ==NULL )return -ENOMEM ;perf_evsel__reset_stat_priv (evsel);
@@ -304,7 +304,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, struct perf_evsel *counter) {struct perf_counts_values *aggr = &counter->counts->aggr; -struct perf_stat *ps = counter->priv; +struct perf_stat_evsel *ps = counter->priv;u64 *count = counter->counts->aggr.values;int i, ret;
tools/perf/util/stat.h +1 -1
@@ -20,7 +20,7 @@ enum perf_stat_evsel_id { PERF_STAT_EVSEL_ID__MAX, }; -struct perf_stat { +struct perf_stat_evsel {struct stats res_stats[3 ];enum perf_stat_evsel_id id; };
Signature · 1 line
2.4.3
Re: [PATCH 28/57] perf stat: Rename perf_stat struct into perf_stat_evsel
Em Fri, Oct 16, 2015 at 12:41:03PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
It's used as the
perf_evsel::privdata, so the name suits better. Also we'll need theperf_statname free for more generic struct.
Applied.
Quoted 2 lines
Signed-off-by Jiri Olsa <[email protected]>
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Rename perf_stat struct into perf_stat_evsel
In reply to Jiri Olsaperf stat: Rename perf_stat struct into perf_stat_evsel
Commit-ID: 581cc8a2a2a00afc864840720186b0f6a38079d9 Gitweb: http://git.kernel.org/tip/581cc8a2a2a00afc864840720186b0f6a38079d9 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 16 Oct 2015 12:41:03 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 19 Oct 2015 18:01:05 -0300
perf stat: Rename perf_stat struct into perf_stat_evsel
It's used as the perf_evsel::priv data, so the name suits better. Also we'll need the perf_stat name free for more generic struct.
--- tools/perf/builtin-stat.c | 4 ++-- tools/perf/util/stat.c | 10 +++++----- tools/perf/util/stat.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/builtin-stat.c +2 -2
@@ -434,7 +434,7 @@ static void print_noise_pct(double total, double avg)static void print_noise (struct perf_evsel *evsel,double avg) { -struct perf_stat *ps; +struct perf_stat_evsel *ps;if (run_count ==1 )return ;
@@ -671,7 +671,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)static void print_counter_aggr (struct perf_evsel *counter,char *prefix) {FILE *output = stat_config.output; -struct perf_stat *ps = counter->priv; +struct perf_stat_evsel *ps = counter->priv;double avg =avg_stats (&ps->res_stats[0 ]);int scaled = counter->counts->scaled;double uval;
tools/perf/util/stat.c +5 -5
@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg)bool __perf_evsel_stat__is (struct perf_evsel *evsel,enum perf_stat_evsel_id id) { -struct perf_stat *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->priv;return ps->id == id; }
@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {void perf_stat_evsel_id_init (struct perf_evsel *evsel) { -struct perf_stat *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->priv;int i;/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) {int i; -struct perf_stat *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->priv;for (i =0 ; i <3 ; i++)init_stats (&ps->res_stats[i]);
@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)int perf_evsel__alloc_stat_priv (struct perf_evsel *evsel) { - evsel->priv =zalloc (sizeof (struct perf_stat )); + evsel->priv =zalloc (sizeof (struct perf_stat_evsel ));if (evsel->priv ==NULL )return -ENOMEM ;perf_evsel__reset_stat_priv (evsel);
@@ -304,7 +304,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, struct perf_evsel *counter) {struct perf_counts_values *aggr = &counter->counts->aggr; -struct perf_stat *ps = counter->priv; +struct perf_stat_evsel *ps = counter->priv;u64 *count = counter->counts->aggr.values;int i, ret;
tools/perf/util/stat.h +1 -1
@@ -20,7 +20,7 @@ enum perf_stat_evsel_id { PERF_STAT_EVSEL_ID__MAX, }; -struct perf_stat { +struct perf_stat_evsel {struct stats res_stats[3 ];enum perf_stat_evsel_id id; };
Jiri Olsa
reviewerPATCH v4 29/57 perf stat: Add AGGR_UNSET mode
In reply to Jiri OlsaAdding AGGR_UNSET mode, so we could distinguish
unset aggr_mode in following patches.
--- tools/perf/builtin-stat.c | 5 +++++ tools/perf/util/stat.c | 1 + tools/perf/util/stat.h | 1 + 3 files changed, 7 insertions(+)
tools/perf/builtin-stat.c +5 -0
@@ -479,6 +479,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep);break ;case AGGR_GLOBAL : +case AGGR_UNSET :default :break ; }
@@ -799,6 +800,8 @@ static void print_interval(char *prefix, struct timespec *ts)case AGGR_GLOBAL :default :fprintf (output,"# time counts %*s events\n" , unit_width,"unit" ); +case AGGR_UNSET : +break ; } }
@@ -880,6 +883,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)evlist__for_each (evsel_list, counter)print_counter (counter, prefix);break ; +case AGGR_UNSET :default :break ; }
@@ -960,6 +964,7 @@ static int perf_stat_init_aggr_mode(void)case AGGR_NONE :case AGGR_GLOBAL :case AGGR_THREAD : +case AGGR_UNSET :default :break ; }
tools/perf/util/stat.c +1 -0
@@ -272,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel aggr->ena += count->ena; aggr->run += count->run; } +case AGGR_UNSET :default :break ; }
tools/perf/util/stat.h +1 -0
@@ -31,6 +31,7 @@ enum aggr_mode {AGGR_SOCKET ,AGGR_CORE ,AGGR_THREAD , + AGGR_UNSET, }; struct perf_stat_config {
Signature · 1 line
2.4.3
Re: [PATCH 29/57] perf stat: Add AGGR_UNSET mode
Em Fri, Oct 16, 2015 at 12:41:04PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding
AGGR_UNSETmode, so we could distinguish
unsetaggr_modein following patches.Signed-off-by Jiri Olsa <[email protected]>
Applied.
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Add AGGR_UNSET mode
In reply to Jiri Olsaperf stat: Add AGGR_UNSET mode
Commit-ID: 208df99ed07ca5e86ee41617e0384930fc9ca819 Gitweb: http://git.kernel.org/tip/208df99ed07ca5e86ee41617e0384930fc9ca819 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 16 Oct 2015 12:41:04 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 19 Oct 2015 18:02:07 -0300
perf stat: Add AGGR_UNSET mode
Adding AGGR_UNSET mode, so we could distinguish unset aggr_mode in following patches.
--- tools/perf/builtin-stat.c | 5 +++++ tools/perf/util/stat.c | 1 + tools/perf/util/stat.h | 1 + 3 files changed, 7 insertions(+)
tools/perf/builtin-stat.c +5 -0
@@ -479,6 +479,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep);break ;case AGGR_GLOBAL : +case AGGR_UNSET :default :break ; }
@@ -799,6 +800,8 @@ static void print_interval(char *prefix, struct timespec *ts)case AGGR_GLOBAL :default :fprintf (output,"# time counts %*s events\n" , unit_width,"unit" ); +case AGGR_UNSET : +break ; } }
@@ -880,6 +883,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)evlist__for_each (evsel_list, counter)print_counter (counter, prefix);break ; +case AGGR_UNSET :default :break ; }
@@ -960,6 +964,7 @@ static int perf_stat_init_aggr_mode(void)case AGGR_NONE :case AGGR_GLOBAL :case AGGR_THREAD : +case AGGR_UNSET :default :break ; }
tools/perf/util/stat.c +1 -0
@@ -272,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel aggr->ena += count->ena; aggr->run += count->run; } +case AGGR_UNSET :default :break ; }
tools/perf/util/stat.h +1 -0
@@ -31,6 +31,7 @@ enum aggr_mode {AGGR_SOCKET ,AGGR_CORE ,AGGR_THREAD , + AGGR_UNSET, }; struct perf_stat_config {
Jiri Olsa
reviewerPATCH v4 30/57 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=::
@@ -159,6 +162,15 @@ filter out the startup phase of the program, which is often very different. Print statistics of transactional execution if supported. +STAT RECORD +----------- +Stores stat data into perf data file. + +-o file:: +--output file:: +Output file name. + + EXAMPLES --------
tools/perf/builtin-stat.c +72 -2
116 lines not on this page · raw message
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 31/57 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
@@ -1155,6 +1155,19 @@ static const char * const recort_usage[] = { NULL, }; +static void init_features (struct perf_session *session) +{ +int feat; + +for (feat =HEADER_FIRST_FEATURE ; feat <HEADER_LAST_FEATURE ; feat++) +perf_header__set_feat (&session->header, feat); + +perf_header__clear_feat (&session->header,HEADER_BUILD_ID ); +perf_header__clear_feat (&session->header,HEADER_TRACING_DATA ); +perf_header__clear_feat (&session->header,HEADER_BRANCH_STACK ); +perf_header__clear_feat (&session->header,HEADER_AUXTRACE ); +} +static int __cmd_record (int argc,const char **argv) {struct perf_session *session;
@@ -1177,6 +1190,8 @@ static int __cmd_record(int argc, const char **argv)if (perf_stat.file.is_pipe)return -EINVAL ; +init_features (session); + session->evlist = evsel_list; perf_stat.session = session; perf_stat.record = true;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 32/57 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 | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
tools/perf/builtin-stat.c +47 -0
@@ -191,6 +191,20 @@ static inline int nsec_counter(struct perf_evsel *evsel)return 0 ; } +static int process_synthesized_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_sample *sample__maybe_unused , +struct machine *machine__maybe_unused ) +{ +if (perf_data_file__write (&perf_stat.file, event, event->header.size) <0 ) { +pr_err ("failed to write perf data, error: %m\n" ); +return -1 ; + } + + perf_stat.bytes_written += event->header.size; +return 0 ; +} +/* * Read out the results of a single counter: * do not aggregate counts across CPUs in system-wide mode
@@ -277,6 +291,35 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf workload_exec_errno = info->si_value.sival_int; } +static int perf_stat_synthesize_config (void ) +{ +int err; + + err =perf_event__synthesize_thread_map2 (NULL , evsel_list->threads, + process_synthesized_event, +NULL ); +if (err <0 ) { +pr_err ("Couldn't synthesize thread map.\n" ); +return err; + } + + err =perf_event__synthesize_cpu_map (NULL , evsel_list->cpus, + process_synthesized_event,NULL ); +if (err <0 ) { +pr_err ("Couldn't synthesize thread map.\n" ); +return err; + } + + err =perf_event__synthesize_stat_config (NULL , &stat_config, + process_synthesized_event,NULL ); +if (err <0 ) { +pr_err ("Couldn't synthesize config.\n" ); +return err; + } + +return 0 ; +} +static int __run_perf_stat (int argc,const char **argv) {int interval = stat_config.interval;
@@ -357,6 +400,10 @@ static int __run_perf_stat(int argc, const char **argv) fd, false);if (err <0 )return err; + + err =perf_stat_synthesize_config (); +if (err <0 ) +return err; }/*
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 33/57 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.
Also making perf_evlist__id_add_fd global.
--- 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
@@ -550,9 +550,9 @@ void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, evsel->id[evsel->ids++] = id; } -static int perf_evlist__id_add_fd (struct perf_evlist *evlist, -struct perf_evsel *evsel, -int cpu,int thread,int fd) +int perf_evlist__id_add_fd (struct perf_evlist *evlist, +struct perf_evsel *evsel, +int cpu,int thread,int fd) {u64 read_data[4 ] = {0 , };int id_idx =1 ;/* The first entry is the counter value */
tools/perf/util/evlist.h +3 -0
@@ -97,6 +97,9 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,void perf_evlist__id_add (struct perf_evlist *evlist,struct perf_evsel *evsel,int cpu,int thread,u64 id); +int perf_evlist__id_add_fd (struct perf_evlist *evlist, +struct perf_evsel *evsel, +int cpu,int thread,int fd);int perf_evlist__add_pollfd (struct perf_evlist *evlist,int fd);int perf_evlist__alloc_pollfd (struct perf_evlist *evlist);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 34/57 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
@@ -291,10 +291,19 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf workload_exec_errno = info->si_value.sival_int; } -static int perf_stat_synthesize_config (void ) +static int perf_stat_synthesize_config (bool is_pipe) {int err; +if (is_pipe) { + err =perf_event__synthesize_attrs (NULL , perf_stat.session, + process_synthesized_event); +if (err <0 ) { +pr_err ("Couldn't synthesize attrs.\n" ); +return err; + } + } + err =perf_event__synthesize_thread_map2 (NULL , evsel_list->threads, process_synthesized_event,NULL );
@@ -362,6 +371,7 @@ static int __run_perf_stat(int argc, const char **argv)size_t l;int status =0 ;const bool forks = (argc >0 ); +bool is_pipe =STAT_RECORD ? perf_stat.file.is_pipe : false;if (interval) { ts.tv_sec = interval /1000 ;
@@ -372,7 +382,7 @@ static int __run_perf_stat(int argc, const char **argv) }if (forks) { -if (perf_evlist__prepare_workload (evsel_list, &target, argv, false, +if (perf_evlist__prepare_workload (evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) <0 ) {perror ("failed to prepare workload" );return -1 ;
@@ -431,12 +441,17 @@ static int __run_perf_stat(int argc, const char **argv)if (STAT_RECORD ) {int err, fd =perf_data_file__fd (&perf_stat.file); - err =perf_session__write_header (perf_stat.session, evsel_list, - fd, false); +if (is_pipe) { + err =perf_header__write_pipe (perf_data_file__fd (&perf_stat.file)); + }else { + err =perf_session__write_header (perf_stat.session, evsel_list, + fd, false); + } +if (err <0 )return err; - err =perf_stat_synthesize_config (); + err =perf_stat_synthesize_config (is_pipe);if (err <0 )return err; }
@@ -963,6 +978,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)struct perf_evsel *counter;char buf[64 ], *prefix =NULL ; +/* Do not print anything if we record to the pipe. */ +if (STAT_RECORD && perf_stat.file.is_pipe) +return ; +if (interval)print_interval (prefix = buf, ts);else
@@ -1268,10 +1287,6 @@ static int __cmd_record(int argc, const char **argv)return -1 ; } -/* No pipe support ATM */ -if (perf_stat.file.is_pipe) -return -EINVAL ; -init_features (session); session->evlist = evsel_list;
@@ -1543,8 +1558,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)if (STAT_RECORD ) {int fd =perf_data_file__fd (&perf_stat.file); - perf_stat.session->header.data_size += perf_stat.bytes_written; -perf_session__write_header (perf_stat.session, evsel_list, fd, true); +if (!perf_stat.file.is_pipe) { + perf_stat.session->header.data_size += perf_stat.bytes_written; +perf_session__write_header (perf_stat.session, evsel_list, fd, true); + }perf_session__delete (perf_stat.session); }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 35/57 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
@@ -205,6 +205,18 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,return 0 ; } +#define SID (e, x, y) xyarray__entry(e->sample_id, x, y) + +static int +perf_evsel__write_stat_event (struct perf_evsel *counter,u32 cpu,u32 thread, +struct perf_counts_values *count) +{ +struct perf_sample_id *sid =SID (counter, cpu, thread); + +return perf_event__synthesize_stat (NULL , cpu, thread, sid->id, count, + process_synthesized_event,NULL ); +} +/* * Read out the results of a single counter: * do not aggregate counts across CPUs in system-wide mode
@@ -228,6 +240,13 @@ static int read_counter(struct perf_evsel *counter) count =perf_counts (counter->counts, cpu, thread);if (perf_evsel__read (counter, cpu, thread, count))return -1 ; + +if (STAT_RECORD ) { +if (perf_evsel__write_stat_event (counter, cpu, thread, count)) { +pr_err ("failed to write stat event\n" ); +return -1 ; + } + } } }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 36/57 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 | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
tools/perf/builtin-stat.c +20 -0
@@ -205,6 +205,16 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,return 0 ; } +static int write_stat_round_event (u64 time,u64 type) +{ +return perf_event__synthesize_stat_round (NULL , time, type, + process_synthesized_event, +NULL ); +} + +#define WRITE_STAT_ROUND_EVENT (time, interval) \ + write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval) +#define SID (e, x, y) xyarray__entry(e->sample_id, x, y) static int
@@ -280,6 +290,11 @@ static void process_interval(void)clock_gettime (CLOCK_MONOTONIC , &ts);diff_timespec (&rs, &ts, &ref_time); +if (STAT_RECORD ) { +if (WRITE_STAT_ROUND_EVENT (rs.tv_sec *NSECS_PER_SEC + rs.tv_nsec,INTERVAL )) +pr_err ("failed to write stat round event\n" ); + } +print_counters (&rs,0 ,NULL ); }
@@ -1577,6 +1592,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)if (STAT_RECORD ) {int fd =perf_data_file__fd (&perf_stat.file); +if (!interval) { +if (WRITE_STAT_ROUND_EVENT (walltime_nsecs_stats.max,FINAL )) +pr_err ("failed to write stat round event\n" ); + } +if (!perf_stat.file.is_pipe) { perf_stat.session->header.data_size += perf_stat.bytes_written;perf_session__write_header (perf_stat.session, evsel_list, fd, true);
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 37/57 perf stat record: Do not allow record with multiple runs mode
In reply to Jiri OlsaWe currently don't support storing multiple session in perf.data, so we can't allow -r option in stat record.
$ perf stat -e cycles -r 2 record ls Cannot use -r option with perf stat record.
--- tools/perf/builtin-stat.c | 5 +++++ 1 file changed, 5 insertions(+)
tools/perf/builtin-stat.c +5 -0
@@ -1315,6 +1315,11 @@ static int __cmd_record(int argc, const char **argv) argc =parse_options (argc, argv, options, record_usage,PARSE_OPT_STOP_AT_NON_OPTION ); +if (run_count !=1 || forever) { +pr_err ("Cannot use -r option with perf stat record.\n" ); +return -1 ; + } + session =perf_session__new (file, false,NULL );if (session ==NULL ) {pr_err ("Perf session creation failed.\n" );
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 38/57 perf stat record: Synthesize attr update events
In reply to Jiri OlsaSynthesize other events stuff not carried within
attr event - unit, scale, name.
--- tools/perf/builtin-stat.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
tools/perf/builtin-stat.c +59 -0
@@ -325,8 +325,19 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf workload_exec_errno = info->si_value.sival_int; } +static bool has_unit (struct perf_evsel *counter) +{ +return counter->unit && *counter->unit; +} + +static bool has_scale (struct perf_evsel *counter) +{ +return counter->scale !=1 ; +} +static int perf_stat_synthesize_config (bool is_pipe) { +struct perf_evsel *counter;int err;if (is_pipe) {
@@ -338,6 +349,54 @@ static int perf_stat_synthesize_config(bool is_pipe) } } +/* +* Synthesize other events stuff not carried within +* attr event - unit, scale, name +*/ +evlist__for_each (evsel_list, counter) { +if (!counter->supported) +continue ; + +/* +* Synthesize unit and scale only if it's defined. +*/ +if (has_unit (counter)) { + err =perf_event__synthesize_attr_update_unit (NULL , counter, process_synthesized_event); +if (err <0 ) { +pr_err ("Couldn't synthesize evsel unit.\n" ); +return err; + } + } + +if (has_scale (counter)) { + err =perf_event__synthesize_attr_update_scale (NULL , counter, process_synthesized_event); +if (err <0 ) { +pr_err ("Couldn't synthesize evsel scale.\n" ); +return err; + } + } + +if (counter->own_cpus) { + err =perf_event__synthesize_attr_update_cpus (NULL , counter, process_synthesized_event); +if (err <0 ) { +pr_err ("Couldn't synthesize evsel scale.\n" ); +return err; + } + } + +/* +* Name is needed only for pipe output, +* perf.data carries event names. +*/ +if (is_pipe) { + err =perf_event__synthesize_attr_update_name (NULL , counter, process_synthesized_event); +if (err <0 ) { +pr_err ("Couldn't synthesize evsel name.\n" ); +return err; + } + } + } + err =perf_event__synthesize_thread_map2 (NULL , evsel_list->threads, process_synthesized_event,NULL );
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 39/57 perf tools: Make cpu_map__build_map global
In reply to Jiri OlsaWe'll need to call it from perf stat in following patches.
--- tools/perf/util/cpumap.c | 4 ++-- tools/perf/util/cpumap.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)
tools/perf/util/cpumap.c +2 -2
@@ -317,8 +317,8 @@ static int cmp_ids(const void *a, const void *b)return *(int *)a - *(int *)b; } -static int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, -int (*f)(struct cpu_map *map,int cpu)) +int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, +int (*f)(struct cpu_map *map,int cpu)) {struct cpu_map *c;int nr = cpus->nr;
tools/perf/util/cpumap.h +2 -0
@@ -89,4 +89,6 @@ static inline int cpu__get_node(int cpu) return cpunode_map[cpu]; } +int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, +int (*f)(struct cpu_map *map,int cpu));#endif /* __PERF_CPUMAP_H */
Signature · 1 line
2.4.3
Re: [PATCH 39/57] perf tools: Make cpu_map__build_map global
Em Fri, Oct 16, 2015 at 12:41:14PM +0200, Jiri Olsa escreveu:
Quoted 4 lines
We'll need to call it from perf stat in following patches.
Signed-off-by Jiri Olsa <[email protected]>
Applied
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf cpu_map: Make cpu_map__build_map global
In reply to Jiri Olsaperf cpu_map: Make cpu_map__build_map global
Commit-ID: f1cbb8f35719e36803f226d1bbf08ac12cedcd76 Gitweb: http://git.kernel.org/tip/f1cbb8f35719e36803f226d1bbf08ac12cedcd76 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 16 Oct 2015 12:41:14 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 19 Oct 2015 18:03:03 -0300
perf cpu_map: Make cpu_map__build_map global
We'll need to call it from perf stat in the stat_script patchkit
--- tools/perf/util/cpumap.c | 4 ++-- tools/perf/util/cpumap.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)
tools/perf/util/cpumap.c +2 -2
@@ -258,8 +258,8 @@ static int cmp_ids(const void *a, const void *b)return *(int *)a - *(int *)b; } -static int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, -int (*f)(struct cpu_map *map,int cpu)) +int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, +int (*f)(struct cpu_map *map,int cpu)) {struct cpu_map *c;int nr = cpus->nr;
tools/perf/util/cpumap.h +2 -0
@@ -87,4 +87,6 @@ static inline int cpu__get_node(int cpu) return cpunode_map[cpu]; } +int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, +int (*f)(struct cpu_map *map,int cpu));#endif /* __PERF_CPUMAP_H */
Jiri Olsa
reviewerPATCH v4 40/57 perf tools: Add data arg to cpu_map__build_map callback
In reply to Jiri OlsaAdding data arg to cpu_map__build_map callback, so we could pass data along to the callback. It'll be needed in following patches to retrieve topology info from perf.data.
--- tools/perf/builtin-stat.c | 14 ++++++++++++-- tools/perf/tests/topology.c | 4 ++-- tools/perf/util/cpumap.c | 15 ++++++++------- tools/perf/util/cpumap.h | 7 ++++--- tools/perf/util/stat.c | 2 +- 5 files changed, 27 insertions(+), 15 deletions(-)
tools/perf/builtin-stat.c +12 -2
@@ -1158,6 +1158,16 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,return 0 ; } +static int perf_stat__get_socket (struct cpu_map *map,int cpu) +{ +return cpu_map__get_socket (map, cpu,NULL ); +} + +static int perf_stat__get_core (struct cpu_map *map,int cpu) +{ +return cpu_map__get_core (map, cpu,NULL ); +} +static int perf_stat_init_aggr_mode (void ) {switch (stat_config.aggr_mode) {
@@ -1166,14 +1176,14 @@ static int perf_stat_init_aggr_mode(void)perror ("cannot build socket map" );return -1 ; } - aggr_get_id = cpu_map__get_socket; + aggr_get_id = perf_stat__get_socket;break ;case AGGR_CORE :if (cpu_map__build_core_map (evsel_list->cpus, &aggr_map)) {perror ("cannot build core map" );return -1 ; } - aggr_get_id = cpu_map__get_core; + aggr_get_id = perf_stat__get_core;break ;case AGGR_NONE :case AGGR_GLOBAL :
tools/perf/tests/topology.c +2 -2
@@ -73,10 +73,10 @@ static int check_cpu_topology(char *path, struct cpu_map *map)for (i =0 ; i < map->nr; i++) {TEST_ASSERT_VAL ("Core ID doesn't match" , - (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core (map, i) &0xffff ))); + (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core (map, i,NULL ) &0xffff )));TEST_ASSERT_VAL ("Socket ID doesn't match" , - (session->header.env.cpu[map->map[i]].socket_id ==cpu_map__get_socket (map, i))); + (session->header.env.cpu[map->map[i]].socket_id ==cpu_map__get_socket (map, i,NULL ))); }perf_session__delete (session);
tools/perf/util/cpumap.c +8 -7
@@ -300,7 +300,7 @@ int cpu_map__get_socket_id(int cpu)return ret ?: value; } -int cpu_map__get_socket (struct cpu_map *map,int idx) +int cpu_map__get_socket (struct cpu_map *map,int idx,void *data__maybe_unused ) {int cpu;
@@ -318,7 +318,8 @@ static int cmp_ids(const void *a, const void *b) }int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, -int (*f)(struct cpu_map *map,int cpu)) +int (*f)(struct cpu_map *map,int cpu,void *data), +void *data) {struct cpu_map *c;int nr = cpus->nr;
@@ -330,7 +331,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,return -1 ;for (cpu =0 ; cpu < nr; cpu++) { - s1 =f (cpus, cpu); + s1 =f (cpus, cpu, data);for (s2 =0 ; s2 < c->nr; s2++) {if (s1 == c->map[s2])break ;
@@ -354,7 +355,7 @@ int cpu_map__get_core_id(int cpu)return ret ?: value; } -int cpu_map__get_core (struct cpu_map *map,int idx) +int cpu_map__get_core (struct cpu_map *map,int idx,void *data) {int cpu, s;
@@ -365,7 +366,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx) cpu =cpu_map__get_core_id (cpu); - s =cpu_map__get_socket (map, idx); + s =cpu_map__get_socket (map, idx, data);if (s ==-1 )return -1 ;
@@ -380,12 +381,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx)int cpu_map__build_socket_map (struct cpu_map *cpus,struct cpu_map **sockp) { -return cpu_map__build_map (cpus, sockp, cpu_map__get_socket); +return cpu_map__build_map (cpus, sockp, cpu_map__get_socket,NULL ); }int cpu_map__build_core_map (struct cpu_map *cpus,struct cpu_map **corep) { -return cpu_map__build_map (cpus, corep, cpu_map__get_core); +return cpu_map__build_map (cpus, corep, cpu_map__get_core,NULL ); }/* setup simple routines to easily access node numbers given a cpu number */
tools/perf/util/cpumap.h +4 -3
@@ -21,9 +21,9 @@ struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);struct cpu_map *cpu_map__read (FILE *file);size_t cpu_map__fprintf (struct cpu_map *map,FILE *fp);int cpu_map__get_socket_id (int cpu); -int cpu_map__get_socket (struct cpu_map *map,int idx); +int cpu_map__get_socket (struct cpu_map *map,int idx,void *data);int cpu_map__get_core_id (int cpu); -int cpu_map__get_core (struct cpu_map *map,int idx); +int cpu_map__get_core (struct cpu_map *map,int idx,void *data);int cpu_map__build_socket_map (struct cpu_map *cpus,struct cpu_map **sockp);int cpu_map__build_core_map (struct cpu_map *cpus,struct cpu_map **corep);
@@ -90,5 +90,6 @@ static inline int cpu__get_node(int cpu) }int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, -int (*f)(struct cpu_map *map,int cpu)); +int (*f)(struct cpu_map *map,int cpu,void *data), +void *data);#endif /* __PERF_CPUMAP_H */
tools/perf/util/stat.c +1 -1
@@ -230,7 +230,7 @@ static int check_per_pkg(struct perf_evsel *counter,if (!(vals->run && vals->ena))return 0 ; - s =cpu_map__get_socket (cpus, cpu); + s =cpu_map__get_socket (cpus, cpu,NULL );if (s <0 )return -1 ;
Signature · 1 line
2.4.3
Re: [PATCH 40/57] perf tools: Add data arg to cpu_map__build_map callback
Em Fri, Oct 16, 2015 at 12:41:15PM +0200, Jiri Olsa escreveu:
Quoted 6 lines
Adding data arg to
cpu_map__build_mapcallback, so we could pass data along to the callback. It'll be needed in following patches to retrieve topology info from perf.data.Signed-off-by Jiri Olsa <[email protected]>
Applied
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf cpu_map: Add data arg to cpu_map__build_map callback
In reply to Jiri Olsaperf cpu_map: Add data arg to cpu_map__build_map callback
Commit-ID: 1fe7a30028eeccd92e6fccfbeb8c5c3811b11b64 Gitweb: http://git.kernel.org/tip/1fe7a30028eeccd92e6fccfbeb8c5c3811b11b64 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 16 Oct 2015 12:41:15 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 19 Oct 2015 18:04:01 -0300
perf cpu_map: Add data arg to cpu_map__build_map callback
Adding data arg to cpu_map__build_map callback, so we could pass data along to the callback. It'll be needed in following patches to retrieve topology info from perf.data.
--- tools/perf/builtin-stat.c | 14 ++++++++++++-- tools/perf/tests/topology.c | 4 ++-- tools/perf/util/cpumap.c | 15 ++++++++------- tools/perf/util/cpumap.h | 7 ++++--- tools/perf/util/stat.c | 2 +- 5 files changed, 27 insertions(+), 15 deletions(-)
tools/perf/builtin-stat.c +12 -2
@@ -944,6 +944,16 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,return 0 ; } +static int perf_stat__get_socket (struct cpu_map *map,int cpu) +{ +return cpu_map__get_socket (map, cpu,NULL ); +} + +static int perf_stat__get_core (struct cpu_map *map,int cpu) +{ +return cpu_map__get_core (map, cpu,NULL ); +} +static int perf_stat_init_aggr_mode (void ) {switch (stat_config.aggr_mode) {
@@ -952,14 +962,14 @@ static int perf_stat_init_aggr_mode(void)perror ("cannot build socket map" );return -1 ; } - aggr_get_id = cpu_map__get_socket; + aggr_get_id = perf_stat__get_socket;break ;case AGGR_CORE :if (cpu_map__build_core_map (evsel_list->cpus, &aggr_map)) {perror ("cannot build core map" );return -1 ; } - aggr_get_id = cpu_map__get_core; + aggr_get_id = perf_stat__get_core;break ;case AGGR_NONE :case AGGR_GLOBAL :
tools/perf/tests/topology.c +2 -2
@@ -73,10 +73,10 @@ static int check_cpu_topology(char *path, struct cpu_map *map)for (i =0 ; i < map->nr; i++) {TEST_ASSERT_VAL ("Core ID doesn't match" , - (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core (map, i) &0xffff ))); + (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core (map, i,NULL ) &0xffff )));TEST_ASSERT_VAL ("Socket ID doesn't match" , - (session->header.env.cpu[map->map[i]].socket_id ==cpu_map__get_socket (map, i))); + (session->header.env.cpu[map->map[i]].socket_id ==cpu_map__get_socket (map, i,NULL ))); }perf_session__delete (session);
tools/perf/util/cpumap.c +8 -7
@@ -241,7 +241,7 @@ int cpu_map__get_socket_id(int cpu)return ret ?: value; } -int cpu_map__get_socket (struct cpu_map *map,int idx) +int cpu_map__get_socket (struct cpu_map *map,int idx,void *data__maybe_unused ) {int cpu;
@@ -259,7 +259,8 @@ static int cmp_ids(const void *a, const void *b) }int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, -int (*f)(struct cpu_map *map,int cpu)) +int (*f)(struct cpu_map *map,int cpu,void *data), +void *data) {struct cpu_map *c;int nr = cpus->nr;
@@ -271,7 +272,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,return -1 ;for (cpu =0 ; cpu < nr; cpu++) { - s1 =f (cpus, cpu); + s1 =f (cpus, cpu, data);for (s2 =0 ; s2 < c->nr; s2++) {if (s1 == c->map[s2])break ;
@@ -295,7 +296,7 @@ int cpu_map__get_core_id(int cpu)return ret ?: value; } -int cpu_map__get_core (struct cpu_map *map,int idx) +int cpu_map__get_core (struct cpu_map *map,int idx,void *data) {int cpu, s;
@@ -306,7 +307,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx) cpu =cpu_map__get_core_id (cpu); - s =cpu_map__get_socket (map, idx); + s =cpu_map__get_socket (map, idx, data);if (s ==-1 )return -1 ;
@@ -321,12 +322,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx)int cpu_map__build_socket_map (struct cpu_map *cpus,struct cpu_map **sockp) { -return cpu_map__build_map (cpus, sockp, cpu_map__get_socket); +return cpu_map__build_map (cpus, sockp, cpu_map__get_socket,NULL ); }int cpu_map__build_core_map (struct cpu_map *cpus,struct cpu_map **corep) { -return cpu_map__build_map (cpus, corep, cpu_map__get_core); +return cpu_map__build_map (cpus, corep, cpu_map__get_core,NULL ); }/* setup simple routines to easily access node numbers given a cpu number */
tools/perf/util/cpumap.h +4 -3
@@ -19,9 +19,9 @@ struct cpu_map *cpu_map__dummy_new(void);struct cpu_map *cpu_map__read (FILE *file);size_t cpu_map__fprintf (struct cpu_map *map,FILE *fp);int cpu_map__get_socket_id (int cpu); -int cpu_map__get_socket (struct cpu_map *map,int idx); +int cpu_map__get_socket (struct cpu_map *map,int idx,void *data);int cpu_map__get_core_id (int cpu); -int cpu_map__get_core (struct cpu_map *map,int idx); +int cpu_map__get_core (struct cpu_map *map,int idx,void *data);int cpu_map__build_socket_map (struct cpu_map *cpus,struct cpu_map **sockp);int cpu_map__build_core_map (struct cpu_map *cpus,struct cpu_map **corep);
@@ -88,5 +88,6 @@ static inline int cpu__get_node(int cpu) }int cpu_map__build_map (struct cpu_map *cpus,struct cpu_map **res, -int (*f)(struct cpu_map *map,int cpu)); +int (*f)(struct cpu_map *map,int cpu,void *data), +void *data);#endif /* __PERF_CPUMAP_H */
tools/perf/util/stat.c +1 -1
@@ -230,7 +230,7 @@ static int check_per_pkg(struct perf_evsel *counter,if (!(vals->run && vals->ena))return 0 ; - s =cpu_map__get_socket (cpus, cpu); + s =cpu_map__get_socket (cpus, cpu,NULL );if (s <0 )return -1 ;
Jiri Olsa
reviewerPATCH v4 41/57 perf stat report: Cache aggregated map entries in extra cpumap
In reply to Jiri OlsaCurrently any time we need to access socket or core id for given cpu, we access the sysfs topology file.
Adding cpus_aggr_map cpu_map to cache those entries.
--- tools/perf/builtin-stat.c | 60 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-)
tools/perf/builtin-stat.c +56 -4
@@ -101,6 +101,8 @@ static struct target target = { .uid = UINT_MAX, }; +typedef int (*aggr_get_id_t )(struct cpu_map *m,int cpu); +static int run_count =1 ;static bool no_inherit = false;static volatile pid_t child_pid =-1 ;
@@ -120,7 +122,7 @@ static unsigned int unit_width = 4; /* strlen("unit") */static bool forever = false;static struct timespec ref_time;static struct cpu_map *aggr_map; -static int (*aggr_get_id)(struct cpu_map *m,int cpu); +static aggr_get_id_t aggr_get_id;struct perf_stat {bool record;
@@ -1158,6 +1160,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,return 0 ; } +static int perf_stat__get_socket (struct cpu_map *map,int cpu) {return cpu_map__get_socket (map, cpu,NULL );
@@ -1168,22 +1171,63 @@ static int perf_stat__get_core(struct cpu_map *map, int cpu)return cpu_map__get_core (map, cpu,NULL ); } +static int cpu_map__get_max (struct cpu_map *map) +{ +int i, max =-1 ; + +for (i =0 ; i < map->nr; i++) { +if (map->map[i] > max) + max = map->map[i]; + } + +return max; +} + +static struct cpu_map *cpus_aggr_map; + +static int perf_stat__get_aggr (aggr_get_id_t get_id,struct cpu_map *map,int idx) +{ +int cpu; + +if (idx > map->nr) +return -1 ; + + cpu = map->map[idx]; + +if (cpus_aggr_map->map[cpu] ==-1 ) + cpus_aggr_map->map[cpu] =get_id (map, idx); + +return cpus_aggr_map->map[cpu]; +} + +static int perf_stat__get_socket_cached (struct cpu_map *map,int idx) +{ +return perf_stat__get_aggr (perf_stat__get_socket, map, idx); +} + +static int perf_stat__get_core_cached (struct cpu_map *map,int idx) +{ +return perf_stat__get_aggr (perf_stat__get_core, map, idx); +} +static int perf_stat_init_aggr_mode (void ) { +int nr; +switch (stat_config.aggr_mode) {case AGGR_SOCKET :if (cpu_map__build_socket_map (evsel_list->cpus, &aggr_map)) {perror ("cannot build socket map" );return -1 ; } - aggr_get_id = perf_stat__get_socket; + aggr_get_id = perf_stat__get_socket_cached;break ;case AGGR_CORE :if (cpu_map__build_core_map (evsel_list->cpus, &aggr_map)) {perror ("cannot build core map" );return -1 ; } - aggr_get_id = perf_stat__get_core; + aggr_get_id = perf_stat__get_core_cached;break ;case AGGR_NONE :case AGGR_GLOBAL :
@@ -1192,7 +1236,15 @@ static int perf_stat_init_aggr_mode(void)default :break ; } -return 0 ; + +/* +* The evsel_list->cpus is the base we operate on, +* taking the highest cpu number to be the size of +* the aggregation translate cpumap. +*/ + nr =cpu_map__get_max (evsel_list->cpus); + cpus_aggr_map =cpu_map__empty_new (nr +1 ); +return cpus_aggr_map ?0 : -ENOMEM ; }/*
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 42/57 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 | 61 +++++++++++++++++++++++++++++++--- tools/perf/util/session.c | 3 ++ 3 files changed, 72 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:
@@ -170,6 +174,14 @@ Stores stat data into perf data file. --output file:: Output file name. +STAT REPORT +----------- +Reads and reports stat data from perf data file. + +-i file:: +--input file:: +Input file name. + EXAMPLES --------
tools/perf/builtin-stat.c +57 -4
97 lines not on this page · raw message
tools/perf/util/session.c +3 -0
@@ -37,6 +37,9 @@ static int perf_session__open(struct perf_session *session)if (perf_data_file__is_pipe (file))return 0 ; +if (perf_header__has_feat (&session->header,HEADER_STAT )) +return 0 ; +if (!perf_evlist__valid_sample_type (session->evlist)) {pr_err ("non matching sample_type" );return -1 ;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 43/57 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 | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+)
tools/perf/builtin-stat.c +62 -0
@@ -132,6 +132,9 @@ struct perf_stat {struct perf_session *session;u64 bytes_written;struct perf_tool tool; +bool maps_allocated; +struct cpu_map *cpus; +struct thread_map *threads; };static struct perf_stat perf_stat;
@@ -1458,6 +1461,63 @@ static int __cmd_record(int argc, const char **argv)return argc; } +static int set_maps (struct perf_stat *stat) +{ +if (!stat->cpus || !stat->threads) +return 0 ; + +if (WARN_ONCE (stat->maps_allocated,"stats double allocation\n" )) +return -EINVAL ; + +perf_evlist__set_maps (evsel_list, stat->cpus, stat->threads); + +if (perf_evlist__alloc_stats (evsel_list, true)) +return -ENOMEM ; + + stat->maps_allocated = true; +return 0 ; +} + +static +int process_thread_map_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ + struct perf_stat *stat = container_of(tool, struct perf_stat, tool); + +if (stat->threads) { +pr_warning ("Extra thread map event, ignoring.\n" ); +return 0 ; + } + + stat->threads =thread_map__new_event (&event->thread_map); +if (!stat->threads) +return -ENOMEM ; + +return set_maps (stat); +} + +static +int process_cpu_map_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ + struct perf_stat *stat = container_of(tool, struct perf_stat, tool); +struct cpu_map *cpus; + +if (stat->cpus) { +pr_warning ("Extra cpu map event, ignoring.\n" ); +return 0 ; + } + + cpus =cpu_map__new_data (&event->cpu_map.data); +if (!cpus) +return -ENOMEM ; + + stat->cpus = cpus; +return set_maps (stat); +} +static const char *const report_usage[] = {"perf stat report [<options>]" ,NULL ,
@@ -1466,6 +1526,8 @@ static const char * const report_usage[] = {static struct perf_stat perf_stat = { .tool = { .attr = perf_event__process_attr, + .thread_map = process_thread_map_event, + .cpu_map = process_cpu_map_event, }, };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 44/57 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
@@ -1461,6 +1461,15 @@ static int __cmd_record(int argc, const char **argv)return argc; } +static +int process_stat_config_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ +perf_event__read_stat_config (&stat_config, &event->stat_config); +return 0 ; +} +static int set_maps (struct perf_stat *stat) {if (!stat->cpus || !stat->threads)
@@ -1528,6 +1537,7 @@ static struct perf_stat perf_stat = { .attr = perf_event__process_attr, .thread_map = process_thread_map_event, .cpu_map = process_cpu_map_event, + .stat_config = process_stat_config_event, }, };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 45/57 perf stat report: Add support to initialize aggr_map from file
In reply to Jiri OlsaUsing perf.data's perf_env data to initialize
aggregate config.
--- tools/perf/builtin-stat.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+)
tools/perf/builtin-stat.c +103 -0
@@ -1253,6 +1253,101 @@ static int perf_stat_init_aggr_mode(void)return cpus_aggr_map ?0 : -ENOMEM ; } +static inline int perf_env__get_cpu (struct perf_env *env,struct cpu_map *map,int idx) +{ +int cpu; + +if (idx > map->nr) +return -1 ; + + cpu = map->map[idx]; + +if (cpu >= env->nr_cpus_online) +return -1 ; + +return cpu; +} + +static int perf_env__get_socket (struct cpu_map *map,int idx,void *data) +{ +struct perf_env *env = data; +int cpu =perf_env__get_cpu (env, map, idx); + +return cpu ==-1 ?-1 : env->cpu[cpu].socket_id; +} + +static int perf_env__get_core (struct cpu_map *map,int idx,void *data) +{ +struct perf_env *env = data; +int core =-1 , cpu =perf_env__get_cpu (env, map, idx); + +if (cpu !=-1 ) { +int socket = env->cpu[cpu].socket_id; + +/* +* Encode socket in upper 16 bits +* core_id is relative to socket, and +* we need a global id. So we combine +* socket + core id. +*/ + core = (socket <<16 ) | (env->cpu[cpu].core_id &0xffff ); + } + +return core; +} + +static int perf_env__build_socket_map (struct perf_env *env,struct cpu_map *cpus, +struct cpu_map **sockp) +{ +return cpu_map__build_map (cpus, sockp, perf_env__get_socket, env); +} + +static int perf_env__build_core_map (struct perf_env *env,struct cpu_map *cpus, +struct cpu_map **corep) +{ +return cpu_map__build_map (cpus, corep, perf_env__get_core, env); +} + +static int perf_stat__get_socket_file (struct cpu_map *map,int idx) +{ +return perf_env__get_socket (map, idx, &perf_stat.session->header.env); +} + +static int perf_stat__get_core_file (struct cpu_map *map,int idx) +{ +return perf_env__get_core (map, idx, &perf_stat.session->header.env); +} + +static int perf_stat_init_aggr_mode_file (struct perf_stat *stat) +{ +struct perf_env *env = &stat->session->header.env; + +switch (stat_config.aggr_mode) { +case AGGR_SOCKET : +if (perf_env__build_socket_map (env, evsel_list->cpus, &aggr_map)) { +perror ("cannot build socket map" ); +return -1 ; + } + aggr_get_id = perf_stat__get_socket_file; +break ; +case AGGR_CORE : +if (perf_env__build_core_map (env, evsel_list->cpus, &aggr_map)) { +perror ("cannot build core map" ); +return -1 ; + } + aggr_get_id = perf_stat__get_core_file; +break ; +case AGGR_NONE : +case AGGR_GLOBAL : +case AGGR_THREAD : +case AGGR_UNSET : +default : +break ; + } + +return 0 ; +} +/* * Add default attributes, if there were no attributes specified or * if -d/--detailed, -d -d or -d -d -d is used:
@@ -1466,7 +1561,15 @@ int process_stat_config_event(struct perf_tool *tool __maybe_unused,union perf_event *event, struct perf_session *session __maybe_unused) { + struct perf_stat *stat = container_of(tool, struct perf_stat, tool); +perf_event__read_stat_config (&stat_config, &event->stat_config); + +if (perf_stat.file.is_pipe) +perf_stat_init_aggr_mode (); +else +perf_stat_init_aggr_mode_file (stat); +return 0 ; }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 46/57 perf stat report: Process stat and stat round events
In reply to Jiri OlsaAdding processing of stat and stat round events.
The stat data com in stat events, using generic function process_stat_round_event to store data under perf_evsel object.
The stat-round events comes each interval or as last event in non interval mode. The function process_stat_round_event process stored data for each perf_evsel object and print it out.
--- tools/perf/builtin-stat.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
tools/perf/builtin-stat.c +28 -0
@@ -1556,6 +1556,32 @@ static int __cmd_record(int argc, const char **argv)return argc; } +static int process_stat_round_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session) +{ +struct stat_round_event *round = &event->stat_round; +struct perf_evsel *counter; +struct timespec tsh, *ts =NULL ; +const char **argv = session->header.env.cmdline_argv; +int argc = session->header.env.nr_cmdline; + +evlist__for_each (evsel_list, counter) +perf_stat_process_counter (&stat_config, counter); + +if (round->type ==PERF_STAT_ROUND_TYPE__FINAL ) +update_stats (&walltime_nsecs_stats, round->time); + +if (stat_config.interval && round->time) { + tsh.tv_sec = round->time /NSECS_PER_SEC ; + tsh.tv_nsec = round->time %NSECS_PER_SEC ; + ts = &tsh; + } + +print_counters (ts, argc, argv); +return 0 ; +} + static int process_stat_config_event(struct perf_tool *tool __maybe_unused, union perf_event *event,
@@ -1641,6 +1667,8 @@ static struct perf_stat perf_stat = { .thread_map = process_thread_map_event, .cpu_map = process_cpu_map_event, .stat_config = process_stat_config_event, + .stat = perf_event__process_stat_event, + .stat_round = process_stat_round_event, }, };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 47/57 perf stat report: Process attr update events
In reply to Jiri OlsaAdding processing of attr update events, so perf stat report can store additional info for events - unit,scale,name.
--- tools/perf/builtin-stat.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/builtin-stat.c +1 -0
@@ -1664,6 +1664,7 @@ static const char * const report_usage[] = {static struct perf_stat perf_stat = { .tool = { .attr = perf_event__process_attr, + .attr_update = perf_event__process_attr_update, .thread_map = process_thread_map_event, .cpu_map = process_cpu_map_event, .stat_config = process_stat_config_event,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 48/57 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
@@ -1796,6 +1796,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 )
@@ -1843,13 +1850,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 v4 49/57 perf stat report: Allow to override aggr_mode
In reply to Jiri OlsaAllowing to override record aggr_mode. It's possible to use perf stat like:
$ perf stat report -A $ perf stat report --per-core $ perf stat report --per-socket
To customize the recorded aggregate mode regardless what was used during the stat record command.
--- tools/perf/Documentation/perf-stat.txt | 10 ++++++++++ tools/perf/builtin-stat.c | 17 +++++++++++++++++ 2 files changed, 27 insertions(+)
tools/perf/Documentation/perf-stat.txt +10 -0
@@ -182,6 +182,16 @@ Reads and reports stat data from perf data file. --input file:: Input file name. +--per-socket:: +Aggregate counts per processor socket for system-wide mode measurements. + +--per-core:: +Aggregate counts per physical processor for system-wide mode measurements. + +-A:: +--no-aggr:: +Do not aggregate counts across all monitored CPUs. + EXAMPLES --------
tools/perf/builtin-stat.c +17 -0
@@ -135,6 +135,7 @@ struct perf_stat {bool maps_allocated;struct cpu_map *cpus;struct thread_map *threads; +enum aggr_mode aggr_mode; };static struct perf_stat perf_stat;
@@ -1591,6 +1592,15 @@ int process_stat_config_event(struct perf_tool *tool __maybe_unused,perf_event__read_stat_config (&stat_config, &event->stat_config); +if (cpu_map__empty (stat->cpus)) { +if (stat->aggr_mode !=AGGR_UNSET ) +pr_warning ("warning: processing task data, aggregation mode not set\n" ); +return 0 ; + } + +if (stat->aggr_mode !=AGGR_UNSET ) + stat_config.aggr_mode = stat->aggr_mode; +if (perf_stat.file.is_pipe)perf_stat_init_aggr_mode ();else
@@ -1671,6 +1681,7 @@ static struct perf_stat perf_stat = { .stat = perf_event__process_stat_event, .stat_round = process_stat_round_event, }, + .aggr_mode = AGGR_UNSET, };static int __cmd_report (int argc,const char **argv)
@@ -1678,6 +1689,12 @@ static int __cmd_report(int argc, const char **argv)struct perf_session *session;const struct option options[] = {OPT_STRING ('i' ,"input" , &input_name,"file" ,"input file name" ), +OPT_SET_UINT (0 ,"per-socket" , &perf_stat.aggr_mode, +"aggregate counts per processor socket" ,AGGR_SOCKET ), +OPT_SET_UINT (0 ,"per-core" , &perf_stat.aggr_mode, +"aggregate counts per physical processor core" ,AGGR_CORE ), +OPT_SET_UINT ('A' ,"no-aggr" , &perf_stat.aggr_mode, +"disable CPU count aggregation" ,AGGR_NONE ),OPT_END () };struct stat st;
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 50/57 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
@@ -686,7 +686,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,set_print_ip_opts (&evsel->attr); -return perf_evsel__check_attr (evsel, scr->session); +if (evsel->attr.sample_type) + err =perf_evsel__check_attr (evsel, scr->session); + +return err; } static int process_comm_event(struct perf_tool *tool,
Signature · 1 line
2.4.3
Re: [PATCH 50/57] perf script: Check output fields only for samples
Em Fri, Oct 16, 2015 at 12:41:25PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
There's no need to check sampling output fields
for events withoutperf_event_attr::sample_type
field set.
Applied.
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf script: Check output fields only for samples
In reply to Jiri Olsaperf script: Check output fields only for samples
Commit-ID: d2b5a315ae84d235f00761468885c466f81d7805 Gitweb: http://git.kernel.org/tip/d2b5a315ae84d235f00761468885c466f81d7805 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 16 Oct 2015 12:41:25 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 19 Oct 2015 18:05:59 -0300
perf script: Check output fields only for samples
There'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
@@ -686,7 +686,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,set_print_ip_opts (&evsel->attr); -return perf_evsel__check_attr (evsel, scr->session); +if (evsel->attr.sample_type) + err =perf_evsel__check_attr (evsel, scr->session); + +return err; } static int process_comm_event(struct perf_tool *tool,
Jiri Olsa
reviewerPATCH v4 51/57 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 | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)
tools/perf/builtin-script.c +67 -0
@@ -18,7 +18,11 @@#include "util/sort.h" #include "util/data.h" #include "util/auxtrace.h" +#include "util/cpumap.h" +#include "util/thread_map.h" +#include "util/stat.h" #include <linux/bitmap.h> +#include "asm/bug.h" static char const *script_name;static char const *generate_script_lang;
@@ -659,6 +663,9 @@ struct perf_script {bool show_task_events;bool show_mmap_events;bool show_switch_events; +bool allocated; +struct cpu_map *cpus; +struct thread_map *threads; }; static int process_attr(struct perf_tool *tool, union perf_event *event,
@@ -1615,6 +1622,63 @@ static void script__setup_sample_type(struct perf_script *script) } } +static int set_maps (struct perf_script *script) +{ +struct perf_evlist *evlist = script->session->evlist; + +if (!script->cpus || !script->threads) +return 0 ; + +if (WARN_ONCE (script->allocated,"stats double allocation\n" )) +return -EINVAL ; + +perf_evlist__set_maps (evlist, script->cpus, script->threads); + +if (perf_evlist__alloc_stats (evlist, true)) +return -ENOMEM ; + + script->allocated = true; +return 0 ; +} + +static +int process_thread_map_event (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ + struct perf_script *script = container_of(tool, struct perf_script, tool); + +if (script->threads) { +pr_warning ("Extra thread map event, ignoring.\n" ); +return 0 ; + } + + script->threads =thread_map__new_event (&event->thread_map); +if (!script->threads) +return -ENOMEM ; + +return set_maps (script); +} + +static +int process_cpu_map_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ + struct perf_script *script = container_of(tool, struct perf_script, tool); + +if (script->cpus) { +pr_warning ("Extra cpu map event, ignoring.\n" ); +return 0 ; + } + + script->cpus =cpu_map__new_data (&event->cpu_map.data); +if (!script->cpus) +return -ENOMEM ; + +return set_maps (script); +} +int cmd_script (int argc,const char **argv,const char *prefix__maybe_unused ) {bool show_full_info = false;
@@ -1643,6 +1707,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__process_auxtrace_info, .auxtrace = perf_event__process_auxtrace, .auxtrace_error = perf_event__process_auxtrace_error, + .thread_map = process_thread_map_event, + .cpu_map = process_cpu_map_event, .ordered_events = true, .ordering_requires_timestamps = true, },
@@ -1996,6 +2062,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)flush_scripting (); out_delete: +perf_evlist__free_stats (session->evlist);perf_session__delete (session);if (script_started)
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 52/57 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 | 10 ++++++++++ 1 file changed, 10 insertions(+)
tools/perf/builtin-script.c +10 -0
@@ -36,6 +36,7 @@ static bool print_flags;static bool nanosecs;static const char *cpu_list; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); +static struct perf_stat_config stat_config;unsigned int scripting_max_stack =PERF_MAX_STACK_DEPTH ;
@@ -1622,6 +1623,14 @@ static void script__setup_sample_type(struct perf_script *script) } } +static int process_stat_config_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ +perf_event__read_stat_config (&stat_config, &event->stat_config); +return 0 ; +} +static int set_maps (struct perf_script *script) {struct perf_evlist *evlist = script->session->evlist;
@@ -1707,6 +1716,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__process_auxtrace_info, .auxtrace = perf_event__process_auxtrace, .auxtrace_error = perf_event__process_auxtrace_error, + .stat_config = process_stat_config_event, .thread_map = process_thread_map_event, .cpu_map = process_cpu_map_event, .ordered_events = true,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 53/57 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
@@ -65,6 +65,7 @@ int tracing_data_put(struct tracing_data *tdata);struct addr_location ;struct perf_session ; +struct perf_stat_config ;struct scripting_ops {const char *name;
@@ -75,6 +76,9 @@ struct scripting_ops {struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al); +void (*process_stat) (struct perf_stat_config *config, +struct perf_evsel *evsel,u64 time); +void (*process_stat_interval) (u64 time);int (*generate_script) (struct pevent *pevent,const char *outfile); };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 54/57 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
@@ -205,6 +205,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,struct perf_event_attr *attr = &evsel->attr;bool allow_user_set; +if (perf_header__has_feat (&session->header,HEADER_STAT )) +return 0 ; + allow_user_set =perf_header__has_feat (&session->header,HEADER_AUXTRACE );
@@ -568,6 +571,14 @@ static void process_event(union perf_event *event, struct perf_sample *sample,printf ("\n" ); } +static void process_stat (struct perf_stat_config *config__maybe_unused , +struct perf_evsel *evsel__maybe_unused , +u64 time__maybe_unused ) +{ +} + +static void process_stat_interval (u64 time__maybe_unused ) { } +static int default_start_script (const char *script__maybe_unused ,int argc__maybe_unused ,const char **argv__maybe_unused )
@@ -596,6 +607,8 @@ static struct scripting_ops default_scripting_ops = { .flush_script = default_flush_script, .stop_script = default_stop_script, .process_event = process_event, + .process_stat = process_stat, + .process_stat_interval = process_stat_interval, .generate_script = default_generate_script, };
@@ -1623,6 +1636,22 @@ static void script__setup_sample_type(struct perf_script *script) } } +static int process_stat_round_event (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session) +{ +struct stat_round_event *round = &event->stat_round; +struct perf_evsel *counter; + +evlist__for_each (session->evlist, counter) { +perf_stat_process_counter (&stat_config, counter); + scripting_ops->process_stat (&stat_config, counter, round->time); + } + + scripting_ops->process_stat_interval (round->time); +return 0 ; +} +static int process_stat_config_event (struct perf_tool *tool__maybe_unused ,union perf_event *event,struct perf_session *session__maybe_unused )
@@ -1716,6 +1745,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__process_auxtrace_info, .auxtrace = perf_event__process_auxtrace, .auxtrace_error = perf_event__process_auxtrace_error, + .stat = perf_event__process_stat_event, + .stat_round = process_stat_round_event, .stat_config = process_stat_config_event, .thread_map = process_thread_map_event, .cpu_map = process_cpu_map_event,
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 55/57 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.
$ perf stat record ls
SNIP
Performance counter stats for 'ls':
0.851585 task-clock (msec) # 0.717 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
114 page-faults # 0.134 M/sec
2,620,918 cycles # 3.078 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
2,714,111 instructions # 1.04 insns per cycle
542,434 branches # 636.970 M/sec
15,946 branch-misses # 2.94% of all branches0.001186954 seconds time elapsed
$ perf script CPU THREAD VAL ENA RUN TIME EVENT -1 26185 851585 851585 851585 1186954 task-clock -1 26185 0 851585 851585 1186954 context-switches -1 26185 0 851585 851585 1186954 cpu-migrations -1 26185 114 851585 851585 1186954 page-faults -1 26185 2620918 853340 853340 1186954 cycles -1 26185 0 0 0 1186954 stalled-cycles-frontend -1 26185 0 0 0 1186954 stalled-cycles-backend -1 26185 2714111 853340 853340 1186954 instructions -1 26185 542434 853340 853340 1186954 branches -1 26185 15946 853340 853340 1186954 branch-misses
--- tools/perf/builtin-script.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-)
tools/perf/builtin-script.c +33 -2
@@ -572,9 +572,40 @@ static void process_event(union perf_event *event, struct perf_sample *sample, }static void process_stat (struct perf_stat_config *config__maybe_unused , -struct perf_evsel *evsel__maybe_unused , -u64 time__maybe_unused ) +struct perf_evsel *counter,u64 time) { +int nthreads =thread_map__nr (counter->threads); +int ncpus =perf_evsel__nr_cpus (counter); +int cpu, thread; +static int header_printed; + +if (counter->system_wide) + nthreads =1 ; + +if (!header_printed) { +printf ("%3s %8s %15s %15s %15s %15s %s\n" , +"CPU" ,"THREAD" ,"VAL" ,"ENA" ,"RUN" ,"TIME" ,"EVENT" ); + header_printed =1 ; + } + +for (thread =0 ; thread < nthreads; thread++) { +for (cpu =0 ; cpu < ncpus; cpu++) { +struct perf_counts_values *counts; + + counts =perf_counts (counter->counts, cpu, thread); + +printf ("%3d %8d %15" PRIu64" %15" PRIu64" %15" PRIu64" %15" PRIu64" %s\n" , + counter->cpus->map[cpu], +thread_map__pid (counter->threads, thread), + counts->val, + counts->ena, + counts->run, + time, +perf_evsel__name (counter)); + } + } + +return ; }static void process_stat_interval (u64 time__maybe_unused ) { }
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 56/57 perf script: Add python support for stat events
In reply to Jiri OlsaAdd support to get stat events data in perf python scripts.
The python script shall implement following
new interface to process stat data:
def stat__<event_name>_[<modifier>](cpu, thread, time, val, ena, run):
- is called for every stat event for given counter, if user monitors 'cycles,instructions:u" following callbacks should be defined:
def stat__cycles(cpu, thread, time, val, ena, run):
def stat__instructions_u(cpu, thread, time, val, ena, run):
def stat__interval(time):
- is called for every interval with its time,
in non interval mode it's called after last
stat event with total meassured time in ns
The rest of the current interface stays untouched..
Please check example CPI metrics script in following patch with command line examples in changelogs.
--- .../util/scripting-engines/trace-event-python.c | 114 +++++++++++++++++++-- 1 file changed, 108 insertions(+), 6 deletions(-)
tools/perf/util/scripting-engines/trace-event-python.c +108 -6
@@ -41,6 +41,9 @@#include "../thread-stack.h" #include "../trace-event.h" #include "../machine.h" +#include "thread_map.h" +#include "cpumap.h" +#include "stat.h" PyMODINIT_FUNC initperf_trace_context (void );
@@ -859,6 +862,103 @@ static void python_process_event(union perf_event *event, } } +static void get_handler_name (char *str,size_t size, +struct perf_evsel *evsel) +{ +char *p = str; + +scnprintf (str, size,"stat__%s" ,perf_evsel__name (evsel)); + +while ((p =strchr (p,':' ))) { + *p ='_' ; + p++; + } +} + +static void +process_stat (struct perf_evsel *counter,int cpu,int thread,u64 time, +struct perf_counts_values *count) +{ +PyObject *handler, *t; +static char handler_name[256 ]; +int n =0 ; + + t =PyTuple_New (MAX_FIELDS ); +if (!t) +Py_FatalError ("couldn't create Python tuple" ); + +get_handler_name (handler_name,sizeof (handler_name), + counter); + + handler =get_handler (handler_name); +if (!handler) { +pr_debug ("can't find python handler %s\n" , handler_name); +return ; + } + +PyTuple_SetItem (t, n++,PyInt_FromLong (cpu)); +PyTuple_SetItem (t, n++,PyInt_FromLong (thread)); +PyTuple_SetItem (t, n++,PyLong_FromLong (time)); +PyTuple_SetItem (t, n++,PyLong_FromLong (count->val)); +PyTuple_SetItem (t, n++,PyLong_FromLong (count->ena)); +PyTuple_SetItem (t, n++,PyLong_FromLong (count->run)); + +if (_PyTuple_Resize (&t, n) ==-1 ) +Py_FatalError ("error resizing Python tuple" ); + +call_object (handler, t, handler_name); + +Py_DECREF (t); +} + +static void python_process_stat (struct perf_stat_config *config, +struct perf_evsel *counter,u64 time) +{ +struct thread_map *threads = counter->threads; +struct cpu_map *cpus = counter->cpus; +int cpu, thread; + +if (config->aggr_mode ==AGGR_GLOBAL ) { +process_stat (counter,-1 ,-1 , time, + &counter->counts->aggr); +return ; + } + +for (thread =0 ; thread < threads->nr; thread++) { +for (cpu =0 ; cpu < cpus->nr; cpu++) { +process_stat (counter, cpus->map[cpu], +thread_map__pid (threads, thread), time, +perf_counts (counter->counts, cpu, thread)); + } + } +} + +static void python_process_stat_interval (u64 time) +{ +PyObject *handler, *t; +static const char handler_name[] ="stat__interval" ; +int n =0 ; + + t =PyTuple_New (MAX_FIELDS ); +if (!t) +Py_FatalError ("couldn't create Python tuple" ); + + handler =get_handler (handler_name); +if (!handler) { +pr_debug ("can't find python handler %s\n" , handler_name); +return ; + } + +PyTuple_SetItem (t, n++,PyLong_FromLong (time)); + +if (_PyTuple_Resize (&t, n) ==-1 ) +Py_FatalError ("error resizing Python tuple" ); + +call_object (handler, t, handler_name); + +Py_DECREF (t); +} +static int run_start_sub (void ) { main_module =PyImport_AddModule ("__main__" );
@@ -1201,10 +1301,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) }struct scripting_ops python_scripting_ops = { - .name ="Python" , - .start_script = python_start_script, - .flush_script = python_flush_script, - .stop_script = python_stop_script, - .process_event = python_process_event, - .generate_script = python_generate_script, + .name ="Python" , + .start_script = python_start_script, + .flush_script = python_flush_script, + .stop_script = python_stop_script, + .process_event = python_process_event, + .process_stat = python_process_stat, + .process_stat_interval = python_process_stat_interval, + .generate_script = python_generate_script, };
Signature · 1 line
2.4.3
Jiri Olsa
reviewerPATCH v4 57/57 perf script: Add stat-cpi.py script
In reply to Jiri OlsaAdding stat-cpi.py as an example of how to do stat scripting. It computes the CPI metrics from cycles and instructions events.
Following stat record/report/script combinations could be used:
- get CPI for given workload
$ perf stat -e cycles,instructions record ls
SNIP
Performance counter stats for 'ls':
2,904,431 cycles
3,346,878 instructions # 1.15 insns per cycle
0.001782686 seconds time elapsed
$ perf script -s ./scripts/python/stat-cpi.py
0.001783: cpu -1, thread -1 -> cpi 0.867803 (2904431/3346878)
$ perf stat -e cycles,instructions record ls | perf script -s ./scripts/python/stat-cpi.py
SNIP
0.001730: cpu -1, thread -1 -> cpi 0.869026 (2928292/3369627)
- get CPI systemwide:
$ perf stat -e cycles,instructions -a -I 1000 record sleep 3
# time counts unit events
1.000158618 594,274,711 cycles (100.00%)
1.000158618 441,898,250 instructions
2.000350973 567,649,705 cycles (100.00%)
2.000350973 432,669,206 instructions
3.000559210 561,940,430 cycles (100.00%)
3.000559210 420,403,465 instructions
3.000670798 780,105 cycles (100.00%)
3.000670798 326,516 instructions $ perf script -s ./scripts/python/stat-cpi.py
1.000159: cpu -1, thread -1 -> cpi 1.344823 (594274711/441898250)
2.000351: cpu -1, thread -1 -> cpi 1.311972 (567649705/432669206)
3.000559: cpu -1, thread -1 -> cpi 1.336669 (561940430/420403465)
3.000671: cpu -1, thread -1 -> cpi 2.389178 (780105/326516) $ perf stat -e cycles,instructions -a -I 1000 record sleep 3 | perf script -s ./scripts/python/stat-cpi.py
1.000202: cpu -1, thread -1 -> cpi 1.035091 (940778881/908885530)
2.000392: cpu -1, thread -1 -> cpi 1.442600 (627493992/434974455)
3.000545: cpu -1, thread -1 -> cpi 1.353612 (741463930/547766890)
3.000622: cpu -1, thread -1 -> cpi 2.642110 (784083/296764)--- 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 43 lines
hi,
sending another version of stat scripting.v4 changes:
- added attr update event for event's cpumask
- forbig aggregation on task workloads
- some minor reorders and changelog fixesv3 changes:
- added attr update event to handle unit,scale,name for event it fixed the uncore_imc_1/cas_count_read/ record/report
- perf report -D now displays stat related events
- some minor and changelog fixesv2 changes:
- rebased to latest Arnaldo's perf/core
- patches 1 to 11 already merged in
- added --per-core/--per-socket/-A options for perf stat report command to allow custom aggregation in stat report, please check new examples below
- couple changelogs changesThe 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 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.
The stat data are stored in new stat, stat-round, stat-config user events.
stat - stored for each read syscall of the counter
stat round - stored for each interval or end of the command invocation stat config - stores all the config information needed to process data
so report tool could restore the same output as record
Quoted 9 lines
The python script can now define 'stat__<eventname>_<modifier>' functions to get stat events data and '
stat__interval' to get stat-round data.See CPI script example in
scripts/python/stat-cpi.py.Also available in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/stat_script
Thanks,
Kan
Quoted 259 lines
thanks,
jirkaExamples:
- 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 branches0.000607287 seconds time elapsed- To report perf stat data:
$ perf stat reportPerformance counter stats for '
/home/jolsa/bin/perfstat 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 branches0.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.pyscript over perf.data:$ perf script -s scripts/python/stat-cpi.py 1.000265: cpu -1, thread -1 -> cpi 0.783529 (462311482/590037440) 2.000483: cpu -1, thread -1 -> cpi 0.851362 (722532336/848678197) 3.000760: cpu -1, thread -1 -> cpi 0.881689 (75990880/86187813) 3.213961: cpu -1, thread -1 -> cpi 0.627634 (85329533/135954296)- To pipe data from stat to stat-cpi script:
$ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf script -s scripts/python/stat-cpi.py 1.000192: cpu 0, thread -1 -> cpi 0.739535 (23921908/32347236) 2.000376: cpu 0, thread -1 -> cpi 1.663482 (2519340/1514498) 3.000621: cpu 0, thread -1 -> cpi 1.396308 (16162767/11575362) 4.000700: cpu 0, thread -1 -> cpi 1.092246 (20077258/18381624) 5.000867: cpu 0, thread -1 -> cpi 0.473816 (45157586/95306156) 6.001034: cpu 0, thread -1 -> cpi 0.532792 (43701668/82023818) 7.001195: cpu 0, thread -1 -> cpi 1.122059 (29890042/26638561)- Raw script stat data output:
$ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf --no- pager script CPU THREAD VAL ENA RUN TIME EVENT 0 -1 12302059 1000811347 1000810712 1000198821 cycles:u 0 -1 2565362 1000823218 1000823218 1000198821 instructions:u 0 -1 14453353 1000812704 1000812704 2000382283 cycles:u 0 -1 4600932 1000799342 1000799342 2000382283 instructions:u 0 -1 15245106 1000774425 1000774425 3000538255 cycles:u 0 -1 2624324 1000769310 1000769310 3000538255 instructions:u- To display different aggregation in report:
$ perf stat -e cycles -a -I 1000 record sleep 3 # time counts unit events 1.000223609 703,427,617 cycles 2.000443651 609,975,307 cycles 3.000569616 668,479,597 cycles 3.000735323 1,155,816 cycles$ perf stat report # time counts unit events 1.000223609 703,427,617 cycles 2.000443651 609,975,307 cycles 3.000569616 668,479,597 cycles 3.000735323 1,155,816 cycles$ perf stat report --per-core # time core cpus counts unit events 1.000223609 S0-C0 2 327,612,412 cycles 1.000223609 S0-C1 2 375,815,205 cycles 2.000443651 S0-C0 2 287,462,177 cycles 2.000443651 S0-C1 2 322,513,130 cycles 3.000569616 S0-C0 2 271,571,908 cycles 3.000569616 S0-C1 2 396,907,689 cycles 3.000735323 S0-C0 2 694,977 cycles 3.000735323 S0-C1 2 460,839 cycles$ perf stat report --per-socket # time socket cpus counts unit events 1.000223609 S0 4 703,427,617 cycles 2.000443651 S0 4 609,975,307 cycles 3.000569616 S0 4 668,479,597 cycles 3.000735323 S0 4 1,155,816 cycles$ perf stat report -A # time CPU counts unit events 1.000223609 CPU0 205,431,505 cycles 1.000223609 CPU1 122,180,907 cycles 1.000223609 CPU2 176,649,682 cycles 1.000223609 CPU3 199,165,523 cycles 2.000443651 CPU0 148,447,922 cycles 2.000443651 CPU1 139,014,255 cycles 2.000443651 CPU2 204,436,559 cycles 2.000443651 CPU3 118,076,571 cycles 3.000569616 CPU0 149,788,954 cycles 3.000569616 CPU1 121,782,954 cycles 3.000569616 CPU2 247,277,700 cycles 3.000569616 CPU3 149,629,989 cycles 3.000735323 CPU0 269,675 cycles 3.000735323 CPU1 425,302 cycles 3.000735323 CPU2 364,169 cycles 3.000735323 CPU3 96,670 cyclesCc Andi Kleen <[email protected]>Cc Ulrich Drepper <[email protected]>Cc Will Deacon <[email protected]>Cc Stephane Eranian <[email protected]>Cc Don Zickus <[email protected]>---
Jiri Olsa (57):
perf tools: Addthread_mapevent
perf tools: Addthread_mapevent sythesize function
perf tools: Addthread_map__new_eventfunction
perf tools: Addperf_event__fprintf_thread_mapfunction perf tools: Addcpu_mapevent
perf tools: Addcpu_mapevent synthesize function
perf tools: Addcpu_map__empty_newfunction
perf tools: Addcpu_map__new_eventfunction
perf tools: Addperf_event__fprintf_cpu_mapfunction
perf tools: Add stat config event
perf tools: Add stat config event synthesize function
perf tools: Add stat config event read function
perf tools: Add stat event
perf tools: Add stat event synthesize function
perf tools: Add stat event read function
perf tools: Add stat round event
perf tools: Add stat round event synthesize function
perf tools: Add stat events fprintf functions
perf tools: Addattr_updateevent
perf tools: Addattr_updateevent unit type
perf tools: Addattr_updateevent scale type
perf tools: Addattr_updateevent name type
perf tools: Addattr_updateevent cpus type
perf tools: Addperf_event__fprintf_attr_updatefunction perf report: Display newly added events in raw dump
perf tools: Introduce stat feature
perf tools: Moveid_offsetout of structperf_evselunion perf stat: Renameperf_statstruct intoperf_stat_evselperf stat: AddAGGR_UNSETmode
perf stat record: Add record command
perf stat record: Initialize record features
perf stat record: Synthesize stat record data
perf stat record: Store events IDs in perf data file
perf stat record: Add pipe support for record command
perf stat record: Write stat events on record
perf stat record: Write stat round events on record
perf stat record: Do not allow record with multiple runs mode perf stat record: Synthesize attr update events
perf tools: Makecpu_map__build_mapglobal
perf tools: Add data arg tocpu_map__build_mapcallback perf stat report: Cache aggregated map entries in extra cpumap perf stat report: Add report command
perf stat report: Process cpu/threads maps
perf stat report: Process stat config event
perf stat report: Add support to initializeaggr_mapfrom file perf stat report: Process stat and stat round events
perf stat report: Process attr update events
perf stat report: Movecsv_sepinitialization before report command perf stat report: Allow to overrideaggr_mode
perf script: Check output fields only for samples
perf script: Process cpu/threads maps
perf script: Process stat config event
perf script: Add process_stat/process_stat_interval scripting interface perf script: Add stat default handlers
perf script: Display stat events by default
perf script: Add python support for stat events
perf script: Addstat-cpi.pyscripttools/perf/Documentation/perf-stat.txt | 34 ++ tools/perf/builtin-record.c | 2 + tools/perf/builtin-script.c | 144 ++++- tools/perf/builtin-stat.c | 662 ++++++++++++++++++++- tools/perf/scripts/python/stat-cpi.py | 74 +++ tools/perf/tests/Build | 3 + tools/perf/tests/attr_update.c | 118 ++++ tools/perf/tests/builtin-test.c | 24 + tools/perf/tests/cpumap.c | 91 +++ tools/perf/tests/stat.c | 111 ++++ tools/perf/tests/tests.h | 7 + tools/perf/tests/thread-map.c | 43 ++ tools/perf/tests/topology.c | 4 +- tools/perf/util/cpumap.c | 76 ++- tools/perf/util/cpumap.h | 9 +- tools/perf/util/event.c | 308 ++++++++++ tools/perf/util/event.h | 151 ++++- tools/perf/util/evlist.c | 6 +- tools/perf/util/evlist.h | 3 + tools/perf/util/evsel.h | 2 +- tools/perf/util/header.c | 205 +++++++ tools/perf/util/header.h | 17 + .../util/scripting-engines/trace-event-python.c | 114 +++- tools/perf/util/session.c | 189 ++++++ tools/perf/util/stat.c | 75 ++- tools/perf/util/stat.h | 13 +- tools/perf/util/thread_map.c | 27 + tools/perf/util/thread_map.h | 3 + tools/perf/util/tool.h | 8 +- tools/perf/util/trace-event.h | 4 + 30 files changed, 2478 insertions(+), 49 deletions(-) create mode 100644 tools/perf/scripts/python/stat-cpi.py create mode 100644 tools/perf/tests/attr_update.c create mode 100644
tools/perf/tests/cpumap.ccreate mode 100644tools/perf/tests/stat.c
Namhyung Kim
maintainerHi Jiri,
Quoted 26 lines · Jiri Olsa
hi,
sending another version of stat scripting.v4 changes:
- added attr update event for event's cpumask
- forbig aggregation on task workloads
- some minor reorders and changelog fixesv3 changes:
- added attr update event to handle unit,scale,name for event it fixed the uncore_imc_1/cas_count_read/ record/report
- perf report -D now displays stat related events
- some minor and changelog fixesv2 changes:
- rebased to latest Arnaldo's perf/core
- patches 1 to 11 already merged in
- added --per-core/--per-socket/-A options for perf stat report command to allow custom aggregation in stat report, please check new examples below
- couple changelogs changesThe 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.
Nice. I didn't review this patchset (yet) but I have a feature request. :) It'd be great if we have 'perf stat diff' to compare two (or more) files in some way.
Thanks,
Namhyung
Quoted 34 lines · Namhyung Kim
Hi Jiri,
Quoted 31 lines · Jiri Olsa
hi,
sending another version of stat scripting.v4 changes:
- added attr update event for event's cpumask
- forbig aggregation on task workloads
- some minor reorders and changelog fixesv3 changes:
- added attr update event to handle unit,scale,name for event it fixed the uncore_imc_1/cas_count_read/ record/report
- perf report -D now displays stat related events
- some minor and changelog fixesv2 changes:
- rebased to latest Arnaldo's perf/core
- patches 1 to 11 already merged in
- added --per-core/--per-socket/-A options for perf stat report command to allow custom aggregation in stat report, please check new examples below
- couple changelogs changesThe 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 7 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.
Nice. I didn't review this patchset (yet) but I have a feature request. :) It'd be great if we have 'perf stat diff' to compare two (or more) files in some way.
yep, I plan to do stat diff
jirka