perf stat: Introduce --per-task option
Jiri Olsa
reviewerv2 cover perf stat: Introduce --per-task option
hi,
adding the possibility to display stat data per thread.
Allowing following commands and output:
$ perf stat -e cycles,instructions --per-task -p 25388,25442 -a ^C Performance counter stats for process id '25388,25442':
cat-25388 100,122 cycles vim-25442 4,167,876 cycles cat-25388 20,080 instructions vim-25442 3,232,735 instructions
6.057130572 seconds time elapsed
Also works under interval mode:
$ perf stat -e cycles,instructions --per-task -p 25388,25442 -a -I 1000
# time task counts unit events
1.000190002 cat-25388 54,196 cycles
1.000190002 vim-25442 0 cycles
1.000190002 cat-25388 11,660 instructions
1.000190002 vim-25442 0 instructions
2.000742579 cat-25388 55,247 cycles
2.000742579 vim-25442 1,752,951 cycles
2.000742579 cat-25388 11,872 instructions
2.000742579 vim-25442 1,238,512 instructions
3.001057871 cat-25388 0 cycles
3.001057871 vim-25442 0 cycles
3.001057871 cat-25388 0 instructions
3.001057871 vim-25442 0 instructions
^C 3.242519732 cat-25388 0 cycles
3.242519732 vim-25442 0 cycles
3.242519732 cat-25388 0 instructions
3.242519732 vim-25442 0 instructionsv2 changes:
- renamed xyarray__zero to xyarray__reset
- using atomic_t for cpu_map/thread_map refcnt
- moving all stat functions into stat object
- using init_stats to initialize 'struct stats*'
- change TASK-$pid output into $comm-$pid
- updated doc with --per-task option
thanks for comments,
jirka
---
Jiri Olsa (30):
perf tools: Introduce xyarray__reset function
perf tools: Add thread_map__(alloc|realloc) helpers
perf tools: Change thread_map::map into struct
perf tools: Add comm string into struct thread_map
perf tests: Add thread_map object tests
perf tools: Add reference counting for cpu_map object
perf tools: Add reference counting for thread_map object perf tools: Propagate cpu maps through the evlist
perf tools: Propagate thread maps through the evlist
perf tools: Make perf_evsel__(nr_)cpus generic
perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object perf stat: Introduce perf_counts__(alloc|free|reset) functions perf stat: Introduce perf_counts function
perf stat: Use xyarray for cpu evsel counts
perf stat: Make stats work over the thread dimension
perf stat: Rename struct perf_counts::cpu member to values perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into stat object perf stat: Move perf_evlist__(alloc|free)_stats into evlist object perf stat: Introduce perf_evsel__alloc_stats function
perf stat: Introduce perf_evsel__read function
perf stat: Introduce read_counters function
perf stat: Separate counters reading and processing
perf stat: Move zero_per_pkg into counter process code
perf stat: Move perf_stat initialization counter process code perf stat: Remove perf_evsel__read_cb function
perf stat: Rename print_interval to process_interval
perf stat: Using init_stats instead of memset
perf stat: Introduce print_counters function
perf stat: Introduce --per-task option
tools/perf/Documentation/perf-stat.txt | 3 + tools/perf/builtin-stat.c | 398 ++++++++++++++-------------- tools/perf/builtin-trace.c | 4 +- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 + tools/perf/tests/code-reading.c | 4 +- tools/perf/tests/keep-tracking.c | 4 +- tools/perf/tests/mmap-basic.c | 4 +- tools/perf/tests/mmap-thread-lookup.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 9 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/openat-syscall.c | 6 +- tools/perf/tests/switch-tracking.c | 4 +- tools/perf/tests/tests.h | 1 + tools/perf/tests/thread-map.c | 28 ++ tools/perf/util/auxtrace.c | 4 +- tools/perf/util/cpumap.c | 25 +- tools/perf/util/cpumap.h | 6 +- tools/perf/util/event.c | 6 +- tools/perf/util/evlist.c | 38 ++- tools/perf/util/evlist.h | 1 - tools/perf/util/evsel.c | 47 ++-- tools/perf/util/evsel.h | 43 ++- tools/perf/util/parse-events.c | 5 +- tools/perf/util/python-ext-sources | 2 + tools/perf/util/python.c | 4 +- tools/perf/util/record.c | 4 +- tools/perf/util/session.c | 2 +- tools/perf/util/stat.c | 134 ++++++++++ tools/perf/util/stat.h | 46 ++++ tools/perf/util/svghelper.c | 2 +- tools/perf/util/thread_map.c | 131 +++++++-- tools/perf/util/thread_map.h | 17 +- tools/perf/util/xyarray.c | 8 + tools/perf/util/xyarray.h | 2 + 35 files changed, 672 insertions(+), 329 deletions(-) create mode 100644 tools/perf/tests/thread-map.c
Jiri Olsa
reviewerPATCH v2 1/30 perf tools: Introduce xyarray__reset function
To zero all the xyarray contents. It will be used
in following patches.
--- tools/perf/util/xyarray.c | 8 ++++++++ tools/perf/util/xyarray.h | 2 ++ 2 files changed, 10 insertions(+)
tools/perf/util/xyarray.c +8 -0
@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)if (xy !=NULL ) { xy->entry_size = entry_size; xy->row_size = row_size; + xy->entries = xlen * ylen; }return xy; } +void xyarray__reset (struct xyarray *xy) +{ +size_t n = xy->entries * xy->entry_size; + +memset (xy->contents,0 , n); +} +void xyarray__delete (struct xyarray *xy) {free (xy);
tools/perf/util/xyarray.h +2 -0
@@ -6,11 +6,13 @@struct xyarray {size_t row_size;size_t entry_size; +size_t entries;char contents[]; };struct xyarray *xyarray__new (int xlen,int ylen,size_t entry_size);void xyarray__delete (struct xyarray *xy); +void xyarray__reset (struct xyarray *xy);static inline void *xyarray__entry (struct xyarray *xy,int x,int y) {
Signature · 1 line
1.9.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf tools: Introduce xyarray__reset function
perf tools: Introduce xyarray__reset function
Commit-ID: b45f65e8fddc89ac6b46388908d3f6ac728be372 Gitweb: http://git.kernel.org/tip/b45f65e8fddc89ac6b46388908d3f6ac728be372 Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Jun 2015 10:19:16 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Jun 2015 10:34:39 -0300
perf tools: Introduce xyarray__reset function
To zero all the xyarray contents. It will be used in following patches.
--- tools/perf/util/xyarray.c | 8 ++++++++ tools/perf/util/xyarray.h | 2 ++ 2 files changed, 10 insertions(+)
tools/perf/util/xyarray.c +8 -0
@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)if (xy !=NULL ) { xy->entry_size = entry_size; xy->row_size = row_size; + xy->entries = xlen * ylen; }return xy; } +void xyarray__reset (struct xyarray *xy) +{ +size_t n = xy->entries * xy->entry_size; + +memset (xy->contents,0 , n); +} +void xyarray__delete (struct xyarray *xy) {free (xy);
tools/perf/util/xyarray.h +2 -0
@@ -6,11 +6,13 @@struct xyarray {size_t row_size;size_t entry_size; +size_t entries;char contents[]; };struct xyarray *xyarray__new (int xlen,int ylen,size_t entry_size);void xyarray__delete (struct xyarray *xy); +void xyarray__reset (struct xyarray *xy);static inline void *xyarray__entry (struct xyarray *xy,int x,int y) {
Jiri Olsa
reviewerPATCH v2 2/30 perf tools: Add thread_map__(alloc|realloc) helpers
In reply to Jiri OlsaIn order to have 'struct thread_map' allocation on single place and can change it easily in following patch.
Using alloc|realloc for static helpers, because thread_map__new is already used in public interface.
--- tools/perf/util/thread_map.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
tools/perf/util/thread_map.c +16 -8
@@ -20,6 +20,15 @@ static int filter(const struct dirent *dir)return 1 ; } +static struct thread_map *thread_map__realloc (struct thread_map *map,int nr) +{ +size_t size =sizeof (*map) +sizeof (pid_t) * nr; + +return realloc (map, size); +} + +#define thread_map__alloc (__nr) thread_map__realloc(NULL, __nr) +struct thread_map *thread_map__new_by_pid (pid_t pid) {struct thread_map *threads;
@@ -33,7 +42,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)if (items <=0 )return NULL ; - threads =malloc (sizeof (*threads) +sizeof (pid_t) * items); + threads =thread_map__alloc (items);if (threads !=NULL ) {for (i =0 ; i < items; i++) threads->map[i] =atoi (namelist[i]->d_name);
@@ -49,7 +58,7 @@ 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 *threads =malloc (sizeof (*threads) +sizeof (pid_t)); +struct thread_map *threads =thread_map__alloc (1 );if (threads !=NULL ) { threads->map[0 ] = tid;
@@ -65,8 +74,8 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)int max_threads =32 , items, i;char path[256 ];struct dirent dirent, *next, **namelist =NULL ; -struct thread_map *threads =malloc (sizeof (*threads) + - max_threads *sizeof (pid_t)); +struct thread_map *threads =thread_map__alloc (max_threads); +if (threads ==NULL ) goto out;
@@ -185,8 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) goto out_free_threads; total_tasks += items; - nt =realloc (threads, (sizeof (*threads) + -sizeof (pid_t) * total_tasks)); + nt =thread_map__realloc (threads, total_tasks);if (nt ==NULL ) goto out_free_namelist;
@@ -216,7 +224,7 @@ out_free_threads:struct thread_map *thread_map__new_dummy (void ) { -struct thread_map *threads =malloc (sizeof (*threads) +sizeof (pid_t)); +struct thread_map *threads =thread_map__alloc (1 );if (threads !=NULL ) { threads->map[0 ] =-1 ;
@@ -253,7 +261,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)continue ; ntasks++; - nt =realloc (threads,sizeof (*threads) +sizeof (pid_t) * ntasks); + nt =thread_map__realloc (threads, ntasks);if (nt ==NULL ) goto out_free_threads;
Signature · 1 line
1.9.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf tools: Add thread_map__(alloc|realloc) helpers
perf tools: Add thread_map__(alloc|realloc) helpers
Commit-ID: 9d7e8c3a96e5a903a4e0951e08f7fa6957170bef Gitweb: http://git.kernel.org/tip/9d7e8c3a96e5a903a4e0951e08f7fa6957170bef Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Jun 2015 10:19:17 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Jun 2015 10:34:40 -0300
perf tools: Add thread_map__(alloc|realloc) helpers
In order to have 'struct thread_map' allocation on single place and can change it easily in following patch.
Using alloc|realloc for static helpers, because thread_map__new is already used in public interface.
--- tools/perf/util/thread_map.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
tools/perf/util/thread_map.c +16 -8
@@ -20,6 +20,15 @@ static int filter(const struct dirent *dir)return 1 ; } +static struct thread_map *thread_map__realloc (struct thread_map *map,int nr) +{ +size_t size =sizeof (*map) +sizeof (pid_t) * nr; + +return realloc (map, size); +} + +#define thread_map__alloc (__nr) thread_map__realloc(NULL, __nr) +struct thread_map *thread_map__new_by_pid (pid_t pid) {struct thread_map *threads;
@@ -33,7 +42,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)if (items <=0 )return NULL ; - threads =malloc (sizeof (*threads) +sizeof (pid_t) * items); + threads =thread_map__alloc (items);if (threads !=NULL ) {for (i =0 ; i < items; i++) threads->map[i] =atoi (namelist[i]->d_name);
@@ -49,7 +58,7 @@ 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 *threads =malloc (sizeof (*threads) +sizeof (pid_t)); +struct thread_map *threads =thread_map__alloc (1 );if (threads !=NULL ) { threads->map[0 ] = tid;
@@ -65,8 +74,8 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)int max_threads =32 , items, i;char path[256 ];struct dirent dirent, *next, **namelist =NULL ; -struct thread_map *threads =malloc (sizeof (*threads) + - max_threads *sizeof (pid_t)); +struct thread_map *threads =thread_map__alloc (max_threads); +if (threads ==NULL ) goto out;
@@ -185,8 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) goto out_free_threads; total_tasks += items; - nt =realloc (threads, (sizeof (*threads) + -sizeof (pid_t) * total_tasks)); + nt =thread_map__realloc (threads, total_tasks);if (nt ==NULL ) goto out_free_namelist;
@@ -216,7 +224,7 @@ out_free_threads:struct thread_map *thread_map__new_dummy (void ) { -struct thread_map *threads =malloc (sizeof (*threads) +sizeof (pid_t)); +struct thread_map *threads =thread_map__alloc (1 );if (threads !=NULL ) { threads->map[0 ] =-1 ;
@@ -253,7 +261,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)continue ; ntasks++; - nt =realloc (threads,sizeof (*threads) +sizeof (pid_t) * ntasks); + nt =thread_map__realloc (threads, ntasks);if (nt ==NULL ) goto out_free_threads;
Jiri Olsa
reviewerPATCH v2 3/30 perf tools: Change thread_map::map into struct
In reply to Jiri OlsaWe need to store command names with the pid. Changing map to be struct holding pid. Process name is coming in shortly.
--- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/util/auxtrace.c | 4 ++-- tools/perf/util/event.c | 6 +++--- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 2 +- tools/perf/util/thread_map.c | 22 +++++++++++----------- tools/perf/util/thread_map.h | 8 +++++++- 8 files changed, 29 insertions(+), 23 deletions(-)
tools/perf/builtin-trace.c +2 -2
@@ -2324,7 +2324,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)*/ if (trace->filter_pids.nr >0 ) err =perf_evlist__set_filter_pids (evlist, trace->filter_pids.nr, trace->filter_pids.entries); -else if (evlist->threads->map[0 ] ==-1 ) +else if (thread_map__pid (evlist->threads,0 ) ==-1 ) err =perf_evlist__set_filter_pid (evlist,getpid ());if (err <0 ) {
@@ -2342,7 +2342,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)if (forks)perf_evlist__start_workload (evlist); - trace->multiple_threads = evlist->threads->map[0 ] ==-1 || + trace->multiple_threads =thread_map__pid (evlist->threads,0 ) ==-1 || evlist->threads->nr >1 ||perf_evlist__first (evlist)->attr.inherit; again:
tools/perf/tests/openat-syscall-tp-fields.c +1 -1
@@ -45,7 +45,7 @@ int test__syscall_openat_tp_fields(void)perf_evsel__config (evsel, &opts); - evlist->threads->map[0 ] =getpid (); +thread_map__pid (evlist->threads,0 ) =getpid (); err =perf_evlist__open (evlist);if (err <0 ) {
tools/perf/util/auxtrace.c +2 -2
@@ -119,12 +119,12 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,if (per_cpu) { mp->cpu = evlist->cpus->map[idx];if (evlist->threads) - mp->tid = evlist->threads->map[0 ]; + mp->tid =thread_map__pid (evlist->threads,0 );else mp->tid =-1 ; }else { mp->cpu =-1 ; - mp->tid = evlist->threads->map[idx]; + mp->tid =thread_map__pid (evlist->threads, idx); } }
tools/perf/util/event.c +3 -3
@@ -479,7 +479,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,for (thread =0 ; thread < threads->nr; ++thread) {if (__event__synthesize_thread (comm_event, mmap_event, fork_event, - threads->map[thread],0 , +thread_map__pid (threads, thread),0 , process, tool, machine, mmap_data)) { err =-1 ;
@@ -490,12 +490,12 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,* comm.pid is set to thread group id by * perf_event__synthesize_comm */ -if ((int ) comm_event->comm.pid != threads->map[thread]) { +if ((int ) comm_event->comm.pid !=thread_map__pid (threads, thread)) {bool need_leader = true;/* is thread group leader in thread_map? */ for (j =0 ; j < threads->nr; ++j) { -if ((int ) comm_event->comm.pid == threads->map[j]) { +if ((int ) comm_event->comm.pid ==thread_map__pid (threads, j)) { need_leader = false;break ; }
tools/perf/util/evlist.c +2 -2
@@ -539,7 +539,7 @@ static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,else sid->cpu =-1 ;if (!evsel->system_wide && evlist->threads && thread >=0 ) - sid->tid = evlist->threads->map[thread]; + sid->tid =thread_map__pid (evlist->threads, thread);else sid->tid =-1 ; }
@@ -1459,7 +1459,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar __func__, __LINE__); goto out_close_pipes; } - evlist->threads->map[0 ] = evlist->workload.pid; +thread_map__pid (evlist->threads,0 ) = evlist->workload.pid; }close (child_ready_pipe[1 ]);
tools/perf/util/evsel.c +1 -1
@@ -1184,7 +1184,7 @@ retry_sample_id:int group_fd;if (!evsel->cgrp && !evsel->system_wide) - pid = threads->map[thread]; + pid =thread_map__pid (threads, thread); group_fd =get_group_fd (evsel, cpu, thread); retry_open:
tools/perf/util/thread_map.c +11 -11
@@ -22,7 +22,7 @@ static int filter(const struct dirent *dir)static struct thread_map *thread_map__realloc (struct thread_map *map,int nr) { -size_t size =sizeof (*map) +sizeof (pid_t) * nr; +size_t size =sizeof (*map) +sizeof (struct thread_map_data ) * nr;return realloc (map, size); }
@@ -45,7 +45,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) threads =thread_map__alloc (items);if (threads !=NULL ) {for (i =0 ; i < items; i++) - threads->map[i] =atoi (namelist[i]->d_name); +thread_map__pid (threads, i) =atoi (namelist[i]->d_name); threads->nr = items; }
@@ -61,8 +61,8 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)struct thread_map *threads =thread_map__alloc (1 );if (threads !=NULL ) { - threads->map[0 ] = tid; - threads->nr =1 ; +thread_map__pid (threads,0 ) = tid; + threads->nr =1 ; }return threads;
@@ -124,7 +124,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) }for (i =0 ; i < items; i++) - threads->map[threads->nr + i] =atoi (namelist[i]->d_name); +thread_map__pid (threads, threads->nr + i) =atoi (namelist[i]->d_name);for (i =0 ; i < items; i++)zfree (&namelist[i]);
@@ -201,7 +201,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) threads = nt;for (i =0 ; i < items; i++) { - threads->map[j++] =atoi (namelist[i]->d_name); +thread_map__pid (threads, j++) =atoi (namelist[i]->d_name);zfree (&namelist[i]); } threads->nr = total_tasks;
@@ -227,8 +227,8 @@ struct thread_map *thread_map__new_dummy(void)struct thread_map *threads =thread_map__alloc (1 );if (threads !=NULL ) { - threads->map[0 ] =-1 ; - threads->nr =1 ; +thread_map__pid (threads,0 ) =-1 ; + threads->nr =1 ; }return threads; }
@@ -267,8 +267,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) goto out_free_threads; threads = nt; - threads->map[ntasks -1 ] = tid; - threads->nr = ntasks; +thread_map__pid (threads, ntasks -1 ) = tid; + threads->nr = ntasks; } out:return threads;
@@ -301,7 +301,7 @@ size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)size_t printed =fprintf (fp,"%d thread%s: " , threads->nr, threads->nr >1 ?"s" :"" );for (i =0 ; i < threads->nr; ++i) - printed +=fprintf (fp,"%s%d" , i ?", " :"" , threads->map[i]); + printed +=fprintf (fp,"%s%d" , i ?", " :"" ,thread_map__pid (threads, i));return printed +fprintf (fp,"\n" ); }
tools/perf/util/thread_map.h +7 -1
@@ -4,11 +4,17 @@#include <sys/types.h> #include <stdio.h> +struct thread_map_data { +pid_t pid; +}; +struct thread_map {int nr; -pid_t map[]; +struct thread_map_data map[]; }; +#define thread_map__pid (__m, __t) __m->map[__t].pid +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);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 03/30] perf tools: Change thread_map::map into struct
Em Sun, Jun 14, 2015 at 10:19:18AM +0200, Jiri Olsa escreveu:
Quoted 3 lines
We need to store command names with the pid. Changing map to be struct holding pid. Process name is coming in shortly.
<SNIP>
tools/perf/util/thread_map.h line 10
Quoted 9 lines
+++
b/tools/perf/util/thread_map.htools/perf/util/thread_map.h +4
-0@@ -4,11 +4,17 @@#include <sys/types.h> #include <stdio.h> +struct thread_map_data { +pid_t pid; +}; +
What 'data' is this? That is way vague term.
Will try looking at the other patches to try to suggest some other name
for this :-\
Quoted 13 lines
tools/perf/util/thread_map.h +3
-1struct thread_map {int nr; -pid_t map[]; +struct thread_map_data map[]; }; +#define thread_map__pid (__m, __t) __m->map[__t].pid +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);Signature · 1 line
1.9.3
Re: [PATCH 03/30] perf tools: Change thread_map::map into struct
Quoted 12 lines · Arnaldo Carvalho de Melo
Em Sun, Jun 14, 2015 at 10:19:18AM +0200, Jiri Olsa escreveu:
Quoted 3 lines
We need to store command names with the pid. Changing map to be struct holding pid. Process name is coming in shortly.
<SNIP>
Quoted 5 lines
+++
b/tools/perf/util/thread_map.htools/perf/util/thread_map.h +0
-0@@ -4,11 +4,17 @@#include <sys/types.h> #include <stdio.h>
Quoted 6 lines
tools/perf/util/thread_map.h line 10
Quoted 4 lines
tools/perf/util/thread_map.h +4
-0+struct thread_map_data { +pid_t pid; +}; +What 'data' is this? That is way vague term.
data related to thread_mmap ;-)
jirka
Quoted 17 lines
Will try looking at the other patches to try to suggest some other name
for this :-\Quoted 13 lines
tools/perf/util/thread_map.h +3
-1struct thread_map {int nr; -pid_t map[]; +struct thread_map_data map[]; }; +#define thread_map__pid (__m, __t) __m->map[__t].pid +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);Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 4/30 perf tools: Add comm string into struct thread_map
In reply to Jiri OlsaAdding support to hold comm name together with pids in 'struct thread_map'. It will be useful for --per-task option to display task pid together with task name.
Getting the task name from /proc/$pid/comm.
--- tools/perf/util/python-ext-sources | 1 + tools/perf/util/thread_map.c | 63 +++++++++++++++++++++++++++++++++++--- tools/perf/util/thread_map.h | 2 ++ 3 files changed, 62 insertions(+), 4 deletions(-)
tools/perf/util/python-ext-sources +1 -0
@@ -19,3 +19,4 @@ util/rblist.c util/strlist.c util/trace-event.c ../../lib/rbtree.c +util/string.c
tools/perf/util/thread_map.c +59 -4
121 lines not on this page · raw message
tools/perf/util/thread_map.h +2 -0
@@ -6,6 +6,7 @@struct thread_map_data {pid_t pid; +char *comm; };struct thread_map {
@@ -14,6 +15,7 @@ struct thread_map { };#define thread_map__pid (__m, __t) __m->map[__t].pid +#define thread_map__comm (__m, __t) __m->map[__t].commstruct thread_map *thread_map__new_dummy (void );struct thread_map *thread_map__new_by_pid (pid_t pid);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 04/30] perf tools: Add comm string into struct thread_map
Em Sun, Jun 14, 2015 at 10:19:19AM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding support to hold comm name together with pids in 'struct
thread_map'. It will be useful for --per-task option to display task pid together with task name.Getting the task name from
/proc/$pid/comm.
Humm, so you want to extend the thread_map, that was just for pids, to have some more info about the thread, if that is the case, why not synthesize the whole thread, and have a pointer to 'struct thread', that is the representation for a thread in perf instead of creating a new, partial thing like 'thread_map_data'?
You wouldn't have to use the existing synthesizing code if that seems to overkill, i.e. instead of having 'pid_t' as the array element in a thread_map, you would have 'struct thread', i.e. the whole shebang, but would just set what you need now, i.e. thread->pid and thread->comm, but later could do the rest instead of recreating it in that thread_map_data :-)
I.e. besides --per-task, don't you want --per-pid, --per-thread, or other stuff that will use other thread characteristics?
That or rename that 'thread_map_data' to something like mini_thread, ...}.
Got carried away, but that was the reaction to that vague name 'thread_map_data' 8-)
Anyway, applied the first two, looking at the rest...
- Arnaldo
Quoted 173 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/python-ext-sources | 1 + tools/perf/util/thread_map.c | 63 +++++++++++++++++++++++++++++++++++--- tools/perf/util/thread_map.h | 2 ++ 3 files changed, 62 insertions(+), 4 deletions(-)tools/perf/util/python-ext-sources +1
-0@@ -19,3 +19,4 @@ util/rblist.c util/strlist.c util/trace-event.c ../../lib/rbtree.c +util/string.ctools/perf/util/thread_map.c +59
-4@@ -8,8 +8,10 @@#include <unistd.h> #include "strlist.h" #include <string.h> +#include <api/fs/fs.h> #include "thread_map.h" #include "util.h" +#include "debug.h" /* Skip "." and ".." directories */ static int filter (const struct dirent *dir)@@ -29,6 +31,44 @@ static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)#define thread_map__alloc (__nr) thread_map__realloc(NULL, __nr) +static int get_comm (char **comm,pid_t pid) +{ +char *path; +size_t size; +int err; + +if (asprintf (&path,"%s/%d/comm" ,procfs__mountpoint (), pid) ==-1 ) +return -ENOMEM ; + + err =filename__read_str (path, comm, &size); +if (!err) +rtrim (*comm); + +free (path); +return err; +} + +static void comm_init (struct thread_map *map,int i) +{ +struct thread_map_data *data = &map->map[i]; + +/* +* The comm name is like extra bonus ;-), +* so just warn if we fail for any reason. +*/ + data->comm =NULL ; + +/* dummy pid comm initialization */ +if (data->pid ==-1 ) { + data->comm =strdup ("dummy" ); +return ; + } + +/* try to get pid's comm string */ +if (get_comm (&data->comm, data->pid)) +pr_warning ("Couldn't resolve comm name for pid %d\n" , data->pid); +} +struct thread_map *thread_map__new_by_pid (pid_t pid) {struct thread_map *threads;@@ -44,8 +84,10 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) threads =thread_map__alloc (items);if (threads !=NULL ) { -for (i =0 ; i < items; i++) +for (i =0 ; i < items; i++) {thread_map__pid (threads, i) =atoi (namelist[i]->d_name); +comm_init (threads, i); + } threads->nr = items; }@@ -63,6 +105,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)if (threads !=NULL ) {thread_map__pid (threads,0 ) = tid; threads->nr =1 ; +comm_init (threads,0 ); }return threads;@@ -123,8 +166,10 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) threads = tmp; } -for (i =0 ; i < items; i++) +for (i =0 ; i < items; i++) {thread_map__pid (threads, threads->nr + i) =atoi (namelist[i]->d_name); +comm_init (threads, threads->nr + i); + }for (i =0 ; i < items; i++)zfree (&namelist[i]);@@ -200,8 +245,9 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) threads = nt; -for (i =0 ; i < items; i++) { -thread_map__pid (threads, j++) =atoi (namelist[i]->d_name); +for (i =0 ; i < items; i++, j++) { +thread_map__pid (threads, j) =atoi (namelist[i]->d_name); +comm_init (threads, j);zfree (&namelist[i]); } threads->nr = total_tasks;@@ -229,6 +275,7 @@ struct thread_map *thread_map__new_dummy(void)if (threads !=NULL ) {thread_map__pid (threads,0 ) =-1 ; threads->nr =1 ; +comm_init (threads,0 ); }return threads; }@@ -269,6 +316,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) threads = nt;thread_map__pid (threads, ntasks -1 ) = tid; threads->nr = ntasks; +comm_init (threads, ntasks -1 ); } out:return threads;@@ -292,6 +340,13 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,void thread_map__delete (struct thread_map *threads) { +int i; + +if (threads) { +for (i =0 ; i < threads->nr; i++) +free (thread_map__comm (threads, i)); + } +free (threads); }tools/perf/util/thread_map.h +2
-0@@ -6,6 +6,7 @@struct thread_map_data {pid_t pid; +char *comm; };struct thread_map {@@ -14,6 +15,7 @@ struct thread_map { };#define thread_map__pid (__m, __t) __m->map[__t].pid +#define thread_map__comm (__m, __t) __m->map[__t].commstruct thread_map *thread_map__new_dummy (void );struct thread_map *thread_map__new_by_pid (pid_t pid);Signature · 1 line
1.9.3
Re: [PATCH 04/30] perf tools: Add comm string into struct thread_map
Quoted 13 lines · Arnaldo Carvalho de Melo
Em Sun, Jun 14, 2015 at 10:19:19AM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding support to hold comm name together with pids in 'struct
thread_map'. It will be useful for --per-task option to display task pid together with task name.Getting the task name from
/proc/$pid/comm.Humm, so you want to extend the
thread_map, that was just for pids, to have some more info about the thread, if that is the case, why not synthesize the whole thread, and have a pointer to 'struct thread', that is the representation for a thread in perf instead of creating a new, partial thing like 'thread_map_data'?
Quoted 6 lines
You wouldn't have to use the existing synthesizing code if that seems to overkill, i.e. instead of having '
pid_t' as the array element in athread_map, you would have 'struct thread', i.e. the whole shebang, but would just set what you need now, i.e.thread->pidandthread->comm, but later could do the rest instead of recreating it in thatthread_map_data:-)
hum, I guess I could find some parts of code that could be shared, but I fear not all of it.. 'struct thread' seems to be fairly customized for usage in sampling report code
maybe introduce 'machine' storage and provide interface to fill in live server data.. but it feels like overkill just for 2 lines of code that need print pid's name ;-)
Quoted 3 lines
I.e. besides --per-task, don't you want --per-pid, --per-thread, or other stuff that will use other thread characteristics?
with --per-task we dont do any grouping, just displaying what we store (now) for each separated thread
it might be better to use --per-thread instead of --per-task probably, I dont have strong feeling about that
also we could add --per-process that would group all threads based on process
jirka
Jiri Olsa
reviewerPATCH v2 5/30 perf tests: Add thread_map object tests
In reply to Jiri OlsaAdding thread_map object tests for comm name values.
--- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/tests.h | 1 + tools/perf/tests/thread-map.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 tools/perf/tests/thread-map.c
tools/perf/tests/Build +1 -0
@@ -31,6 +31,7 @@ perf-y += code-reading.o perf-y += sample-parsing.o perf-y += parse-no-sample-id-all.o perf-y += kmod-path.o +perf-y += thread-map.o perf-$(CONFIG_X86) += perf-time-to-tsc.o
tools/perf/tests/builtin-test.c +4 -0
@@ -171,6 +171,10 @@ static struct test { .func = test__kmod_path__parse, }, { + .desc = "Test thread map", + .func = test__thread_map, + }, + { .func = NULL, }, };
tools/perf/tests/tests.h +1 -0
@@ -61,6 +61,7 @@ int test__switch_tracking(void);int test__fdarray__filter (void );int test__fdarray__add (void );int test__kmod_path__parse (void ); +int test__thread_map (void );#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/tests/thread-map.c new file +28 -0
@@ -0,0 +1,28 @@ +#include <sys/types.h> +#include <unistd.h> +#include "tests.h" +#include "thread_map.h" +#include "debug.h" + +int test__thread_map (void ) +{ +struct thread_map *map; + +/* test map on current pid */ + map =thread_map__new_by_pid (getpid ()); +TEST_ASSERT_VAL ("wrong nr" , map->nr ==1 ); +TEST_ASSERT_VAL ("wrong pid" , +thread_map__pid (map,0 ) ==getpid ()); +TEST_ASSERT_VAL ("wrong pid" , + !strcmp (thread_map__comm (map,0 ),"perf" )); +thread_map__put (map); + +/* test dummy pid */ + map =thread_map__new_dummy (); +TEST_ASSERT_VAL ("wrong nr" , map->nr ==1 ); +TEST_ASSERT_VAL ("wrong pid" ,thread_map__pid (map,0 ) ==-1 ); +TEST_ASSERT_VAL ("wrong pid" , + !strcmp (thread_map__comm (map,0 ),"dummy" )); +thread_map__put (map); +return 0 ; +}
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 6/30 perf tools: Add reference counting for cpu_map object
In reply to Jiri OlsaAdding refference counting for cpu_map object, so
it could be easily shared among other objects.
Using cpu_map__put instead cpu_map__delete and making cpu_map__delete static.
--- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/util/cpumap.c | 25 +++++++++++++++++++++++-- tools/perf/util/cpumap.h | 6 +++++- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 1 + tools/perf/util/parse-events.c | 5 ++++- tools/perf/util/python.c | 2 +- tools/perf/util/record.c | 4 ++-- tools/perf/util/session.c | 2 +- tools/perf/util/svghelper.c | 2 +- 13 files changed, 44 insertions(+), 15 deletions(-)
tools/perf/tests/code-reading.c +1 -1
@@ -545,7 +545,7 @@ out_err:if (evlist) {perf_evlist__delete (evlist); }else { -cpu_map__delete (cpus); +cpu_map__put (cpus);thread_map__delete (threads); }machines__destroy_kernel_maps (&machines);
tools/perf/tests/keep-tracking.c +1 -1
@@ -144,7 +144,7 @@ out_err:perf_evlist__disable (evlist);perf_evlist__delete (evlist); }else { -cpu_map__delete (cpus); +cpu_map__put (cpus);thread_map__delete (threads); }
tools/perf/tests/mmap-basic.c +1 -1
@@ -140,7 +140,7 @@ out_delete_evlist: cpus =NULL ; threads =NULL ; out_free_cpus: -cpu_map__delete (cpus); +cpu_map__put (cpus); out_free_threads:thread_map__delete (threads);return err;
tools/perf/tests/switch-tracking.c +1 -1
@@ -560,7 +560,7 @@ out:perf_evlist__disable (evlist);perf_evlist__delete (evlist); }else { -cpu_map__delete (cpus); +cpu_map__put (cpus);thread_map__delete (threads); }
tools/perf/util/cpumap.c +23 -2
@@ -5,6 +5,7 @@#include <assert.h> #include <stdio.h> #include <stdlib.h> +#include "asm/bug.h" static struct cpu_map *cpu_map__default_new (void ) {
@@ -22,6 +23,7 @@ static struct cpu_map *cpu_map__default_new(void) cpus->map[i] = i; cpus->nr = nr_cpus; +atomic_set (&cpus->refcnt,1 ); }return cpus;
@@ -35,6 +37,7 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)if (cpus !=NULL ) { cpus->nr = nr_cpus;memcpy (cpus->map, tmp_cpus, payload_size); +atomic_set (&cpus->refcnt,1 ); }return cpus;
@@ -194,14 +197,31 @@ struct cpu_map *cpu_map__dummy_new(void)if (cpus !=NULL ) { cpus->nr =1 ; cpus->map[0 ] =-1 ; +atomic_set (&cpus->refcnt,1 ); }return cpus; } -void cpu_map__delete (struct cpu_map *map) +static void cpu_map__delete (struct cpu_map *map) { -free (map); +if (map) { +WARN_ONCE (atomic_read (&map->refcnt) !=0 , +"cpu map refcnt disbalanced\n" ); +free (map); + } +} + +struct cpu_map *cpu_map__get (struct cpu_map *map) +{ +atomic_inc (&map->refcnt); +return map; +} + +void cpu_map__put (struct cpu_map *map) +{ +if (map &&atomic_dec_and_test (&map->refcnt)) +cpu_map__delete (map); }int cpu_map__get_socket (struct cpu_map *map,int idx)
@@ -263,6 +283,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,/* ensure we process id in increasing order */ qsort (c->map, c->nr,sizeof (int ), cmp_ids); +atomic_set (&cpus->refcnt,1 ); *res = c;return 0 ; }
tools/perf/util/cpumap.h +5 -1
@@ -3,18 +3,19 @@#include <stdio.h> #include <stdbool.h> +#include <linux/atomic.h> #include "perf.h" #include "util/debug.h" struct cpu_map { +atomic_t refcnt;int nr;int map[]; };struct cpu_map *cpu_map__new (const char *cpu_list);struct cpu_map *cpu_map__dummy_new (void ); -void cpu_map__delete (struct cpu_map *map);struct cpu_map *cpu_map__read (FILE *file);size_t cpu_map__fprintf (struct cpu_map *map,FILE *fp);int cpu_map__get_socket (struct cpu_map *map,int idx);
@@ -22,6 +23,9 @@ 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);int cpu_map__build_core_map (struct cpu_map *cpus,struct cpu_map **corep); +struct cpu_map *cpu_map__get (struct cpu_map *map); +void cpu_map__put (struct cpu_map *map); +static inline int cpu_map__socket (struct cpu_map *sock,int s) {if (!sock || s > sock->nr || s <0 )
tools/perf/util/evlist.c +2 -2
@@ -114,7 +114,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) {perf_evlist__munmap (evlist);perf_evlist__close (evlist); -cpu_map__delete (evlist->cpus); +cpu_map__put (evlist->cpus);thread_map__delete (evlist->threads); evlist->cpus =NULL ; evlist->threads =NULL ;
@@ -1337,7 +1337,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) out:return err; out_free_cpus: -cpu_map__delete (evlist->cpus); +cpu_map__put (evlist->cpus); evlist->cpus =NULL ; goto out; }
tools/perf/util/evsel.c +1 -0
@@ -902,6 +902,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)perf_evsel__free_fd (evsel);perf_evsel__free_id (evsel);close_cgroup (evsel->cgrp); +cpu_map__put (evsel->cpus);zfree (&evsel->group_name);zfree (&evsel->name); perf_evsel__object.fini (evsel);
tools/perf/util/parse-events.c +4 -1
@@ -17,6 +17,7 @@#include "parse-events-flex.h" #include "pmu.h" #include "thread_map.h" +#include "cpumap.h" #include "asm/bug.h" #define MAX_NAME_LEN 100
@@ -285,7 +286,9 @@ __add_event(struct list_head *list, int *idx,if (!evsel)return NULL ; - evsel->cpus = cpus; +if (cpus) + evsel->cpus =cpu_map__get (cpus); +if (name) evsel->name =strdup (name);list_add_tail (&evsel->node, list);
tools/perf/util/python.c +1 -1
@@ -384,7 +384,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,static void pyrf_cpu_map__delete (struct pyrf_cpu_map *pcpus) { -cpu_map__delete (pcpus->cpus); +cpu_map__put (pcpus->cpus); pcpus->ob_type->tp_free ((PyObject *)pcpus); }
tools/perf/util/record.c +2 -2
@@ -64,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn)if (!cpus)return false; cpu = cpus->map[0 ]; -cpu_map__delete (cpus); +cpu_map__put (cpus); do { ret = perf_do_probe_api(fn, cpu, try[i++]);
@@ -226,7 +226,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)struct cpu_map *cpus =cpu_map__new (NULL ); cpu = cpus ? cpus->map[0 ] :0 ; -cpu_map__delete (cpus); +cpu_map__put (cpus); }else { cpu = evlist->cpus->map[0 ]; }
tools/perf/util/session.c +1 -1
@@ -1838,7 +1838,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, err =0 ; out_delete_map: -cpu_map__delete (map); +cpu_map__put (map);return err; }
tools/perf/util/svghelper.c +1 -1
@@ -748,7 +748,7 @@ static int str_to_bitmap(char *s, cpumask_t *b)set_bit (c,cpumask_bits (b)); } -cpu_map__delete (m); +cpu_map__put (m);return ret; }
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 7/30 perf tools: Add reference counting for thread_map object
In reply to Jiri OlsaAdding refference counting for thread_map object, so it could be easily shared among other objects.
Using thread_map__put instead thread_map__delete and making thread_map__delete static.
--- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/mmap-thread-lookup.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/python.c | 2 +- tools/perf/util/thread_map.c | 30 ++++++++++++++++++++++++++---- tools/perf/util/thread_map.h | 7 +++++-- 11 files changed, 41 insertions(+), 16 deletions(-)
tools/perf/tests/code-reading.c +1 -1
@@ -546,7 +546,7 @@ out_err:perf_evlist__delete (evlist); }else {cpu_map__put (cpus); -thread_map__delete (threads); +thread_map__put (threads); }machines__destroy_kernel_maps (&machines);machine__delete_threads (machine);
tools/perf/tests/keep-tracking.c +1 -1
@@ -145,7 +145,7 @@ out_err:perf_evlist__delete (evlist); }else {cpu_map__put (cpus); -thread_map__delete (threads); +thread_map__put (threads); }return err;
tools/perf/tests/mmap-basic.c +1 -1
@@ -142,6 +142,6 @@ out_delete_evlist: out_free_cpus:cpu_map__put (cpus); out_free_threads: -thread_map__delete (threads); +thread_map__put (threads);return err; }
tools/perf/tests/mmap-thread-lookup.c +1 -1
@@ -143,7 +143,7 @@ static int synth_process(struct machine *machine) perf_event__process, machine, 0); -thread_map__delete (map); +thread_map__put (map);return err; }
tools/perf/tests/openat-syscall-all-cpus.c +1 -1
@@ -110,6 +110,6 @@ out_close_fd: out_evsel_delete:perf_evsel__delete (evsel); out_thread_map_delete: -thread_map__delete (threads); +thread_map__put (threads);return err; }
tools/perf/tests/openat-syscall.c +1 -1
@@ -56,6 +56,6 @@ out_close_fd: out_evsel_delete:perf_evsel__delete (evsel); out_thread_map_delete: -thread_map__delete (threads); +thread_map__put (threads);return err; }
tools/perf/tests/switch-tracking.c +1 -1
@@ -561,7 +561,7 @@ out:perf_evlist__delete (evlist); }else {cpu_map__put (cpus); -thread_map__delete (threads); +thread_map__put (threads); }return err;
tools/perf/util/evlist.c +2 -2
@@ -115,7 +115,7 @@ void perf_evlist__delete(struct perf_evlist *evlist)perf_evlist__munmap (evlist);perf_evlist__close (evlist);cpu_map__put (evlist->cpus); -thread_map__delete (evlist->threads); +thread_map__put (evlist->threads); evlist->cpus =NULL ; evlist->threads =NULL ;perf_evlist__purge (evlist);
@@ -1104,7 +1104,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)return 0 ; out_delete_threads: -thread_map__delete (evlist->threads); +thread_map__put (evlist->threads); evlist->threads =NULL ;return -1 ; }
tools/perf/util/python.c +1 -1
@@ -453,7 +453,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,static void pyrf_thread_map__delete (struct pyrf_thread_map *pthreads) { -thread_map__delete (pthreads->threads); +thread_map__put (pthreads->threads); pthreads->ob_type->tp_free ((PyObject *)pthreads); }
tools/perf/util/thread_map.c +26 -4
@@ -9,6 +9,7 @@#include "strlist.h" #include <string.h> #include <api/fs/fs.h> +#include "asm/bug.h" #include "thread_map.h" #include "util.h" #include "debug.h"
@@ -89,6 +90,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)comm_init (threads, i); } threads->nr = items; +atomic_set (&threads->refcnt,1 ); }for (i=0 ; i<items; i++)
@@ -106,6 +108,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)thread_map__pid (threads,0 ) = tid; threads->nr =1 ;comm_init (threads,0 ); +atomic_set (&threads->refcnt,1 ); }return threads;
@@ -127,6 +130,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) goto out_free_threads; threads->nr =0 ; +atomic_set (&threads->refcnt,1 );while (!readdir_r (proc, &dirent, &next) && next) {char *end;
@@ -256,6 +260,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) out:strlist__delete (slist); +if (threads) +atomic_set (&threads->refcnt,1 );return threads; out_free_namelist:
@@ -276,6 +282,7 @@ struct thread_map *thread_map__new_dummy(void)thread_map__pid (threads,0 ) =-1 ; threads->nr =1 ;comm_init (threads,0 ); +atomic_set (&threads->refcnt,1 ); }return threads; }
@@ -319,6 +326,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)comm_init (threads, ntasks -1 ); } out: +if (threads) +atomic_set (&threads->refcnt,1 );return threads; out_free_threads:
@@ -338,16 +347,29 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,return thread_map__new_by_tid_str (tid); } -void thread_map__delete (struct thread_map *threads) +static void thread_map__delete (struct thread_map *threads) { -int i; -if (threads) { +int i; + +WARN_ONCE (atomic_read (&threads->refcnt) !=0 , +"thread map refcnt disbalanced\n" );for (i =0 ; i < threads->nr; i++)free (thread_map__comm (threads, i)); +free (threads); } +} -free (threads); +struct thread_map *thread_map__get (struct thread_map *map) +{ +atomic_inc (&map->refcnt); +return map; +} + +void thread_map__put (struct thread_map *map) +{ +if (map &&atomic_dec_and_test (&map->refcnt)) +thread_map__delete (map); }size_t thread_map__fprintf (struct thread_map *threads,FILE *fp)
tools/perf/util/thread_map.h +5 -2
@@ -3,6 +3,7 @@#include <sys/types.h> #include <stdio.h> +#include <linux/atomic.h> struct thread_map_data {pid_t pid;
@@ -10,6 +11,7 @@ struct thread_map_data { };struct thread_map { +atomic_t refcnt;int nr;struct thread_map_data map[]; };
@@ -23,11 +25,12 @@ 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__get (struct thread_map *map); +void thread_map__put (struct thread_map *map); +struct thread_map *thread_map__new_str (const char *pid,const char *tid,uid_t uid); -void thread_map__delete (struct thread_map *threads); -size_t thread_map__fprintf (struct thread_map *threads,FILE *fp);static inline int thread_map__nr (struct thread_map *threads)
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 07/30] perf tools: Add reference counting for thread_map object
Em Sun, Jun 14, 2015 at 10:19:22AM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding refference counting for
thread_mapobject, so it could be easily shared among other objects.Using
thread_map__putinsteadthread_map__deleteand makingthread_map__deletestatic.
<SNIP>
tools/perf/util/thread_map.c struct thread_map *thread_map__new_str(const char *pid, const char *tid, · line 373
Quoted 11 lines
tools/perf/util/thread_map.c +10
-0+struct thread_map *thread_map__get (struct thread_map *map) +{ +atomic_inc (&map->refcnt); +return map; +} + +void thread_map__put (struct thread_map *map) +{ +if (map &&atomic_dec_and_test (&map->refcnt)) +thread_map__delete (map); }
See comment on the other struct being refcounted, get/put should both accept NULL maps, to avoid having to check it in the users, just like with free().
- Arnaldo
Re: [PATCH 07/30] perf tools: Add reference counting for thread_map object
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Sun, Jun 14, 2015 at 10:19:22AM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding refference counting for
thread_mapobject, so it could be easily shared among other objects.Using
thread_map__putinsteadthread_map__deleteand makingthread_map__deletestatic.<SNIP>
Quoted 15 lines
tools/perf/util/thread_map.c struct thread_map *thread_map__new_str(const char *pid, const char *tid, · line 373
Quoted 11 lines
tools/perf/util/thread_map.c +10
-0+struct thread_map *thread_map__get (struct thread_map *map) +{ +atomic_inc (&map->refcnt); +return map; +} + +void thread_map__put (struct thread_map *map) +{ +if (map &&atomic_dec_and_test (&map->refcnt)) +thread_map__delete (map); }See comment on the other struct being refcounted, get/put should both accept NULL maps, to avoid having to check it in the users, just like with
free().
ook, will repost with the get function fix
thanks,
jirka
Jiri Olsa
reviewerPATCH v2 8/30 perf tools: Propagate cpu maps through the evlist
In reply to Jiri OlsaPropagate evlist's cpu_map object through all the evsel objects, while keeping already configured evsel->cpus.
It'll be handy to access evsel's cpus directly
in following patches.
--- tools/perf/util/evlist.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +23 -1
@@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); } +static int propagate_maps (struct perf_evlist *evlist,struct target *target) +{ +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +/* +* We already have cpus for evsel (via PMU sysfs) so +* keep it, if there's no target cpu list defined. +*/ +if (evsel->cpus && target->cpu_list) +cpu_map__put (evsel->cpus); + +if (!evsel->cpus || target->cpu_list) + evsel->cpus =cpu_map__get (evlist->cpus); + +if (!evsel->cpus) +return -ENOMEM ; + } + +return 0 ; +} +int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid,
@@ -1101,7 +1123,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return 0 ; +return propagate_maps (evlist, target); out_delete_threads:thread_map__put (evlist->threads);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 08/30] perf tools: Propagate cpu maps through the evlist
Em Sun, Jun 14, 2015 at 10:19:23AM +0200, Jiri Olsa escreveu:
Quoted 17 lines
Propagate evlist's
cpu_mapobject through all the evsel objects, while keeping already configuredevsel->cpus.It'll be handy to access evsel's cpus directly
in following patches.Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/evlist.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)tools/perf/util/evlist.c +0
-0
tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1088
Quoted 4 lines
tools/perf/util/evlist.c +1
-0@@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); } +static int propagate_maps (struct perf_evlist *evlist,struct target *target)
Please rename this to perf_evlist__set_maps()
tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1094
Quoted 6 lines
tools/perf/util/evlist.c +5
-0+{ +struct perf_evsel *evsel; +evlist__for_each (evlist, evsel) { +/* +* We already have cpus for evsel (via PMU sysfs) so
If we already...
tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1095
Quoted 1 line
tools/perf/util/evlist.c +1
-0+* keep it, if there's no target cpu list defined.
^ The comma here confused me
tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1098
Quoted 3 lines
tools/perf/util/evlist.c +3
-0+*/ +if (evsel->cpus && target->cpu_list) +cpu_map__put (evsel->cpus);
If you drop the reference, and then will test it... use a cpu_map__zput(&evsel->cpus), so that after the put you don't access something you don't hold a reference for anymore...
But the logic is still confusing! Can you try to rewrite it in a more clear way?
tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1101
Quoted 2 lines
tools/perf/util/evlist.c +2
-0+if (!evsel->cpus || target->cpu_list) + evsel->cpus =cpu_map__get (evlist->cpus);
Something like:
if (evsel->cpus) {
something
} else {
something else
}tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1104
Quoted 3 lines
tools/perf/util/evlist.c +3
-0+ +if (!evsel->cpus) +return -ENOMEM ;
Where was that we tried to allocate memory in this operation?
Quoted 19 lines
tools/perf/util/evlist.c +6
-1+ } + +return 0 ; +} +int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid,@@ -1101,7 +1123,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return 0 ; +return propagate_maps (evlist, target); out_delete_threads:thread_map__put (evlist->threads);Signature · 1 line
1.9.3
Re: [PATCH 08/30] perf tools: Propagate cpu maps through the evlist
Quoted 21 lines · Arnaldo Carvalho de Melo
Em Sun, Jun 14, 2015 at 10:19:23AM +0200, Jiri Olsa escreveu:
Quoted 20 lines
Propagate evlist's
cpu_mapobject through all the evsel objects, while keeping already configuredevsel->cpus.It'll be handy to access evsel's cpus directly
in following patches.Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/evlist.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)tools/perf/util/evlist.c +0
-0@@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); }
Quoted 3 lines
tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1088
Quoted 1 line
tools/perf/util/evlist.c +1
-0+static int propagate_maps (struct perf_evlist *evlist,struct target *target)Please rename this to
perf_evlist__set_maps()
we already have this one.. how about perf_evlist__ropagate_maps ?
jirka
Jiri Olsa
reviewerPATCH v2 9/30 perf tools: Propagate thread maps through the evlist
In reply to Jiri OlsaPropagate evlist's thread_map object through all the evsel objects.
It'll be handy to access evsel's threads directly in following patches. The reason is there's no link from evsel to evlist which hold threads map now and evlist is not always available.
--- tools/perf/util/evlist.c | 4 +++- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +3 -1
@@ -1100,7 +1100,9 @@ static int propagate_maps(struct perf_evlist *evlist, struct target *target)if (!evsel->cpus || target->cpu_list) evsel->cpus =cpu_map__get (evlist->cpus); -if (!evsel->cpus) + evsel->threads =thread_map__get (evlist->threads); + +if (!evsel->cpus || !evsel->threads)return -ENOMEM ; }
tools/perf/util/evsel.c +1 -0
@@ -903,6 +903,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)perf_evsel__free_id (evsel);close_cgroup (evsel->cgrp);cpu_map__put (evsel->cpus); +thread_map__put (evsel->threads);zfree (&evsel->group_name);zfree (&evsel->name); perf_evsel__object.fini (evsel);
tools/perf/util/evsel.h +1 -0
@@ -82,6 +82,7 @@ struct perf_evsel {struct cgroup_sel *cgrp;void *handler;struct cpu_map *cpus; +struct thread_map *threads;unsigned int sample_size;int id_pos;int is_pos;
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 10/30 perf tools: Make perf_evsel__(nr_)cpus generic
In reply to Jiri OlsaBecause we now propagate all evlist's cpu_maps and thread_map objects through all evsels, the perf_evsel__(nr_)cpus no longer need to be specific to stat object and check evlist and target objects.
--- tools/perf/builtin-stat.c | 10 ---------- tools/perf/util/evsel.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-)
tools/perf/builtin-stat.c +0 -10
@@ -141,16 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static inline struct cpu_map *perf_evsel__cpus (struct perf_evsel *evsel) -{ -return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; -} - -static inline int perf_evsel__nr_cpus (struct perf_evsel *evsel) -{ -return perf_evsel__cpus (evsel)->nr; -} -static void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) {int i;
tools/perf/util/evsel.h +11 -0
@@ -8,6 +8,7 @@#include <linux/types.h> #include "xyarray.h" #include "symbol.h" +#include "cpumap.h" struct perf_counts_values { union {
@@ -114,6 +115,16 @@ struct thread_map;struct perf_evlist ;struct record_opts ; +static inline struct cpu_map *perf_evsel__cpus (struct perf_evsel *evsel) +{ +return evsel->cpus; +} + +static inline int perf_evsel__nr_cpus (struct perf_evsel *evsel) +{ +return perf_evsel__cpus (evsel)->nr; +} +void perf_counts_values__scale (struct perf_counts_values *count,bool scale,s8 *pscaled);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 11/30 perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object
In reply to Jiri OlsaIt's stat specific. Updating python build objects with stat.c.
--- tools/perf/tests/openat-syscall-all-cpus.c | 1 + tools/perf/util/evsel.c | 19 +------------------ tools/perf/util/evsel.h | 3 --- tools/perf/util/python-ext-sources | 1 + tools/perf/util/stat.c | 18 ++++++++++++++++++ tools/perf/util/stat.h | 3 +++ 6 files changed, 24 insertions(+), 21 deletions(-)
tools/perf/tests/openat-syscall-all-cpus.c +1 -0
@@ -3,6 +3,7 @@#include "thread_map.h" #include "cpumap.h" #include "debug.h" +#include "stat.h" int test__openat_syscall_event_on_all_cpus (void ) {
tools/perf/util/evsel.c +1 -18
@@ -26,6 +26,7 @@#include "perf_regs.h" #include "debug.h" #include "trace-event.h" +#include "stat.h" static struct { bool sample_id_all;
@@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) -{ -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); -} - -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) -{ - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); -return evsel->counts !=NULL ?0 : -ENOMEM ; -} -static void perf_evsel__free_fd (struct perf_evsel *evsel) {xyarray__delete (evsel->fd);
@@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) } } -void perf_evsel__free_counts (struct perf_evsel *evsel) -{ -zfree (&evsel->counts); -} -void perf_evsel__exit (struct perf_evsel *evsel) {assert (list_empty (&evsel->node));
tools/perf/util/evsel.h +0 -3
@@ -182,9 +182,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);int perf_evsel__group_desc (struct perf_evsel *evsel,char *buf,size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads); -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads); void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
tools/perf/util/python-ext-sources +1 -0
@@ -20,3 +20,4 @@ util/strlist.c util/trace-event.c ../../lib/rbtree.c util/string.c +util/stat.c
tools/perf/util/stat.c +18 -0
@@ -94,3 +94,21 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } } + +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) +{ +memset (evsel->counts,0 , (sizeof (*evsel->counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} + +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) +{ + evsel->counts =zalloc ((sizeof (*evsel->counts) + + (ncpus *sizeof (struct perf_counts_values )))); +return evsel->counts !=NULL ?0 : -ENOMEM ; +} + +void perf_evsel__free_counts (struct perf_evsel *evsel) +{ +zfree (&evsel->counts); +}
tools/perf/util/stat.h +3 -0
@@ -62,4 +62,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu,enum aggr_mode aggr); +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); +void perf_evsel__free_counts (struct perf_evsel *evsel);#endif
Signature · 1 line
1.9.3
Re: [PATCH 11/30] perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object
Em Sun, Jun 14, 2015 at 10:19:26AM +0200, Jiri Olsa escreveu:
Quoted 4 lines
It's stat specific. Updating python build objects with
stat.c.Signed-off-by Jiri Olsa <[email protected]>
thanks, applied.
- Arnaldo
Quoted 128 lines
--- tools/perf/tests/openat-syscall-all-cpus.c | 1 + tools/perf/util/evsel.c | 19 +------------------ tools/perf/util/evsel.h | 3 --- tools/perf/util/python-ext-sources | 1 + tools/perf/util/stat.c | 18 ++++++++++++++++++ tools/perf/util/stat.h | 3 +++ 6 files changed, 24 insertions(+), 21 deletions(-)tools/perf/tests/openat-syscall-all-cpus.c +1
-0@@ -3,6 +3,7 @@#include "thread_map.h" #include "cpumap.h" #include "debug.h" +#include "stat.h" int test__openat_syscall_event_on_all_cpus (void ) {tools/perf/util/evsel.c +1
-18@@ -26,6 +26,7 @@#include "perf_regs.h" #include "debug.h" #include "trace-event.h" +#include "stat.h" static struct { bool sample_id_all;@@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) -{ -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); -} - -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) -{ - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); -return evsel->counts !=NULL ?0 : -ENOMEM ; -} -static void perf_evsel__free_fd (struct perf_evsel *evsel) {xyarray__delete (evsel->fd);@@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) } } -void perf_evsel__free_counts (struct perf_evsel *evsel) -{ -zfree (&evsel->counts); -} -void perf_evsel__exit (struct perf_evsel *evsel) {assert (list_empty (&evsel->node));tools/perf/util/evsel.h +0
-3@@ -182,9 +182,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);int perf_evsel__group_desc (struct perf_evsel *evsel,char *buf,size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads); -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads); void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,tools/perf/util/python-ext-sources +1
-0@@ -20,3 +20,4 @@ util/strlist.c util/trace-event.c ../../lib/rbtree.c util/string.c +util/stat.ctools/perf/util/stat.c +18
-0@@ -94,3 +94,21 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } } + +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) +{ +memset (evsel->counts,0 , (sizeof (*evsel->counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} + +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) +{ + evsel->counts =zalloc ((sizeof (*evsel->counts) + + (ncpus *sizeof (struct perf_counts_values )))); +return evsel->counts !=NULL ?0 : -ENOMEM ; +} + +void perf_evsel__free_counts (struct perf_evsel *evsel) +{ +zfree (&evsel->counts); +}tools/perf/util/stat.h +3
-0@@ -62,4 +62,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu,enum aggr_mode aggr); +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); +void perf_evsel__free_counts (struct perf_evsel *evsel);#endif Signature · 1 line
1.9.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf tools: Move perf_evsel__(alloc|free|reset) _counts into stat object
In reply to Jiri Olsaperf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object
Commit-ID: a9a3a4d92d8f2fb68f4b99d98505bebc70518599 Gitweb: http://git.kernel.org/tip/a9a3a4d92d8f2fb68f4b99d98505bebc70518599 Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Jun 2015 10:19:26 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Jun 2015 10:34:40 -0300
perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object
It's stat specific. Updating python build objects with stat.c.
--- tools/perf/tests/openat-syscall-all-cpus.c | 1 + tools/perf/util/evsel.c | 19 +------------------ tools/perf/util/evsel.h | 3 --- tools/perf/util/python-ext-sources | 1 + tools/perf/util/stat.c | 18 ++++++++++++++++++ tools/perf/util/stat.h | 3 +++ 6 files changed, 24 insertions(+), 21 deletions(-)
tools/perf/tests/openat-syscall-all-cpus.c +1 -0
@@ -3,6 +3,7 @@#include "thread_map.h" #include "cpumap.h" #include "debug.h" +#include "stat.h" int test__openat_syscall_event_on_all_cpus (void ) {
tools/perf/util/evsel.c +1 -18
@@ -26,6 +26,7 @@#include "perf_regs.h" #include "debug.h" #include "trace-event.h" +#include "stat.h" static struct { bool sample_id_all;
@@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) -{ -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); -} - -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) -{ - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); -return evsel->counts !=NULL ?0 : -ENOMEM ; -} -static void perf_evsel__free_fd (struct perf_evsel *evsel) {xyarray__delete (evsel->fd);
@@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) } } -void perf_evsel__free_counts (struct perf_evsel *evsel) -{ -zfree (&evsel->counts); -} -void perf_evsel__exit (struct perf_evsel *evsel) {assert (list_empty (&evsel->node));
tools/perf/util/evsel.h +0 -3
@@ -170,9 +170,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);int perf_evsel__group_desc (struct perf_evsel *evsel,char *buf,size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads); -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads); void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
tools/perf/util/python-ext-sources +1 -0
@@ -16,6 +16,7 @@ util/util.c util/xyarray.c util/cgroup.c util/rblist.c +util/stat.c util/strlist.c util/trace-event.c ../../lib/rbtree.c
tools/perf/util/stat.c +18 -0
@@ -94,3 +94,21 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } } + +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) +{ +memset (evsel->counts,0 , (sizeof (*evsel->counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} + +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) +{ + evsel->counts =zalloc ((sizeof (*evsel->counts) + + (ncpus *sizeof (struct perf_counts_values )))); +return evsel->counts !=NULL ?0 : -ENOMEM ; +} + +void perf_evsel__free_counts (struct perf_evsel *evsel) +{ +zfree (&evsel->counts); +}
tools/perf/util/stat.h +3 -0
@@ -62,4 +62,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu,enum aggr_mode aggr); +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); +void perf_evsel__free_counts (struct perf_evsel *evsel);#endif
Jiri Olsa
reviewerPATCH v2 12/30 perf stat: Introduce perf_counts__(alloc|free|reset) functions
In reply to Jiri OlsaMove 'struct perf_counts' allocation|free|reset code into separate functions.
--- tools/perf/builtin-stat.c | 19 +++++++------------ tools/perf/util/stat.c | 28 +++++++++++++++++++++++----- tools/perf/util/stat.h | 3 +++ 3 files changed, 33 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +7 -12
@@ -168,24 +168,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel) { -void *addr; -size_t sz; +struct perf_counts *counts; - sz =sizeof (*evsel->counts) + - (perf_evsel__nr_cpus (evsel) *sizeof (struct perf_counts_values )); + counts =perf_counts__new (perf_evsel__nr_cpus (evsel)); +if (counts) + evsel->prev_raw_counts = counts; - addr =zalloc (sz); -if (!addr) -return -ENOMEM ; - - evsel->prev_raw_counts = addr; - -return 0 ; +return counts ?0 : -ENOMEM ; }static void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel) { -zfree (&evsel->prev_raw_counts); +perf_counts__delete (evsel->prev_raw_counts); + evsel->prev_raw_counts =NULL ; }static void perf_evlist__free_stats (struct perf_evlist *evlist)
tools/perf/util/stat.c +23 -5
@@ -95,20 +95,38 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } +struct perf_counts *perf_counts__new (int ncpus) +{ +int size =sizeof (struct perf_counts ) + + ncpus *sizeof (struct perf_counts_values ); + +return zalloc (size); +} + +void perf_counts__delete (struct perf_counts *counts) +{ +free (counts); +} + +static void perf_counts__reset (struct perf_counts *counts,int ncpus) +{ +memset (counts,0 , (sizeof (*counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) { -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); +perf_counts__reset (evsel->counts, ncpus); }int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) { - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); + evsel->counts =perf_counts__new (ncpus);return evsel->counts !=NULL ?0 : -ENOMEM ; }void perf_evsel__free_counts (struct perf_evsel *evsel) { -zfree (&evsel->counts); +perf_counts__delete (evsel->counts); + evsel->counts =NULL ; }
tools/perf/util/stat.h +3 -0
@@ -62,6 +62,9 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu,enum aggr_mode aggr); +struct perf_counts *perf_counts__new (int ncpus); +void perf_counts__delete (struct perf_counts *counts); +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus);void perf_evsel__free_counts (struct perf_evsel *evsel);
Signature · 1 line
1.9.3
Re: [PATCH 12/30] perf stat: Introduce perf_counts__(alloc|free|reset) functions
Em Sun, Jun 14, 2015 at 10:19:27AM +0200, Jiri Olsa escreveu:
Quoted 2 lines
Move 'struct
perf_counts' allocation|free|reset code into separate functions.
Applied, after fixing up the Subject to match new/delete.
- Arnaldo
Quoted 108 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/builtin-stat.c | 19 +++++++------------ tools/perf/util/stat.c | 28 +++++++++++++++++++++++----- tools/perf/util/stat.h | 3 +++ 3 files changed, 33 insertions(+), 17 deletions(-)tools/perf/builtin-stat.c +7
-12@@ -168,24 +168,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel) { -void *addr; -size_t sz; +struct perf_counts *counts; - sz =sizeof (*evsel->counts) + - (perf_evsel__nr_cpus (evsel) *sizeof (struct perf_counts_values )); + counts =perf_counts__new (perf_evsel__nr_cpus (evsel)); +if (counts) + evsel->prev_raw_counts = counts; - addr =zalloc (sz); -if (!addr) -return -ENOMEM ; - - evsel->prev_raw_counts = addr; - -return 0 ; +return counts ?0 : -ENOMEM ; }static void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel) { -zfree (&evsel->prev_raw_counts); +perf_counts__delete (evsel->prev_raw_counts); + evsel->prev_raw_counts =NULL ; }static void perf_evlist__free_stats (struct perf_evlist *evlist)tools/perf/util/stat.c +23
-5@@ -95,20 +95,38 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } +struct perf_counts *perf_counts__new (int ncpus) +{ +int size =sizeof (struct perf_counts ) + + ncpus *sizeof (struct perf_counts_values ); + +return zalloc (size); +} + +void perf_counts__delete (struct perf_counts *counts) +{ +free (counts); +} + +static void perf_counts__reset (struct perf_counts *counts,int ncpus) +{ +memset (counts,0 , (sizeof (*counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) { -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); +perf_counts__reset (evsel->counts, ncpus); }int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) { - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); + evsel->counts =perf_counts__new (ncpus);return evsel->counts !=NULL ?0 : -ENOMEM ; }void perf_evsel__free_counts (struct perf_evsel *evsel) { -zfree (&evsel->counts); +perf_counts__delete (evsel->counts); + evsel->counts =NULL ; }tools/perf/util/stat.h +3
-0@@ -62,6 +62,9 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu,enum aggr_mode aggr); +struct perf_counts *perf_counts__new (int ncpus); +void perf_counts__delete (struct perf_counts *counts); +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus);void perf_evsel__free_counts (struct perf_evsel *evsel);Signature · 1 line
1.9.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf stat: Introduce perf_counts__( new|delete|reset) functions
In reply to Jiri Olsaperf stat: Introduce perf_counts__(new|delete|reset) functions
Commit-ID: 9df38e82e2a103cf42177c164a4de9d58052ac3a Gitweb: http://git.kernel.org/tip/9df38e82e2a103cf42177c164a4de9d58052ac3a Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Jun 2015 10:19:27 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Jun 2015 10:34:41 -0300
perf stat: Introduce perf_counts__(new|delete|reset) functions
Move 'struct perf_counts' allocation|free|reset code into separate functions.
--- tools/perf/builtin-stat.c | 19 +++++++------------ tools/perf/util/stat.c | 28 +++++++++++++++++++++++----- tools/perf/util/stat.h | 3 +++ 3 files changed, 33 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +7 -12
@@ -178,24 +178,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel) { -void *addr; -size_t sz; +struct perf_counts *counts; - sz =sizeof (*evsel->counts) + - (perf_evsel__nr_cpus (evsel) *sizeof (struct perf_counts_values )); + counts =perf_counts__new (perf_evsel__nr_cpus (evsel)); +if (counts) + evsel->prev_raw_counts = counts; - addr =zalloc (sz); -if (!addr) -return -ENOMEM ; - - evsel->prev_raw_counts = addr; - -return 0 ; +return counts ?0 : -ENOMEM ; }static void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel) { -zfree (&evsel->prev_raw_counts); +perf_counts__delete (evsel->prev_raw_counts); + evsel->prev_raw_counts =NULL ; }static void perf_evlist__free_stats (struct perf_evlist *evlist)
tools/perf/util/stat.c +23 -5
@@ -95,20 +95,38 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } +struct perf_counts *perf_counts__new (int ncpus) +{ +int size =sizeof (struct perf_counts ) + + ncpus *sizeof (struct perf_counts_values ); + +return zalloc (size); +} + +void perf_counts__delete (struct perf_counts *counts) +{ +free (counts); +} + +static void perf_counts__reset (struct perf_counts *counts,int ncpus) +{ +memset (counts,0 , (sizeof (*counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) { -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); +perf_counts__reset (evsel->counts, ncpus); }int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) { - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); + evsel->counts =perf_counts__new (ncpus);return evsel->counts !=NULL ?0 : -ENOMEM ; }void perf_evsel__free_counts (struct perf_evsel *evsel) { -zfree (&evsel->counts); +perf_counts__delete (evsel->counts); + evsel->counts =NULL ; }
tools/perf/util/stat.h +3 -0
@@ -62,6 +62,9 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu,enum aggr_mode aggr); +struct perf_counts *perf_counts__new (int ncpus); +void perf_counts__delete (struct perf_counts *counts); +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus);void perf_evsel__free_counts (struct perf_evsel *evsel);
Jiri Olsa
reviewerPATCH v2 13/30 perf stat: Introduce perf_counts function
In reply to Jiri OlsaIntroducing perf_counts function, that returns 'struct perf_counts_values' pointer for given cpu.
Also moving perf_counts* structures into stat.h.
--- tools/perf/builtin-stat.c | 14 +++++++------- tools/perf/tests/openat-syscall-all-cpus.c | 4 ++-- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/util/evsel.c | 6 +++--- tools/perf/util/evsel.h | 18 +----------------- tools/perf/util/stat.h | 23 +++++++++++++++++++++++ 6 files changed, 37 insertions(+), 30 deletions(-)
tools/perf/builtin-stat.c +7 -7
@@ -316,7 +316,7 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, count);perf_counts_values__scale (count, scale,NULL ); - evsel->counts->cpu[cpu] = *count; + *perf_counts (evsel->counts, cpu) = *count;if (aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;
@@ -805,9 +805,9 @@ static void print_aggr(char *prefix) s2 =aggr_get_id (evsel_list->cpus, cpu2);if (s2 != id)continue ; - val += counter->counts->cpu[cpu].val; - ena += counter->counts->cpu[cpu].ena; - run += counter->counts->cpu[cpu].run; + val +=perf_counts (counter->counts, cpu)->val; + ena +=perf_counts (counter->counts, cpu)->ena; + run +=perf_counts (counter->counts, cpu)->run; nr++; }if (prefix)
@@ -915,9 +915,9 @@ static void print_counter(struct perf_evsel *counter, char *prefix)int cpu;for (cpu =0 ; cpu <perf_evsel__nr_cpus (counter); cpu++) { - val = counter->counts->cpu[cpu].val; - ena = counter->counts->cpu[cpu].ena; - run = counter->counts->cpu[cpu].run; + val =perf_counts (counter->counts, cpu)->val; + ena =perf_counts (counter->counts, cpu)->ena; + run =perf_counts (counter->counts, cpu)->run;if (prefix)fprintf (output,"%s" , prefix);
tools/perf/tests/openat-syscall-all-cpus.c +2 -2
@@ -98,9 +98,9 @@ int test__openat_syscall_event_on_all_cpus(void) } expected = nr_openat_calls + cpu; -if (evsel->counts->cpu[cpu].val != expected) { +if (perf_counts (evsel->counts, cpu)->val != expected) {pr_debug ("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64"\n" , - expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); + expected, cpus->map[cpu],perf_counts (evsel->counts, cpu)->val); err =-1 ; } }
tools/perf/tests/openat-syscall.c +1 -1
@@ -44,7 +44,7 @@ int test__openat_syscall_event(void) goto out_close_fd; } -if (evsel->counts->cpu[0 ].val != nr_openat_calls) { +if (perf_counts (evsel->counts,0 )->val != nr_openat_calls) {pr_debug ("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64"\n" , nr_openat_calls, evsel->counts->cpu[0 ].val); goto out_close_fd;
tools/perf/util/evsel.c +3 -3
@@ -910,8 +910,8 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, tmp = evsel->prev_raw_counts->aggr; evsel->prev_raw_counts->aggr = *count; }else { - tmp = evsel->prev_raw_counts->cpu[cpu]; - evsel->prev_raw_counts->cpu[cpu] = *count; + tmp = *perf_counts (evsel->prev_raw_counts, cpu); + *perf_counts (evsel->prev_raw_counts, cpu) = *count; } count->val = count->val - tmp.val;
@@ -972,7 +972,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,perf_evsel__compute_deltas (evsel, cpu, &count);perf_counts_values__scale (&count, scale,NULL ); - evsel->counts->cpu[cpu] = count; + *perf_counts (evsel->counts, cpu) = count;return 0 ; }
tools/perf/util/evsel.h +1 -17
@@ -9,23 +9,7 @@#include "xyarray.h" #include "symbol.h" #include "cpumap.h" - -struct perf_counts_values { -union { -struct { -u64 val; -u64 ena; -u64 run; - }; -u64 values[3 ]; - }; -}; - -struct perf_counts { -s8 scaled; -struct perf_counts_values aggr; -struct perf_counts_values cpu[]; -}; +#include "stat.h" struct perf_evsel ;
tools/perf/util/stat.h +23 -0
@@ -31,6 +31,29 @@ enum aggr_mode { AGGR_CORE, }; +struct perf_counts_values { +union { +struct { +u64 val; +u64 ena; +u64 run; + }; +u64 values[3 ]; + }; +}; + +struct perf_counts { +s8 scaled; +struct perf_counts_values aggr; +struct perf_counts_values cpu[]; +}; + +static inline struct perf_counts_values * +perf_counts (struct perf_counts *counts,int cpu) +{ +return &counts->cpu[cpu]; +} +void update_stats (struct stats *stats,u64 val);double avg_stats (struct stats *stats);double stddev_stats (struct stats *stats);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 14/30 perf stat: Use xyarray for cpu evsel counts
In reply to Jiri OlsaSwitching single dimensional array of 'struct perf_counts_values' with xyarray object, so we could store thread dimension counts.
--- tools/perf/builtin-stat.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/util/stat.c | 31 ++++++++++++++++++++++--------- tools/perf/util/stat.h | 7 ++++--- 4 files changed, 28 insertions(+), 14 deletions(-)
tools/perf/builtin-stat.c +1 -1
@@ -218,7 +218,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)evlist__for_each (evlist, evsel) {perf_evsel__reset_stat_priv (evsel); -perf_evsel__reset_counts (evsel,perf_evsel__nr_cpus (evsel)); +perf_evsel__reset_counts (evsel); }perf_stat__reset_shadow_stats ();
tools/perf/tests/openat-syscall.c +1 -1
@@ -46,7 +46,7 @@ int test__openat_syscall_event(void)if (perf_counts (evsel->counts,0 )->val != nr_openat_calls) {pr_debug ("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64"\n" , - nr_openat_calls, evsel->counts->cpu[0 ].val); + nr_openat_calls,perf_counts (evsel->counts,0 )->val); goto out_close_fd; }
tools/perf/util/stat.c +22 -9
@@ -97,26 +97,39 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)struct perf_counts *perf_counts__new (int ncpus) { -int size =sizeof (struct perf_counts ) + - ncpus *sizeof (struct perf_counts_values ); +struct perf_counts *counts =zalloc (sizeof (*counts)); -return zalloc (size); +if (counts) { +struct xyarray *cpu; + + cpu =xyarray__new (ncpus,1 ,sizeof (struct perf_counts_values )); +if (!cpu) { +free (counts); +return NULL ; + } + + counts->cpu = cpu; + } + +return counts; }void perf_counts__delete (struct perf_counts *counts) { -free (counts); +if (counts) { +xyarray__delete (counts->cpu); +free (counts); + } } -static void perf_counts__reset (struct perf_counts *counts,int ncpus) +static void perf_counts__reset (struct perf_counts *counts) { -memset (counts,0 , (sizeof (*counts) + - (ncpus *sizeof (struct perf_counts_values )))); +xyarray__reset (counts->cpu); } -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) +void perf_evsel__reset_counts (struct perf_evsel *evsel) { -perf_counts__reset (evsel->counts, ncpus); +perf_counts__reset (evsel->counts); }int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus)
tools/perf/util/stat.h +4 -3
@@ -3,6 +3,7 @@#include <linux/types.h> #include <stdio.h> +#include "xyarray.h" struct stats {
@@ -45,13 +46,13 @@ struct perf_counts_values {struct perf_counts {s8 scaled;struct perf_counts_values aggr; -struct perf_counts_values cpu[]; +struct xyarray *cpu; };static inline struct perf_counts_values *perf_counts (struct perf_counts *counts,int cpu) { -return &counts->cpu[cpu]; +return xyarray__entry (counts->cpu, cpu,0 ); }void update_stats (struct stats *stats,u64 val);
@@ -88,7 +89,7 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,struct perf_counts *perf_counts__new (int ncpus);void perf_counts__delete (struct perf_counts *counts); -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); +void perf_evsel__reset_counts (struct perf_evsel *evsel);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus);void perf_evsel__free_counts (struct perf_evsel *evsel);#endif
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 15/30 perf stat: Make stats work over the thread dimension
In reply to Jiri OlsaNow that we have space for thread dimension counts, let's store it.
--- tools/perf/builtin-stat.c | 32 +++++++++++++++++------------- tools/perf/tests/openat-syscall-all-cpus.c | 6 +++--- tools/perf/tests/openat-syscall.c | 4 ++-- tools/perf/util/evsel.c | 12 +++++------ tools/perf/util/evsel.h | 2 +- tools/perf/util/stat.c | 8 ++++---- tools/perf/util/stat.h | 8 ++++---- 7 files changed, 38 insertions(+), 34 deletions(-)
tools/perf/builtin-stat.c +18 -14
@@ -166,11 +166,12 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)zfree (&evsel->priv); } -static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel) +static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel, +int ncpus,int nthreads) {struct perf_counts *counts; - counts =perf_counts__new (perf_evsel__nr_cpus (evsel)); + counts =perf_counts__new (ncpus, nthreads);if (counts) evsel->prev_raw_counts = counts;
@@ -197,11 +198,14 @@ static void perf_evlist__free_stats(struct perf_evlist *evlist)static int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) {struct perf_evsel *evsel; +int nthreads =thread_map__nr (evsel_list->threads);evlist__for_each (evlist, evsel) { +int ncpus =perf_evsel__nr_cpus (evsel); +if (perf_evsel__alloc_stat_priv (evsel) <0 || -perf_evsel__alloc_counts (evsel,perf_evsel__nr_cpus (evsel)) <0 || - (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel) <0 )) +perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || + (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) goto out_free; }
@@ -294,7 +298,7 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)return 0 ; } -static int read_cb (struct perf_evsel *evsel,int cpu,int thread__maybe_unused , +static int read_cb (struct perf_evsel *evsel,int cpu,int thread,struct perf_counts_values *count) {struct perf_counts_values *aggr = &evsel->counts->aggr;
@@ -314,9 +318,9 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,case AGGR_SOCKET :case AGGR_NONE :if (!evsel->snapshot) -perf_evsel__compute_deltas (evsel, cpu, count); +perf_evsel__compute_deltas (evsel, cpu, thread, count);perf_counts_values__scale (count, scale,NULL ); - *perf_counts (evsel->counts, cpu) = *count; + *perf_counts (evsel->counts, cpu, thread) = *count;if (aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;
@@ -352,7 +356,7 @@ static int read_counter_aggr(struct perf_evsel *counter)return -1 ;if (!counter->snapshot) -perf_evsel__compute_deltas (counter,-1 , aggr); +perf_evsel__compute_deltas (counter,-1 ,-1 , aggr);perf_counts_values__scale (aggr, scale, &counter->counts->scaled);for (i =0 ; i <3 ; i++)
@@ -805,9 +809,9 @@ static void print_aggr(char *prefix) s2 =aggr_get_id (evsel_list->cpus, cpu2);if (s2 != id)continue ; - val +=perf_counts (counter->counts, cpu)->val; - ena +=perf_counts (counter->counts, cpu)->ena; - run +=perf_counts (counter->counts, cpu)->run; + val +=perf_counts (counter->counts, cpu,0 )->val; + ena +=perf_counts (counter->counts, cpu,0 )->ena; + run +=perf_counts (counter->counts, cpu,0 )->run; nr++; }if (prefix)
@@ -915,9 +919,9 @@ static void print_counter(struct perf_evsel *counter, char *prefix)int cpu;for (cpu =0 ; cpu <perf_evsel__nr_cpus (counter); cpu++) { - val =perf_counts (counter->counts, cpu)->val; - ena =perf_counts (counter->counts, cpu)->ena; - run =perf_counts (counter->counts, cpu)->run; + val =perf_counts (counter->counts, cpu,0 )->val; + ena =perf_counts (counter->counts, cpu,0 )->ena; + run =perf_counts (counter->counts, cpu,0 )->run;if (prefix)fprintf (output,"%s" , prefix);
tools/perf/tests/openat-syscall-all-cpus.c +3 -3
@@ -78,7 +78,7 @@ int test__openat_syscall_event_on_all_cpus(void)* we use the auto allocation it will allocate just for 1 cpu, * as we start by cpu 0. */ -if (perf_evsel__alloc_counts (evsel, cpus->nr) <0 ) { +if (perf_evsel__alloc_counts (evsel, cpus->nr,1 ) <0 ) {pr_debug ("perf_evsel__alloc_counts(ncpus=%d)\n" , cpus->nr); goto out_close_fd; }
@@ -98,9 +98,9 @@ int test__openat_syscall_event_on_all_cpus(void) } expected = nr_openat_calls + cpu; -if (perf_counts (evsel->counts, cpu)->val != expected) { +if (perf_counts (evsel->counts, cpu,0 )->val != expected) {pr_debug ("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64"\n" , - expected, cpus->map[cpu],perf_counts (evsel->counts, cpu)->val); + expected, cpus->map[cpu],perf_counts (evsel->counts, cpu,0 )->val); err =-1 ; } }
tools/perf/tests/openat-syscall.c +2 -2
@@ -44,9 +44,9 @@ int test__openat_syscall_event(void) goto out_close_fd; } -if (perf_counts (evsel->counts,0 )->val != nr_openat_calls) { +if (perf_counts (evsel->counts,0 ,0 )->val != nr_openat_calls) {pr_debug ("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64"\n" , - nr_openat_calls,perf_counts (evsel->counts,0 )->val); + nr_openat_calls,perf_counts (evsel->counts,0 ,0 )->val); goto out_close_fd; }
tools/perf/util/evsel.c +6 -6
@@ -898,7 +898,7 @@ void perf_evsel__delete(struct perf_evsel *evsel)free (evsel); } -void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu, +void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu,int thread,struct perf_counts_values *count) {struct perf_counts_values tmp;
@@ -910,8 +910,8 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, tmp = evsel->prev_raw_counts->aggr; evsel->prev_raw_counts->aggr = *count; }else { - tmp = *perf_counts (evsel->prev_raw_counts, cpu); - *perf_counts (evsel->prev_raw_counts, cpu) = *count; + tmp = *perf_counts (evsel->prev_raw_counts, cpu, thread); + *perf_counts (evsel->prev_raw_counts, cpu, thread) = *count; } count->val = count->val - tmp.val;
@@ -964,15 +964,15 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,if (FD (evsel, cpu, thread) <0 )return -EINVAL ; -if (evsel->counts ==NULL &&perf_evsel__alloc_counts (evsel, cpu +1 ) <0 ) +if (evsel->counts ==NULL &&perf_evsel__alloc_counts (evsel, cpu +1 , thread +1 ) <0 )return -ENOMEM ;if (readn (FD (evsel, cpu, thread), &count, nv *sizeof (u64)) <0 )return -errno; -perf_evsel__compute_deltas (evsel, cpu, &count); +perf_evsel__compute_deltas (evsel, cpu, thread, &count);perf_counts_values__scale (&count, scale,NULL ); - *perf_counts (evsel->counts, cpu) = count; + *perf_counts (evsel->counts, cpu, thread) = count;return 0 ; }
tools/perf/util/evsel.h +1 -1
@@ -112,7 +112,7 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)void perf_counts_values__scale (struct perf_counts_values *count,bool scale,s8 *pscaled); -void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu, +void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu,int thread,struct perf_counts_values *count); int perf_evsel__object_config(size_t object_size,
tools/perf/util/stat.c +4 -4
@@ -95,14 +95,14 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } -struct perf_counts *perf_counts__new (int ncpus) +struct perf_counts *perf_counts__new (int ncpus,int nthreads) {struct perf_counts *counts =zalloc (sizeof (*counts));if (counts) {struct xyarray *cpu; - cpu =xyarray__new (ncpus,1 ,sizeof (struct perf_counts_values )); + cpu =xyarray__new (ncpus, nthreads,sizeof (struct perf_counts_values ));if (!cpu) {free (counts);return NULL ;
@@ -132,9 +132,9 @@ void perf_evsel__reset_counts(struct perf_evsel *evsel)perf_counts__reset (evsel->counts); } -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus,int nthreads) { - evsel->counts =perf_counts__new (ncpus); + evsel->counts =perf_counts__new (ncpus, nthreads);return evsel->counts !=NULL ?0 : -ENOMEM ; }
tools/perf/util/stat.h +4 -4
@@ -50,9 +50,9 @@ struct perf_counts { };static inline struct perf_counts_values * -perf_counts (struct perf_counts *counts,int cpu) +perf_counts (struct perf_counts *counts,int cpu,int thread) { -return xyarray__entry (counts->cpu, cpu,0 ); +return xyarray__entry (counts->cpu, cpu, thread); }void update_stats (struct stats *stats,u64 val);
@@ -86,10 +86,10 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,void perf_stat__print_shadow_stats (FILE *out,struct perf_evsel *evsel,double avg,int cpu,enum aggr_mode aggr); -struct perf_counts *perf_counts__new (int ncpus); +struct perf_counts *perf_counts__new (int ncpus,int nthreads);void perf_counts__delete (struct perf_counts *counts);void perf_evsel__reset_counts (struct perf_evsel *evsel); -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus,int nthreads);void perf_evsel__free_counts (struct perf_evsel *evsel);#endif
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 16/30 perf stat: Rename struct perf_counts::cpu member to values
In reply to Jiri OlsaRenaming 'struct xyarray *cpu' pointer to more fitting/generic values, because now we store both cpu and thread values.
--- tools/perf/util/stat.c | 12 ++++++------ tools/perf/util/stat.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/util/stat.c +6 -6
@@ -100,15 +100,15 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads)struct perf_counts *counts =zalloc (sizeof (*counts));if (counts) { -struct xyarray *cpu; +struct xyarray *values; - cpu =xyarray__new (ncpus, nthreads,sizeof (struct perf_counts_values )); -if (!cpu) { + values =xyarray__new (ncpus, nthreads,sizeof (struct perf_counts_values )); +if (!values) {free (counts);return NULL ; } - counts->cpu = cpu; + counts->values = values; }return counts;
@@ -117,14 +117,14 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads)void perf_counts__delete (struct perf_counts *counts) {if (counts) { -xyarray__delete (counts->cpu); +xyarray__delete (counts->values);free (counts); } }static void perf_counts__reset (struct perf_counts *counts) { -xyarray__reset (counts->cpu); +xyarray__reset (counts->values); }void perf_evsel__reset_counts (struct perf_evsel *evsel)
tools/perf/util/stat.h +2 -2
@@ -46,13 +46,13 @@ struct perf_counts_values {struct perf_counts {s8 scaled;struct perf_counts_values aggr; -struct xyarray *cpu; +struct xyarray *values; };static inline struct perf_counts_values *perf_counts (struct perf_counts *counts,int cpu,int thread) { -return xyarray__entry (counts->cpu, cpu, thread); +return xyarray__entry (counts->values, cpu, thread); }void update_stats (struct stats *stats,u64 val);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 17/30 perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object
In reply to Jiri OlsaMoving perf_evsel__(alloc|free|reset)_stat_priv into stat object, so it could be used outside stat command in following patches.
--- tools/perf/builtin-stat.c | 25 ------------------------- tools/perf/util/stat.c | 25 +++++++++++++++++++++++++ tools/perf/util/stat.h | 4 ++++ 3 files changed, 29 insertions(+), 25 deletions(-)
tools/perf/builtin-stat.c +0 -25
@@ -141,31 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) -{ -int i; -struct perf_stat *ps = evsel->priv; - -for (i =0 ; i <3 ; i++) -init_stats (&ps->res_stats[i]); - -perf_stat_evsel_id_init (evsel); -} - -static int perf_evsel__alloc_stat_priv (struct perf_evsel *evsel) -{ - evsel->priv =zalloc (sizeof (struct perf_stat )); -if (evsel->priv ==NULL ) -return -ENOMEM ; -perf_evsel__reset_stat_priv (evsel); -return 0 ; -} - -static void perf_evsel__free_stat_priv (struct perf_evsel *evsel) -{ -zfree (&evsel->priv); -} -static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel,int ncpus,int nthreads) {
tools/perf/util/stat.c +25 -0
@@ -143,3 +143,28 @@ void perf_evsel__free_counts(struct perf_evsel *evsel)perf_counts__delete (evsel->counts); evsel->counts =NULL ; } + +void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) +{ +int i; +struct perf_stat *ps = evsel->priv; + +for (i =0 ; i <3 ; i++) +init_stats (&ps->res_stats[i]); + +perf_stat_evsel_id_init (evsel); +} + +int perf_evsel__alloc_stat_priv (struct perf_evsel *evsel) +{ + evsel->priv =zalloc (sizeof (struct perf_stat )); +if (evsel->priv ==NULL ) +return -ENOMEM ; +perf_evsel__reset_stat_priv (evsel); +return 0 ; +} + +void perf_evsel__free_stat_priv (struct perf_evsel *evsel) +{ +zfree (&evsel->priv); +}
tools/perf/util/stat.h +4 -0
@@ -92,4 +92,8 @@ void perf_counts__delete(struct perf_counts *counts);void perf_evsel__reset_counts (struct perf_evsel *evsel);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus,int nthreads);void perf_evsel__free_counts (struct perf_evsel *evsel); + +void perf_evsel__reset_stat_priv (struct perf_evsel *evsel); +int perf_evsel__alloc_stat_priv (struct perf_evsel *evsel); +void perf_evsel__free_stat_priv (struct perf_evsel *evsel);#endif
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 18/30 perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into stat object
In reply to Jiri OlsaMoving perf_evsel__(alloc|free)_prev_raw_counts into stat object, so it could be used in following patches.
--- tools/perf/builtin-stat.c | 18 ------------------ tools/perf/util/stat.c | 18 ++++++++++++++++++ tools/perf/util/stat.h | 4 ++++ 3 files changed, 22 insertions(+), 18 deletions(-)
tools/perf/builtin-stat.c +0 -18
@@ -141,24 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel, -int ncpus,int nthreads) -{ -struct perf_counts *counts; - - counts =perf_counts__new (ncpus, nthreads); -if (counts) - evsel->prev_raw_counts = counts; - -return counts ?0 : -ENOMEM ; -} - -static void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel) -{ -perf_counts__delete (evsel->prev_raw_counts); - evsel->prev_raw_counts =NULL ; -} -static void perf_evlist__free_stats (struct perf_evlist *evlist) {struct perf_evsel *evsel;
tools/perf/util/stat.c +18 -0
@@ -168,3 +168,21 @@ void perf_evsel__free_stat_priv(struct perf_evsel *evsel) {zfree (&evsel->priv); } + +int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel, +int ncpus,int nthreads) +{ +struct perf_counts *counts; + + counts =perf_counts__new (ncpus, nthreads); +if (counts) + evsel->prev_raw_counts = counts; + +return counts ?0 : -ENOMEM ; +} + +void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel) +{ +perf_counts__delete (evsel->prev_raw_counts); + evsel->prev_raw_counts =NULL ; +}
tools/perf/util/stat.h +4 -0
@@ -96,4 +96,8 @@ void perf_evsel__free_counts(struct perf_evsel *evsel);void perf_evsel__reset_stat_priv (struct perf_evsel *evsel);int perf_evsel__alloc_stat_priv (struct perf_evsel *evsel);void perf_evsel__free_stat_priv (struct perf_evsel *evsel); + +int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel, +int ncpus,int nthreads); +void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel);#endif
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 19/30 perf stat: Move perf_evlist__(alloc|free)_stats into evlist object
In reply to Jiri OlsaMoving perf_evlist__(alloc|free)_stats into evsel object, so it could be used in following patches.
--- tools/perf/builtin-stat.c | 32 -------------------------------- tools/perf/util/evlist.h | 1 - tools/perf/util/stat.c | 34 ++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 5 +++++ 4 files changed, 39 insertions(+), 33 deletions(-)
tools/perf/builtin-stat.c +0 -32
@@ -141,38 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static void perf_evlist__free_stats (struct perf_evlist *evlist) -{ -struct perf_evsel *evsel; - -evlist__for_each (evlist, evsel) { -perf_evsel__free_stat_priv (evsel); -perf_evsel__free_counts (evsel); -perf_evsel__free_prev_raw_counts (evsel); - } -} - -static int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) -{ -struct perf_evsel *evsel; -int nthreads =thread_map__nr (evsel_list->threads); - -evlist__for_each (evlist, evsel) { -int ncpus =perf_evsel__nr_cpus (evsel); - -if (perf_evsel__alloc_stat_priv (evsel) <0 || -perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || - (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) - goto out_free; - } - -return 0 ; - -out_free: -perf_evlist__free_stats (evlist); -return -1 ; -} -static void perf_stat__reset_stats (struct perf_evlist *evlist) {struct perf_evsel *evsel;
tools/perf/util/evlist.h +0 -1
@@ -287,5 +287,4 @@ void perf_evlist__to_front(struct perf_evlist *evlist,void perf_evlist__set_tracking_event (struct perf_evlist *evlist,struct perf_evsel *tracking_evsel); -#endif /* __PERF_EVLIST_H */
tools/perf/util/stat.c +34 -0
@@ -1,6 +1,8 @@#include <math.h> #include "stat.h" +#include "evlist.h" #include "evsel.h" +#include "thread_map.h" void update_stats (struct stats *stats,u64 val) {
@@ -186,3 +188,35 @@ void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)perf_counts__delete (evsel->prev_raw_counts); evsel->prev_raw_counts =NULL ; } + +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) +{ +struct perf_evsel *evsel; +int nthreads =thread_map__nr (evlist->threads); + +evlist__for_each (evlist, evsel) { +int ncpus =perf_evsel__nr_cpus (evsel); + +if (perf_evsel__alloc_stat_priv (evsel) <0 || +perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || + (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) + goto out_free; + } + +return 0 ; + +out_free: +perf_evlist__free_stats (evlist); +return -1 ; +} + +void perf_evlist__free_stats (struct perf_evlist *evlist) +{ +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +perf_evsel__free_stat_priv (evsel); +perf_evsel__free_counts (evsel); +perf_evsel__free_prev_raw_counts (evsel); + } +}
tools/perf/util/stat.h +5 -0
@@ -70,6 +70,8 @@ static inline void init_stats(struct stats *stats) }struct perf_evsel ; +struct perf_evlist ; +bool __perf_evsel_stat__is (struct perf_evsel *evsel,enum perf_stat_evsel_id id);
@@ -100,4 +102,7 @@ void perf_evsel__free_stat_priv(struct perf_evsel *evsel);int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel,int ncpus,int nthreads);void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel); + +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw); +void perf_evlist__free_stats (struct perf_evlist *evlist);#endif
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 20/30 perf stat: Introduce perf_evsel__alloc_stats function
In reply to Jiri OlsaMove all stat allocation logic related to stat
object under single function. This way we can
use it separately for stat object out of evlist
object.
--- tools/perf/util/stat.c | 20 ++++++++++++++------ tools/perf/util/stat.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-)
tools/perf/util/stat.c +14 -6
@@ -189,17 +189,25 @@ void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) evsel->prev_raw_counts =NULL ; } +int perf_evsel__alloc_stats (struct perf_evsel *evsel,bool alloc_raw) +{ +int ncpus =perf_evsel__nr_cpus (evsel); +int nthreads =thread_map__nr (evsel->threads); + +if (perf_evsel__alloc_stat_priv (evsel) <0 || +perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || + (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) +return -ENOMEM ; + +return 0 ; +} +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) {struct perf_evsel *evsel; -int nthreads =thread_map__nr (evlist->threads);evlist__for_each (evlist, evsel) { -int ncpus =perf_evsel__nr_cpus (evsel); - -if (perf_evsel__alloc_stat_priv (evsel) <0 || -perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || - (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) +if (perf_evsel__alloc_stats (evsel, alloc_raw)) goto out_free; }
tools/perf/util/stat.h +2 -0
@@ -103,6 +103,8 @@ int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, int ncpus, int nthreads);void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel); +int perf_evsel__alloc_stats (struct perf_evsel *evsel,bool alloc_raw); +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw);void perf_evlist__free_stats (struct perf_evlist *evlist);#endif
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 21/30 perf stat: Introduce perf_evsel__read function
In reply to Jiri OlsaAdding simple read function that reads/store data into given struct perf_counts_values *count object.
--- tools/perf/util/evsel.c | 14 ++++++++++++++ tools/perf/util/evsel.h | 3 +++ 2 files changed, 17 insertions(+)
tools/perf/util/evsel.c +14 -0
@@ -955,6 +955,20 @@ int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,return cb (evsel, cpu, thread, &count); } +int perf_evsel__read (struct perf_evsel *evsel,int cpu,int thread, +struct perf_counts_values *count) +{ +memset (count,0 ,sizeof (*count)); + +if (FD (evsel, cpu, thread) <0 ) +return -EINVAL ; + +if (readn (FD (evsel, cpu, thread), count,sizeof (*count)) <0 ) +return -errno; + +return 0 ; +} +int __perf_evsel__read_on_cpu (struct perf_evsel *evsel,int cpu,int thread,bool scale) {
tools/perf/util/evsel.h +3 -0
@@ -236,6 +236,9 @@ typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel,int perf_evsel__read_cb (struct perf_evsel *evsel,int cpu,int thread,perf_evsel__read_cb_t cb); +int perf_evsel__read (struct perf_evsel *evsel,int cpu,int thread, +struct perf_counts_values *count); +int __perf_evsel__read_on_cpu (struct perf_evsel *evsel,int cpu,int thread,bool scale);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 22/30 perf stat: Introduce read_counters function
In reply to Jiri OlsaMoving read counters logic into single read_counters function, which will be called for both interval and overall processing legs.
The reason is to split reading and processing (following patches) counters code, so we could read counters from other sources (like perf.data) and process them in the same way as 'perf stat' command does.
--- tools/perf/builtin-stat.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-)
tools/perf/builtin-stat.c +22 -25
@@ -329,27 +329,35 @@ static int read_counter(struct perf_evsel *counter)return 0 ; } -static void print_interval (void ) +static void read_counters (bool close) { -static int num_print_interval;struct perf_evsel *counter;struct perf_stat *ps; -struct timespec ts, rs; -char prefix[64 ]; -if (aggr_mode ==AGGR_GLOBAL ) { -evlist__for_each (evsel_list, counter) { - ps = counter->priv; -memset (ps->res_stats,0 ,sizeof (ps->res_stats)); +evlist__for_each (evsel_list, counter) { + ps = counter->priv; +memset (ps->res_stats,0 ,sizeof (ps->res_stats)); + +if (aggr_mode ==AGGR_GLOBAL )read_counter_aggr (counter); - } - }else { -evlist__for_each (evsel_list, counter) { - ps = counter->priv; -memset (ps->res_stats,0 ,sizeof (ps->res_stats)); +else read_counter (counter); + +if (close) { +perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter), +thread_map__nr (evsel_list->threads)); } } +} + +static void print_interval (void ) +{ +static int num_print_interval; +struct perf_evsel *counter; +struct timespec ts, rs; +char prefix[64 ]; + +read_counters (false);clock_gettime (CLOCK_MONOTONIC , &ts);diff_timespec (&rs, &ts, &ref_time);
@@ -531,18 +539,7 @@ static int __run_perf_stat(int argc, const char **argv)update_stats (&walltime_nsecs_stats, t1 - t0); -if (aggr_mode ==AGGR_GLOBAL ) { -evlist__for_each (evsel_list, counter) { -read_counter_aggr (counter); -perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter), -thread_map__nr (evsel_list->threads)); - } - }else { -evlist__for_each (evsel_list, counter) { -read_counter (counter); -perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter),1 ); - } - } +read_counters (true);return WEXITSTATUS (status); }
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 23/30 perf stat: Separate counters reading and processing
In reply to Jiri OlsaSeparating counters reading and processing so we could use the processing part in following patches.
Using simple reading via perf_evsel__read function to read counters now, because part of the processing was in the read_cb callback.
--- tools/perf/builtin-stat.c | 56 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +39 -17
@@ -223,8 +223,9 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)return 0 ; } -static int read_cb (struct perf_evsel *evsel,int cpu,int thread, -struct perf_counts_values *count) +static int +process_counter_values (struct perf_evsel *evsel,int cpu,int thread, +struct perf_counts_values *count) {struct perf_counts_values *aggr = &evsel->counts->aggr;static struct perf_counts_values zero;
@@ -245,7 +246,6 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread,if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count);perf_counts_values__scale (count, scale,NULL ); - *perf_counts (evsel->counts, cpu, thread) = *count;if (aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;
@@ -262,23 +262,41 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread,return 0 ; } -static int read_counter (struct perf_evsel *counter); +static int process_counter_maps (struct perf_evsel *counter) +{ +int nthreads =thread_map__nr (counter->threads); +int ncpus =perf_evsel__nr_cpus (counter); +int cpu, thread; -/* -* Read out the results of a single counter: -* aggregate counts across CPUs in system-wide mode -*/ -static int read_counter_aggr (struct perf_evsel *counter) +if (counter->system_wide) + nthreads =1 ; + +for (thread =0 ; thread < nthreads; thread++) { +for (cpu =0 ; cpu < ncpus; cpu++) { +if (process_counter_values (counter, cpu, thread, +perf_counts (counter->counts, cpu, thread))) +return -1 ; + } + } + +return 0 ; +} + +static int process_counter (struct perf_evsel *counter) {struct perf_counts_values *aggr = &counter->counts->aggr;struct perf_stat *ps = counter->priv;u64 *count = counter->counts->aggr.values; -int i; +int i, ret; aggr->val = aggr->ena = aggr->run =0 ; -if (read_counter (counter)) -return -1 ; + ret =process_counter_maps (counter); +if (ret) +return ret; + +if (aggr_mode !=AGGR_GLOBAL ) +return 0 ;if (!counter->snapshot)perf_evsel__compute_deltas (counter,-1 ,-1 , aggr);
@@ -321,7 +339,10 @@ static int read_counter(struct perf_evsel *counter)for (thread =0 ; thread < nthreads; thread++) {for (cpu =0 ; cpu < ncpus; cpu++) { -if (perf_evsel__read_cb (counter, cpu, thread, read_cb)) +struct perf_counts_values *count; + + count =perf_counts (counter->counts, cpu, thread); +if (perf_evsel__read (counter, cpu, thread, count))return -1 ; } }
@@ -338,10 +359,11 @@ static void read_counters(bool close) ps = counter->priv;memset (ps->res_stats,0 ,sizeof (ps->res_stats)); -if (aggr_mode ==AGGR_GLOBAL ) -read_counter_aggr (counter); -else -read_counter (counter); +if (read_counter (counter)) +pr_warning ("failed to read counter %s\n" , counter->name); + +if (process_counter (counter)) +pr_warning ("failed to process counter %s\n" , counter->name);if (close) { perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 24/30 perf stat: Move zero_per_pkg into counter process code
In reply to Jiri OlsaMoving zero_per_pkg into counter process code, to make the reading path free of processing logic.
--- tools/perf/builtin-stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/builtin-stat.c +3 -3
@@ -291,6 +291,9 @@ static int process_counter(struct perf_evsel *counter) aggr->val = aggr->ena = aggr->run =0 ; +if (counter->per_pkg) +zero_per_pkg (counter); + ret =process_counter_maps (counter);if (ret)return ret;
@@ -334,9 +337,6 @@ static int read_counter(struct perf_evsel *counter)if (counter->system_wide) nthreads =1 ; -if (counter->per_pkg) -zero_per_pkg (counter); -for (thread =0 ; thread < nthreads; thread++) {for (cpu =0 ; cpu < ncpus; cpu++) {struct perf_counts_values *count;
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 25/30 perf stat: Move perf_stat initialization counter process code
In reply to Jiri OlsaMoving perf_stat initialization counter process code, to make the reading path free of processing logic.
--- tools/perf/builtin-stat.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
tools/perf/builtin-stat.c +1 -4
@@ -290,6 +290,7 @@ static int process_counter(struct perf_evsel *counter)int i, ret; aggr->val = aggr->ena = aggr->run =0 ; +memset (ps->res_stats,0 ,sizeof (ps->res_stats));if (counter->per_pkg)zero_per_pkg (counter);
@@ -353,12 +354,8 @@ static int read_counter(struct perf_evsel *counter)static void read_counters (bool close) {struct perf_evsel *counter; -struct perf_stat *ps;evlist__for_each (evsel_list, counter) { - ps = counter->priv; -memset (ps->res_stats,0 ,sizeof (ps->res_stats)); -if (read_counter (counter))pr_warning ("failed to read counter %s\n" , counter->name);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 26/30 perf stat: Remove perf_evsel__read_cb function
In reply to Jiri OlsaIt's no longer used, the stat command uses perf_evsel__read now.
--- tools/perf/util/evsel.c | 16 ---------------- tools/perf/util/evsel.h | 7 ------- 2 files changed, 23 deletions(-)
tools/perf/util/evsel.c +0 -16
@@ -939,22 +939,6 @@ void perf_counts_values__scale(struct perf_counts_values *count, *pscaled = scaled; } -int perf_evsel__read_cb (struct perf_evsel *evsel,int cpu,int thread, -perf_evsel__read_cb_t cb) -{ -struct perf_counts_values count; - -memset (&count,0 ,sizeof (count)); - -if (FD (evsel, cpu, thread) <0 ) -return -EINVAL ; - -if (readn (FD (evsel, cpu, thread), &count,sizeof (count)) <0 ) -return -errno; - -return cb (evsel, cpu, thread, &count); -} -int perf_evsel__read (struct perf_evsel *evsel,int cpu,int thread,struct perf_counts_values *count) {
tools/perf/util/evsel.h +0 -7
@@ -229,13 +229,6 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, (a)->attr.type == (b)->attr.type && \ (a)->attr.config == (b)->attr.config) -typedef int (perf_evsel__read_cb_t )(struct perf_evsel *evsel, -int cpu,int thread, -struct perf_counts_values *count); - -int perf_evsel__read_cb (struct perf_evsel *evsel,int cpu,int thread, -perf_evsel__read_cb_t cb); -int perf_evsel__read (struct perf_evsel *evsel,int cpu,int thread,struct perf_counts_values *count);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 27/30 perf stat: Rename print_interval to process_interval
In reply to Jiri OlsaIt suits better, because the function also reads counter's data.
Also the 'print_interval' name will be used in following generalization of counters display.
--- tools/perf/builtin-stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/builtin-stat.c +3 -3
@@ -369,7 +369,7 @@ static void read_counters(bool close) } } -static void print_interval (void ) +static void process_interval (void ) {static int num_print_interval;struct perf_evsel *counter;
@@ -532,7 +532,7 @@ static int __run_perf_stat(int argc, const char **argv)if (interval) {while (!waitpid (child_pid, &status,WNOHANG )) {nanosleep (&ts,NULL ); -print_interval (); +process_interval (); } }wait (&status);
@@ -550,7 +550,7 @@ static int __run_perf_stat(int argc, const char **argv)while (!done) {nanosleep (&ts,NULL );if (interval) -print_interval (); +process_interval (); } }
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 28/30 perf stat: Using init_stats instead of memset
In reply to Jiri OlsaThe init_stats function is meant to init 'struct stats'.
--- tools/perf/builtin-stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/builtin-stat.c +1 -1
@@ -290,7 +290,7 @@ static int process_counter(struct perf_evsel *counter)int i, ret; aggr->val = aggr->ena = aggr->run =0 ; -memset (ps->res_stats,0 ,sizeof (ps->res_stats)); +init_stats (ps->res_stats);if (counter->per_pkg)zero_per_pkg (counter);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 29/30 perf stat: Introduce print_counters function
In reply to Jiri OlsaCentralize counters print code into singleprint_counters function.
--- tools/perf/builtin-stat.c | 127 +++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 63 deletions(-)
tools/perf/builtin-stat.c +64 -63
@@ -67,10 +67,7 @@#define CNTR_NOT_SUPPORTED "<not supported>"#define CNTR_NOT_COUNTED "<not counted>" -static void print_stat (int argc,const char **argv); -static void print_counter_aggr (struct perf_evsel *counter,char *prefix); -static void print_counter (struct perf_evsel *counter,char *prefix); -static void print_aggr (char *prefix); +static void print_counters (struct timespec *ts,int argc,const char **argv);/* Default events used for perf stat -T */ static const char *transaction_attrs = {
@@ -371,53 +368,14 @@ static void read_counters(bool close)static void process_interval (void ) { -static int num_print_interval; -struct perf_evsel *counter;struct timespec ts, rs; -char prefix[64 ];read_counters (false);clock_gettime (CLOCK_MONOTONIC , &ts);diff_timespec (&rs, &ts, &ref_time); -sprintf (prefix,"%6lu.%09lu%s" , rs.tv_sec, rs.tv_nsec, csv_sep); - -if (num_print_interval ==0 && !csv_output) { -switch (aggr_mode) { -case AGGR_SOCKET : -fprintf (output,"# time socket cpus counts %*s events\n" , unit_width,"unit" ); -break ; -case AGGR_CORE : -fprintf (output,"# time core cpus counts %*s events\n" , unit_width,"unit" ); -break ; -case AGGR_NONE : -fprintf (output,"# time CPU counts %*s events\n" , unit_width,"unit" ); -break ; -case AGGR_GLOBAL : -default : -fprintf (output,"# time counts %*s events\n" , unit_width,"unit" ); - } - } - -if (++num_print_interval ==25 ) - num_print_interval =0 ; -switch (aggr_mode) { -case AGGR_CORE : -case AGGR_SOCKET : -print_aggr (prefix); -break ; -case AGGR_NONE : -evlist__for_each (evsel_list, counter) -print_counter (counter, prefix); -break ; -case AGGR_GLOBAL : -default : -evlist__for_each (evsel_list, counter) -print_counter_aggr (counter, prefix); - } - -fflush (output); +print_counters (&rs,0 ,NULL ); }static void handle_initial_delay (void )
@@ -907,9 +865,35 @@ static void print_counter(struct perf_evsel *counter, char *prefix) } } -static void print_stat (int argc,const char **argv) +static void print_interval (char *prefix,struct timespec *ts) +{ +static int num_print_interval; + +sprintf (prefix,"%6lu.%09lu%s" , ts->tv_sec, ts->tv_nsec, csv_sep); + +if (num_print_interval ==0 && !csv_output) { +switch (aggr_mode) { +case AGGR_SOCKET : +fprintf (output,"# time socket cpus counts %*s events\n" , unit_width,"unit" ); +break ; +case AGGR_CORE : +fprintf (output,"# time core cpus counts %*s events\n" , unit_width,"unit" ); +break ; +case AGGR_NONE : +fprintf (output,"# time CPU counts %*s events\n" , unit_width,"unit" ); +break ; +case AGGR_GLOBAL : +default : +fprintf (output,"# time counts %*s events\n" , unit_width,"unit" ); + } + } + +if (++num_print_interval ==25 ) + num_print_interval =0 ; +} + +static void print_header (int argc,const char **argv) { -struct perf_evsel *counter;int i;fflush (stdout);
@@ -935,36 +919,53 @@ static void print_stat(int argc, const char **argv)fprintf (output," (%d runs)" , run_count);fprintf (output,":\n\n" ); } +} + +static void print_footer (void ) +{ +if (!null_run) +fprintf (output,"\n" ); +fprintf (output," %17.9f seconds time elapsed" , +avg_stats (&walltime_nsecs_stats)/1e9 ); +if (run_count >1 ) { +fprintf (output," " ); +print_noise_pct (stddev_stats (&walltime_nsecs_stats), +avg_stats (&walltime_nsecs_stats)); + } +fprintf (output,"\n\n" ); +} + +static void print_counters (struct timespec *ts,int argc,const char **argv) +{ +struct perf_evsel *counter; +char buf[64 ], *prefix =NULL ; + +if (interval) +print_interval (prefix = buf, ts); +else +print_header (argc, argv);switch (aggr_mode) {case AGGR_CORE :case AGGR_SOCKET : -print_aggr (NULL ); +print_aggr (prefix);break ;case AGGR_GLOBAL :evlist__for_each (evsel_list, counter) -print_counter_aggr (counter,NULL ); +print_counter_aggr (counter, prefix);break ;case AGGR_NONE :evlist__for_each (evsel_list, counter) -print_counter (counter,NULL ); +print_counter (counter, prefix);break ;default :break ; } -if (!csv_output) { -if (!null_run) -fprintf (output,"\n" ); -fprintf (output," %17.9f seconds time elapsed" , -avg_stats (&walltime_nsecs_stats)/1e9 ); -if (run_count >1 ) { -fprintf (output," " ); -print_noise_pct (stddev_stats (&walltime_nsecs_stats), -avg_stats (&walltime_nsecs_stats)); - } -fprintf (output,"\n\n" ); - } +if (!interval && !csv_output) +print_footer (); + +fflush (output); }static volatile int signr =-1 ;
@@ -1413,13 +1414,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) status =run_perf_stat (argc, argv);if (forever && status !=-1 ) { -print_stat (argc, argv); +print_counters (NULL , argc, argv);perf_stat__reset_stats (evsel_list); } }if (!forever && status !=-1 && !interval) -print_stat (argc, argv); +print_counters (NULL , argc, argv);perf_evlist__free_stats (evsel_list); out:
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH v2 30/30 perf stat: Introduce --per-task option
In reply to Jiri OlsaCurrently all the -p option PID arguments tasks values get aggregated and printed as single values.
Adding --per-tasks option to print values per task.
$ perf stat -e cycles,instructions --per-task -p 25388,25442 -a ^C Performance counter stats for process id '25388,25442':
cat-25388 100,122 cycles vim-25442 4,167,876 cycles cat-25388 20,080 instructions vim-25442 3,232,735 instructions
6.057130572 seconds time elapsed
Also works under interval mode:
$ perf stat -e cycles,instructions --per-task -p 25388,25442 -a -I 1000
# time task counts unit events
1.000190002 cat-25388 54,196 cycles
1.000190002 vim-25442 0 cycles
1.000190002 cat-25388 11,660 instructions
1.000190002 vim-25442 0 instructions
2.000742579 cat-25388 55,247 cycles
2.000742579 vim-25442 1,752,951 cycles
2.000742579 cat-25388 11,872 instructions
2.000742579 vim-25442 1,238,512 instructions
3.001057871 cat-25388 0 cycles
3.001057871 vim-25442 0 cycles
3.001057871 cat-25388 0 instructions
3.001057871 vim-25442 0 instructions
^C 3.242519732 cat-25388 0 cycles
3.242519732 vim-25442 0 cycles
3.242519732 cat-25388 0 instructions
3.242519732 vim-25442 0 instructionsIt works only with -t and -p options, otherwise following error is printed:
$ perf stat -e cycles --per-task -I 1000 ls
The --per-task option is only available when monitoring tasks via -p -t options.
-p, --pid <pid> stat events on existing process id
-t, --tid <tid> stat events on existing thread id--- tools/perf/Documentation/perf-stat.txt | 3 ++ tools/perf/builtin-stat.c | 67 +++++++++++++++++++++++++++++++++- tools/perf/util/stat.h | 1 + 3 files changed, 69 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-stat.txt +3 -0
@@ -144,6 +144,9 @@ is a useful mode to detect imbalance between physical cores. To enable this mod use --per-core in addition to -a. (system-wide). The output includes the core number and the number of online logical processors on that physical processor. +--per-task:: +Aggregate counts per monitored threads (-t option) or processes (-p option). + -D msecs:: --delay msecs:: After starting the program, wait msecs before measuring. This is useful to
tools/perf/builtin-stat.c +65 -2
115 lines not on this page · raw message
tools/perf/util/stat.h +1 -0
@@ -30,6 +30,7 @@ enum aggr_mode {AGGR_GLOBAL ,AGGR_SOCKET ,AGGR_CORE , + AGGR_TASK, }; struct perf_counts_values {
Signature · 1 line
1.9.3