perf stat: Introduce --per-thread option
Jiri Olsa
reviewerv4 cover perf stat: Introduce --per-thread option
hi,
adding the possibility to display stat data per thread.
Allowing following commands and output:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242 ^C Performance counter stats for process id '30190,30242':
cat-30190 0 cycles
yes-30242 3,842,525,421 cycles
cat-30190 0 instructions
yes-30242 10,370,817,010 instructions1.143155657 seconds time elapsed
Also works under interval mode:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242 -I 1000
# time comm-pid counts unit events
1.000073435 cat-30190 89,058 cycles
1.000073435 yes-30242 3,360,786,902 cycles (100.00%)
1.000073435 cat-30190 14,066 instructions
1.000073435 yes-30242 9,069,937,462 instructions
2.000204830 cat-30190 0 cycles
2.000204830 yes-30242 3,351,667,626 cycles
2.000204830 cat-30190 0 instructions
2.000204830 yes-30242 9,045,796,885 instructions
^C 2.771286639 cat-30190 0 cycles
2.771286639 yes-30242 2,593,884,166 cycles
2.771286639 cat-30190 0 instructions
2.771286639 yes-30242 7,001,171,191 instructionsAvailable in here:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/per_thread
v4 changes:
- add thread_map__set_(pid|comm) interface
- several fixes for task comm string reading
- added perf_evlist__reset_stats function
v3 changes:
- some patches already pulled in, rebased on latest acme's perf/core
- fixed cpu_map__get/thread_map__get to accept NULL map
- renamed propagate_maps to perf_evlist__propagate_maps
- renamed --per-task option to --per-thread
- changed 'task-pid' header output to 'comm-pid'
v2 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,
jirka
---
Jiri Olsa (27):
perf tools: Change thread_map::map into struct
perf tools: Add comm string into struct thread_map
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 tests: Add thread_map object tests
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: Introduce perf_evlist__reset_stats
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|reset)_stats into stat 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-thread option
tools/perf/Documentation/perf-stat.txt | 4 + tools/perf/builtin-stat.c | 404 ++++++++++++++-------------- 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 | 8 +- 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 | 26 +- tools/perf/util/cpumap.h | 6 +- tools/perf/util/event.c | 6 +- tools/perf/util/evlist.c | 39 ++- tools/perf/util/evlist.h | 1 - tools/perf/util/evsel.c | 28 +- tools/perf/util/evsel.h | 40 ++- tools/perf/util/parse-events.c | 5 +- tools/perf/util/python-ext-sources | 1 + tools/perf/util/python.c | 4 +- tools/perf/util/record.c | 4 +- tools/perf/util/session.c | 2 +- tools/perf/util/stat.c | 132 ++++++++- tools/perf/util/stat.h | 47 +++- tools/perf/util/svghelper.c | 2 +- tools/perf/util/thread_map.c | 118 ++++++-- tools/perf/util/thread_map.h | 35 ++- 33 files changed, 661 insertions(+), 319 deletions(-) create mode 100644 tools/perf/tests/thread-map.c
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 1/27 perf tools: Change thread_map::map into struct
We 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 | 26 ++++++++++++++------------ tools/perf/util/thread_map.h | 16 +++++++++++++++- 8 files changed, 40 insertions(+), 24 deletions(-)
tools/perf/builtin-trace.c +2 -2
@@ -2325,7 +2325,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 ) {
@@ -2343,7 +2343,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__set_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
@@ -504,7 +504,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, proc_map_timeout)) { err =-1 ;
@@ -515,12 +515,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
@@ -548,7 +548,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 ; }
@@ -1475,7 +1475,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__set_pid (evlist->threads,0 , evlist->workload.pid); }close (child_ready_pipe[1 ]);
tools/perf/util/evsel.c +1 -1
@@ -1167,7 +1167,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 +14 -12
@@ -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__set_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__set_pid (threads,0 , tid); + threads->nr =1 ; }return threads;
@@ -123,8 +123,10 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) threads = tmp; } -for (i =0 ; i < items; i++) - threads->map[threads->nr + i] =atoi (namelist[i]->d_name); +for (i =0 ; i < items; i++) { +thread_map__set_pid (threads, threads->nr + i, +atoi (namelist[i]->d_name)); + }for (i =0 ; i < items; i++)zfree (&namelist[i]);
@@ -201,7 +203,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__set_pid (threads, j++,atoi (namelist[i]->d_name));zfree (&namelist[i]); } threads->nr = total_tasks;
@@ -227,8 +229,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__set_pid (threads,0 ,-1 ); + threads->nr =1 ; }return threads; }
@@ -267,8 +269,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__set_pid (threads, ntasks -1 , tid); + threads->nr = ntasks; } out:return threads;
@@ -301,7 +303,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 +15 -1
@@ -4,9 +4,13 @@#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[]; };struct thread_map *thread_map__new_dummy (void );
@@ -27,4 +31,14 @@ static inline int thread_map__nr(struct thread_map *threads) return threads ? threads->nr : 1; } +static inline pid_t thread_map__pid (struct thread_map *map,int thread) +{ +return map->map[thread].pid; +} + +static inline void +thread_map__set_pid (struct thread_map *map,int thread,pid_t pid) +{ + map->map[thread].pid = pid; +}#endif /* __PERF_THREAD_MAP_H */
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf thread_map: Don' t access the array entries directly
perf thread_map: Don't access the array entries directly
Commit-ID: e13798c77bdfed1da497f5e076b105b2be17b44f Gitweb: http://git.kernel.org/tip/e13798c77bdfed1da497f5e076b105b2be17b44f Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 23 Jun 2015 00:36:02 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 23 Jun 2015 18:21:44 -0300
perf thread_map: Don't access the array entries directly
Instead provide a method to set the array entries, and another to access the contents.
--- 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 | 24 +++++++++++++----------- tools/perf/util/thread_map.h | 10 ++++++++++ 8 files changed, 34 insertions(+), 22 deletions(-)
tools/perf/builtin-trace.c +2 -2
@@ -2325,7 +2325,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 ) {
@@ -2343,7 +2343,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__set_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
@@ -504,7 +504,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, proc_map_timeout)) { err =-1 ;
@@ -515,12 +515,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
@@ -548,7 +548,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 ; }
@@ -1475,7 +1475,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__set_pid (evlist->threads,0 , evlist->workload.pid); }close (child_ready_pipe[1 ]);
tools/perf/util/evsel.c +1 -1
@@ -1167,7 +1167,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 +13 -11
@@ -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__set_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__set_pid (threads,0 , tid); + threads->nr =1 ; }return threads;
@@ -123,8 +123,10 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) threads = tmp; } -for (i =0 ; i < items; i++) - threads->map[threads->nr + i] =atoi (namelist[i]->d_name); +for (i =0 ; i < items; i++) { +thread_map__set_pid (threads, threads->nr + i, +atoi (namelist[i]->d_name)); + }for (i =0 ; i < items; i++)zfree (&namelist[i]);
@@ -201,7 +203,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__set_pid (threads, j++,atoi (namelist[i]->d_name));zfree (&namelist[i]); } threads->nr = total_tasks;
@@ -227,8 +229,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__set_pid (threads,0 ,-1 ); + threads->nr =1 ; }return threads; }
@@ -267,8 +269,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__set_pid (threads, ntasks -1 , tid); + threads->nr = ntasks; } out:return threads;
@@ -301,7 +303,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 +10 -0
@@ -27,4 +27,14 @@ static inline int thread_map__nr(struct thread_map *threads) return threads ? threads->nr : 1; } +static inline pid_t thread_map__pid (struct thread_map *map,int thread) +{ +return map->map[thread]; +} + +static inline void +thread_map__set_pid (struct thread_map *map,int thread,pid_t pid) +{ + map->map[thread] = pid; +}#endif /* __PERF_THREAD_MAP_H */
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf thread_map: Change map entries into a struct
In reply to Jiri Olsaperf thread_map: Change map entries into a struct
Commit-ID: 38e89d2b1771649c006720903c06d8b8bedd4d83 Gitweb: http://git.kernel.org/tip/38e89d2b1771649c006720903c06d8b8bedd4d83 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 23 Jun 2015 00:36:02 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 23 Jun 2015 18:21:45 -0300
perf thread_map: Change map entries into a struct
We need to store command names with the pid. Changing map entries to be a struct holding pid. Process name is coming in shortly.
--- tools/perf/util/thread_map.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
tools/perf/util/thread_map.h +7 -3
@@ -4,9 +4,13 @@#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[]; };struct thread_map *thread_map__new_dummy (void );
@@ -29,12 +33,12 @@ static inline int thread_map__nr(struct thread_map *threads)static inline pid_t thread_map__pid (struct thread_map *map,int thread) { -return map->map[thread]; +return map->map[thread].pid; }static inline void thread_map__set_pid (struct thread_map *map,int thread,pid_t pid) { - map->map[thread] = pid; + map->map[thread].pid = pid; }#endif /* __PERF_THREAD_MAP_H */
Jiri Olsa
reviewerPATCH v4 2/27 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-thread 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 | 67 ++++++++++++++++++++++++++++++++++++-- tools/perf/util/thread_map.h | 12 +++++++ 3 files changed, 77 insertions(+), 3 deletions(-)
tools/perf/util/python-ext-sources +1 -0
@@ -20,3 +20,4 @@ util/stat.c util/strlist.c util/trace-event.c ../../lib/rbtree.c +util/string.c
tools/perf/util/thread_map.c +64 -3
124 lines not on this page · raw message
tools/perf/util/thread_map.h +12 -0
@@ -6,6 +6,7 @@struct thread_map_data {pid_t pid; +char *comm; };struct thread_map {
@@ -41,4 +42,15 @@ thread_map__set_pid(struct thread_map *map, int thread, pid_t pid) { map->map[thread].pid = pid; } + +static inline char *thread_map__comm (struct thread_map *map,int thread) +{ +return map->map[thread].comm; +} + +static inline void +thread_map__set_comm (struct thread_map *map,int thread,char *comm) +{ + map->map[thread].comm = comm; +}#endif /* __PERF_THREAD_MAP_H */
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 02/27] perf tools: Add comm string into struct thread_map
Em Tue, Jun 23, 2015 at 12:36:03AM +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-thread option to display task pid together with task name.Getting the task name from
/proc/$pid/comm.
Do we really need to read this all the time? Or just for tools that need this?
Can't we have a thread_map__read_comms(map);
That we can make this specific --per-thread option in 'stat' call?
Applied the first patch after breaking it into two, one to add the accessors and the other to transform the map entries into a struct.
Pushed to perf/core already.
- Arnaldo
Quoted 184 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/python-ext-sources | 1 + tools/perf/util/thread_map.c | 67 ++++++++++++++++++++++++++++++++++++-- tools/perf/util/thread_map.h | 12 +++++++ 3 files changed, 77 insertions(+), 3 deletions(-)tools/perf/util/python-ext-sources +1
-0@@ -20,3 +20,4 @@ util/stat.c util/strlist.c util/trace-event.c ../../lib/rbtree.c +util/string.ctools/perf/util/thread_map.c +64
-3@@ -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,51 @@ 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) { +/* +* We're reading 16 bytes, while filename__read_str +* allocates data per BUFSIZ bytes, so we can safely +* mark the end of the string. +*/ + (*comm)[size] =0 ; +rtrim (*comm); + } + +free (path); +return err; +} + +static void comm_init (struct thread_map *map,int i) +{ +pid_t pid =thread_map__pid (map, i); +char *comm =NULL ; + +/* dummy pid comm initialization */ +if (pid ==-1 ) { +thread_map__set_comm (map, i,strdup ("dummy" )); +return ; + } + +/* +* The comm name is like extra bonus ;-), +* so just warn if we fail for any reason. +*/ +if (get_comm (&comm, pid)) +pr_warning ("Couldn't resolve comm name for pid %d\n" , pid); + +thread_map__set_comm (map, i, comm); +} +struct thread_map *thread_map__new_by_pid (pid_t pid) {struct thread_map *threads;@@ -44,8 +91,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__set_pid (threads, i,atoi (namelist[i]->d_name)); +comm_init (threads, i); + } threads->nr = items; }@@ -63,6 +112,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)if (threads !=NULL ) {thread_map__set_pid (threads,0 , tid); threads->nr =1 ; +comm_init (threads,0 ); }return threads;@@ -126,6 +176,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)for (i =0 ; i < items; i++) {thread_map__set_pid (threads, threads->nr + i,atoi (namelist[i]->d_name)); +comm_init (threads, threads->nr + i); }for (i =0 ; i < items; i++)@@ -202,8 +253,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__set_pid (threads, j++,atoi (namelist[i]->d_name)); +for (i =0 ; i < items; i++, j++) { +thread_map__set_pid (threads, j,atoi (namelist[i]->d_name)); +comm_init (threads, j);zfree (&namelist[i]); } threads->nr = total_tasks;@@ -231,6 +283,7 @@ struct thread_map *thread_map__new_dummy(void)if (threads !=NULL ) {thread_map__set_pid (threads,0 ,-1 ); threads->nr =1 ; +comm_init (threads,0 ); }return threads; }@@ -271,6 +324,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) threads = nt;thread_map__set_pid (threads, ntasks -1 , tid); threads->nr = ntasks; +comm_init (threads, ntasks -1 ); } out:return threads;@@ -294,6 +348,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 +12
-0@@ -6,6 +6,7 @@struct thread_map_data {pid_t pid; +char *comm; };struct thread_map {@@ -41,4 +42,15 @@ thread_map__set_pid(struct thread_map *map, int thread, pid_t pid) { map->map[thread].pid = pid; } + +static inline char *thread_map__comm (struct thread_map *map,int thread) +{ +return map->map[thread].comm; +} + +static inline void +thread_map__set_comm (struct thread_map *map,int thread,char *comm) +{ + map->map[thread].comm = comm; +}#endif /* __PERF_THREAD_MAP_H */ Signature · 1 line
1.9.3
Re: [PATCH 02/27] perf tools: Add comm string into struct thread_map
Quoted 5 lines · Arnaldo Carvalho de Melo
Em Tue, Jun 23, 2015 at 12:36:03AM +0200, Jiri Olsa escreveu:
Quoted 4 lines
Adding support to hold comm name together with pids in 'struct
thread_map'. It will be useful for --per-thread option to display task pid together with task name.
Quoted 8 lines
Quoted 1 line
Getting the task name from
/proc/$pid/comm.Do we really need to read this all the time? Or just for tools that need this?
Can't we have a
thread_map__read_comms(map);That we can make this specific --per-thread option in 'stat' call?
ook
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/27] perf tools: Add comm string into struct thread_map
Em Tue, Jun 23, 2015 at 11:56:18PM +0200, Jiri Olsa escreveu:
Quoted 8 lines · Arnaldo Carvalho de Melo
Quoted 6 lines
Em Tue, Jun 23, 2015 at 12:36:03AM +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-thread option to display task pid together with task name.Getting the task name from
/proc/$pid/comm.
Quoted 8 lines
Quoted 6 lines
Do we really need to read this all the time? Or just for tools that need this?
Can't we have a
thread_map__read_comms(map);That we can make this specific --per-thread option in 'stat' call?
ook
Thanks, this made me think: thread_map is just an array that enumerates the pids ultimately for use with sys_perf_event_open(), bloating it with extra details used by just one oddball subfeature of just one tool seems overkill.
Probably it would be better to rename it to pid_map, that is what is useful for all tools using it to create the event file descriptors and have a comm_map that would return another enumeration to obtain the comms, something like:
struct thread_map *tids = thread__map_by_foo(parameters); struct comm_map *comms = comm_map__new(tids);
That way the various ways of populating the thread_map->map[] (the _by_foo() variants of thread_map we have) would do that leg work and the comm_map__new(tids) would just read the comms.
The thread_map users would not have to be touched at all, it would be kept as simple as it was and just tools that need those comms would go to the trouble of allocating the needed space for the array and to do the comm reading.
But nah, I'll probably merge what you did and later, if I find the time, do it myself, better to have that new feature than to be picky, right?
Thanks,
- Arnaldo
Re: [PATCH 02/27] perf tools: Add comm string into struct thread_map
Quoted 35 lines · Arnaldo Carvalho de Melo
Em Tue, Jun 23, 2015 at 11:56:18PM +0200, Jiri Olsa escreveu:
Quoted 8 lines · Arnaldo Carvalho de Melo
Quoted 6 lines
Em Tue, Jun 23, 2015 at 12:36:03AM +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-thread option to display task pid together with task name.Getting the task name from
/proc/$pid/comm.Quoted 8 lines
Quoted 6 lines
Do we really need to read this all the time? Or just for tools that need this?
Can't we have a
thread_map__read_comms(map);That we can make this specific --per-thread option in 'stat' call?
ook
Thanks, this made me think:
thread_mapis just an array that enumerates the pids ultimately for use withsys_perf_event_open(), bloating it with extra details used by just one oddball subfeature of just one tool seems overkill.Probably it would be better to rename it to
pid_map, that is what is useful for all tools using it to create the event file descriptors and have acomm_mapthat would return another enumeration to obtain the comms, something like:struct thread_map *tids = thread__map_by_foo(parameters); struct comm_map *comms = comm_map__new(tids);That way the various ways of populating the thread_map->map[] (the
_by_foo()variants ofthread_mapwe have) would do that leg work and thecomm_map__new(tids)would just read the comms.
Quoted 7 lines
The
thread_mapusers would not have to be touched at all, it would be kept as simple as it was and just tools that need those comms would go to the trouble of allocating the needed space for the array and to do the comm reading.But nah, I'll probably merge what you did and later, if I find the time, do it myself, better to have that new feature than to be picky, right?
right ;-) also the 'comm' string is small update after long time of no change in thread_map and I guess it will take probably another long time period before we will want to change it again..
thanks,
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/27] perf tools: Add comm string into struct thread_map
Em Thu, Jun 25, 2015 at 06:01:25PM +0200, Jiri Olsa escreveu:
Quoted 7 lines · Arnaldo Carvalho de Melo
Quoted 2 lines
But nah, I'll probably merge what you did and later, if I find the time, do it myself, better to have that new feature than to be picky, right?
right ;-) also the 'comm' string is small update after long time of no change in
thread_mapand I guess it will take probably another long time period before we will want to change it again..
Ideal would be that it would never change and keep the simple semantics it has, tho.
Anyway, at some point I can fix this up.
- Arnaldo
Jiri Olsa
reviewerPATCH v4 3/27 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 | 26 ++++++++++++++++++++++++-- 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, 45 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 +24 -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,32 @@ 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) +{ +if (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 +284,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 ;
@@ -1353,7 +1353,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
@@ -885,6 +885,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
@@ -1893,7 +1893,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 03/27] perf tools: Add reference counting for cpu_map object
Em Tue, Jun 23, 2015 at 12:36:04AM +0200, Jiri Olsa escreveu:
tools/perf/util/cpumap.c struct cpu_map *cpu_map__dummy_new(void) · line 210
Quoted 7 lines
tools/perf/util/cpumap.c +4
-2-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" );
Have you used this to catch some bug or is this just some attempt at a proactive check? s/disbalanced/unbalanced/g
- Arnaldo
Re: [PATCH 03/27] perf tools: Add reference counting for cpu_map object
Quoted 11 lines · Arnaldo Carvalho de Melo
Em Tue, Jun 23, 2015 at 12:36:04AM +0200, Jiri Olsa escreveu:
tools/perf/util/cpumap.c struct cpu_map *cpu_map__dummy_new(void) · line 210
Quoted 7 lines
tools/perf/util/cpumap.c +4
-2-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" );Have you used this to catch some bug or is this just some attempt at a proactive check? s/disbalanced/unbalanced/g
yep, proactive check
jirka
tip-bot for Jiri Olsa
merge bot[tip:perf/urgent] perf tools: Add reference counting for cpu_map object
In reply to Jiri Olsaperf tools: Add reference counting for cpu_map object
Commit-ID: f30a79b012e5d9b3887f6a59293d9ef3ca0e2c3e Gitweb: http://git.kernel.org/tip/f30a79b012e5d9b3887f6a59293d9ef3ca0e2c3e Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 23 Jun 2015 00:36:04 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 25 Jun 2015 15:15:50 -0300
perf tools: Add reference counting for cpu_map object
Adding 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 | 26 ++++++++++++++++++++++++-- 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, 45 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 +24 -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,32 @@ 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 unbalanced\n" ); +free (map); + } +} + +struct cpu_map *cpu_map__get (struct cpu_map *map) +{ +if (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 +284,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 ;
@@ -1353,7 +1353,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
@@ -885,6 +885,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
@@ -1895,7 +1895,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; }
Jiri Olsa
reviewerPATCH v4 4/27 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 | 31 ++++++++++++++++++++++++++---- tools/perf/util/thread_map.h | 7 +++++-- 11 files changed, 42 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, 500); -thread_map__delete (map); +thread_map__put (map);return err; }
tools/perf/tests/openat-syscall-all-cpus.c +1 -1
@@ -111,6 +111,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);
@@ -1120,7 +1120,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 +27 -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"
@@ -96,6 +97,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++)
@@ -113,6 +115,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)thread_map__set_pid (threads,0 , tid); threads->nr =1 ;comm_init (threads,0 ); +atomic_set (&threads->refcnt,1 ); }return threads;
@@ -134,6 +137,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;
@@ -264,6 +268,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:
@@ -284,6 +290,7 @@ struct thread_map *thread_map__new_dummy(void)thread_map__set_pid (threads,0 ,-1 ); threads->nr =1 ;comm_init (threads,0 ); +atomic_set (&threads->refcnt,1 ); }return threads; }
@@ -327,6 +334,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:
@@ -346,16 +355,30 @@ 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) +{ +if (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[]; };
@@ -20,11 +22,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
tip-bot for Jiri Olsa
merge bot[tip:perf/urgent] perf tools: Add reference counting for thread_map object
perf tools: Add reference counting for thread_map object
Commit-ID: 186fbb7432f4a740b4fbaf4145375442210110bb Gitweb: http://git.kernel.org/tip/186fbb7432f4a740b4fbaf4145375442210110bb Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 23 Jun 2015 00:36:05 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 25 Jun 2015 15:15:50 -0300
perf tools: Add reference counting for thread_map object
Adding reference 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, 43 insertions(+), 14 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, 500); -thread_map__delete (map); +thread_map__put (map);return err; }
tools/perf/tests/openat-syscall-all-cpus.c +1 -1
@@ -111,6 +111,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);
@@ -1120,7 +1120,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 +28 -2
@@ -8,6 +8,7 @@#include <unistd.h> #include "strlist.h" #include <string.h> +#include "asm/bug.h" #include "thread_map.h" #include "util.h"
@@ -47,6 +48,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)for (i =0 ; i < items; i++)thread_map__set_pid (threads, i,atoi (namelist[i]->d_name)); threads->nr = items; +atomic_set (&threads->refcnt,1 ); }for (i=0 ; i<items; i++)
@@ -63,6 +65,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)if (threads !=NULL ) {thread_map__set_pid (threads,0 , tid); threads->nr =1 ; +atomic_set (&threads->refcnt,1 ); }return threads;
@@ -84,6 +87,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;
@@ -212,6 +216,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:
@@ -231,6 +237,7 @@ struct thread_map *thread_map__new_dummy(void)if (threads !=NULL ) {thread_map__set_pid (threads,0 ,-1 ); threads->nr =1 ; +atomic_set (&threads->refcnt,1 ); }return threads; }
@@ -273,6 +280,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) threads->nr = ntasks; } out: +if (threads) +atomic_set (&threads->refcnt,1 );return threads; out_free_threads:
@@ -292,9 +301,26 @@ 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) { -free (threads); +if (threads) { +WARN_ONCE (atomic_read (&threads->refcnt) !=0 , +"thread map refcnt unbalanced\n" ); +free (threads); + } +} + +struct thread_map *thread_map__get (struct thread_map *map) +{ +if (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,12 +3,14 @@#include <sys/types.h> #include <stdio.h> +#include <linux/atomic.h> struct thread_map_data {pid_t pid; };struct thread_map { +atomic_t refcnt;int nr;struct thread_map_data map[]; };
@@ -19,11 +21,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)
Jiri Olsa
reviewerPATCH v4 5/27 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 | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +24 -1
@@ -1101,6 +1101,29 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); } +static int perf_evlist__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,
@@ -1117,7 +1140,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return 0 ; +return perf_evlist__propagate_maps (evlist, target); out_delete_threads:thread_map__put (evlist->threads);
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
tip-bot for Jiri Olsa
merge bot[tip:perf/urgent] perf evlist: Propagate cpu maps to evsels in an evlist
perf evlist: Propagate cpu maps to evsels in an evlist
Commit-ID: b7f0c203586b91419ff9aa9b1115e261082ff5b4 Gitweb: http://git.kernel.org/tip/b7f0c203586b91419ff9aa9b1115e261082ff5b4 Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 23 Jun 2015 00:36:06 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 25 Jun 2015 15:15:51 -0300
perf evlist: Propagate cpu maps to evsels in an evlist
Propagate 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 | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +24 -1
@@ -1101,6 +1101,29 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); } +static int perf_evlist__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,
@@ -1117,7 +1140,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return 0 ; +return perf_evlist__propagate_maps (evlist, target); out_delete_threads:thread_map__put (evlist->threads);
Jiri Olsa
reviewerPATCH v4 6/27 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
@@ -1117,7 +1117,9 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,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
@@ -886,6 +886,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
tip-bot for Jiri Olsa
merge bot[tip:perf/urgent] perf evlist: Propagate thread maps through the evlist
perf evlist: Propagate thread maps through the evlist
Commit-ID: 578e91ec04d03aca89e300151addb3e3ed5b06ea Gitweb: http://git.kernel.org/tip/578e91ec04d03aca89e300151addb3e3ed5b06ea Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 23 Jun 2015 00:36:07 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 25 Jun 2015 15:15:51 -0300
perf evlist: Propagate thread maps through the evlist
Propagate 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
@@ -1117,7 +1117,9 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,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
@@ -886,6 +886,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;
Jiri Olsa
reviewerPATCH v4 7/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
tip-bot for Jiri Olsa
merge bot[tip:perf/urgent] perf tools: Make perf_evsel__(nr_)cpus generic
perf tools: Make perf_evsel__(nr_)cpus generic
Commit-ID: a22e99cd74a31dee4b5241bd60a256c629c808da Gitweb: http://git.kernel.org/tip/a22e99cd74a31dee4b5241bd60a256c629c808da Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 23 Jun 2015 00:36:08 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 25 Jun 2015 17:15:39 -0300
perf tools: Make perf_evsel__(nr_)cpus generic
Because 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);
Jiri Olsa
reviewerPATCH v4 8/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 9/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 09/27] perf stat: Introduce perf_counts function
Em Tue, Jun 23, 2015 at 12:36:10AM +0200, Jiri Olsa escreveu:
tools/perf/builtin-stat.c static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, · line 319
Quoted 4 lines
Introducing
perf_countsfunction, that returns 'structperf_counts_values' pointer for given cpu.tools/perf/builtin-stat.c +1
-1- evsel->counts->cpu[cpu] = *count; + *perf_counts (evsel->counts, cpu) = *count;
For consistency, just like thread_map__set_pid(), please have a:
perf_counts__set(evsel->counts, *cont);
In addition to its counterpart:
perf_counts__value(evsel->counts, cpu);
Since you're not storing multiple entries per bucket, we need to use the "value" idiom.
- Arnaldo
Re: [PATCH 09/27] perf stat: Introduce perf_counts function
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Tue, Jun 23, 2015 at 12:36:10AM +0200, Jiri Olsa escreveu:
tools/perf/builtin-stat.c static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, · line 319
Quoted 4 lines
Introducing
perf_countsfunction, that returns 'structperf_counts_values' pointer for given cpu.tools/perf/builtin-stat.c +1
-1- evsel->counts->cpu[cpu] = *count; + *perf_counts (evsel->counts, cpu) = *count;For consistency, just like
thread_map__set_pid(), please have a:
it's consistent with xyarray__entry
Quoted 9 lines
perf_counts__set(evsel->counts, *cont);In addition to its counterpart:
perf_counts__value(evsel->counts, cpu);Since you're not storing multiple entries per bucket, we need to use the "value" idiom.
perf_counts returns pointer to the 'struct perf_counts_values' which is clean and valid and IMO the code is more readable
You use just 'perf_counts(counts, cpu, thread)' and get values and do whatever you want with them.. why introduce 2 functions for it?
thanks,
jirka
Jiri Olsa
reviewerPATCH v4 10/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 11/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 12/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 13/27 perf stat: Introduce perf_evlist__reset_stats
In reply to Jiri OlsaTo fit in with the rest of the helpers (alloc and free).
--- tools/perf/builtin-stat.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/perf/builtin-stat.c +6 -2
@@ -216,7 +216,7 @@ out_free:return -1 ; } -static void perf_stat__reset_stats (struct perf_evlist *evlist) +static void perf_evlist__reset_stats (struct perf_evlist *evlist) {struct perf_evsel *evsel;
@@ -224,7 +224,11 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)perf_evsel__reset_stat_priv (evsel);perf_evsel__reset_counts (evsel); } +} +static void perf_stat__reset_stats (void ) +{ +perf_evlist__reset_stats (evsel_list);perf_stat__reset_shadow_stats (); }
@@ -1473,7 +1477,7 @@ 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); -perf_stat__reset_stats (evsel_list); +perf_stat__reset_stats (); } }
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 14/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 15/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 16/27 perf stat: Move perf_evlist__(alloc|free|reset)_stats into stat object
In reply to Jiri OlsaMoving perf_evlist__(alloc|free|reset)_stats into stat object, so it could be used in following patches.
--- tools/perf/builtin-stat.c | 42 ------------------------------------------ tools/perf/util/evlist.h | 1 - tools/perf/util/stat.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 6 ++++++ 4 files changed, 50 insertions(+), 43 deletions(-)
tools/perf/builtin-stat.c +0 -42
@@ -141,48 +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_evlist__reset_stats (struct perf_evlist *evlist) -{ -struct perf_evsel *evsel; - -evlist__for_each (evlist, evsel) { -perf_evsel__reset_stat_priv (evsel); -perf_evsel__reset_counts (evsel); - } -} -static void perf_stat__reset_stats (void ) {perf_evlist__reset_stats (evsel_list);
tools/perf/util/evlist.h +0 -1
@@ -289,5 +289,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 +44 -0
53 lines not on this page · raw message
tools/perf/util/stat.h +6 -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,8 @@ 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); +void perf_evlist__reset_stats (struct perf_evlist *evlist);#endif
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 17/27 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);void perf_evlist__reset_stats (struct perf_evlist *evlist);
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 18/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 19/27 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
@@ -323,27 +323,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);
@@ -525,18 +533,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 20/27 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
@@ -217,8 +217,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;
@@ -239,7 +240,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 ;
@@ -256,23 +256,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);
@@ -315,7 +333,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 ; } }
@@ -332,10 +353,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 21/27 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
@@ -285,6 +285,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;
@@ -328,9 +331,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 22/27 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
@@ -284,6 +284,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);
@@ -347,12 +348,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 23/27 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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 24/27 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
@@ -363,7 +363,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;
@@ -526,7 +526,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);
@@ -544,7 +544,7 @@ static int __run_perf_stat(int argc, const char **argv)while (!done) {nanosleep (&ts,NULL );if (interval) -print_interval (); +process_interval (); } }
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 25/27 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
@@ -284,7 +284,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 · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 26/27 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 = {
@@ -365,53 +362,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 )
@@ -901,9 +859,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);
@@ -929,36 +913,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 ;
@@ -1407,13 +1408,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 (); } }if (!forever && status !=-1 && !interval) -print_stat (argc, argv); +print_counters (NULL , argc, argv);perf_evlist__free_stats (evsel_list); out:
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Jiri Olsa
reviewerPATCH v4 27/27 perf stat: Introduce --per-thread 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-thread -p 30190,30242 ^C Performance counter stats for process id '30190,30242':
cat-30190 0 cycles
yes-30242 3,842,525,421 cycles
cat-30190 0 instructions
yes-30242 10,370,817,010 instructions1.143155657 seconds time elapsed
Also works under interval mode:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242 -I 1000
# time comm-pid counts unit events
1.000073435 cat-30190 89,058 cycles
1.000073435 yes-30242 3,360,786,902 cycles (100.00%)
1.000073435 cat-30190 14,066 instructions
1.000073435 yes-30242 9,069,937,462 instructions
2.000204830 cat-30190 0 cycles
2.000204830 yes-30242 3,351,667,626 cycles
2.000204830 cat-30190 0 instructions
2.000204830 yes-30242 9,045,796,885 instructions
^C 2.771286639 cat-30190 0 cycles
2.771286639 yes-30242 2,593,884,166 cycles
2.771286639 cat-30190 0 instructions
2.771286639 yes-30242 7,001,171,191 instructionsIt works only with -t and -p options, otherwise following error is printed:
$ perf stat -e cycles --per-thread -I 1000 ls
The --per-thread option is only available when monitoring 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 | 4 ++ tools/perf/builtin-stat.c | 68 +++++++++++++++++++++++++++++++++- tools/perf/util/stat.h | 1 + 3 files changed, 71 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-stat.txt +4 -0
@@ -144,6 +144,10 @@ 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-thread:: +Aggregate counts per monitored threads, when monitoring 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 +66 -2
116 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_THREAD, }; struct perf_counts_values {
Signature · 5 lines
1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Arnaldo Carvalho de Melo
maintainerEm Tue, Jun 23, 2015 at 12:36:01AM +0200, Jiri Olsa escreveu:
Quoted 6 lines
hi,
adding the possibility to display stat data per thread.Allowing following commands and output:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242
While testing Adrian's Intel PT patchkit I realised we have --per-thread in 'record', wonder if using a long option with the exact same name but different meanings for 'stat' and 'record' would cause confusion...
- Arnaldo
Quoted 113 lines
^C
Performance counter stats for process id '30190,30242':cat-30190 0 cycles yes-30242 3,842,525,421 cycles cat-30190 0 instructions yes-30242 10,370,817,010 instructions1.143155657 seconds time elapsedAlso works under interval mode:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242 -I 1000 # time comm-pid counts unit events 1.000073435 cat-30190 89,058 cycles 1.000073435 yes-30242 3,360,786,902 cycles (100.00%) 1.000073435 cat-30190 14,066 instructions 1.000073435 yes-30242 9,069,937,462 instructions 2.000204830 cat-30190 0 cycles 2.000204830 yes-30242 3,351,667,626 cycles 2.000204830 cat-30190 0 instructions 2.000204830 yes-30242 9,045,796,885 instructions ^C 2.771286639 cat-30190 0 cycles 2.771286639 yes-30242 2,593,884,166 cycles 2.771286639 cat-30190 0 instructions 2.771286639 yes-30242 7,001,171,191 instructionsAvailable in here:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/per_threadv4 changes:
- addthread_map__set_(pid|comm)interface
- several fixes for task comm string reading
- addedperf_evlist__reset_statsfunctionv3 changes:
- some patches already pulled in, rebased on latest acme's perf/core
- fixed cpu_map__get/thread_map__get to accept NULL map
- renamedpropagate_mapstoperf_evlist__propagate_maps
- renamed --per-task option to --per-thread
- changed 'task-pid' header output to 'comm-pid'v2 changes:
- renamedxyarray__zerotoxyarray__reset
- usingatomic_tfor cpu_map/thread_map refcnt
- moving all stat functions into stat object
- usinginit_statsto initialize 'struct stats*'
- change TASK-$pid output into $comm-$pid
- updated doc with --per-task optionthanks,
jirka
---
Jiri Olsa (27):
perf tools: Changethread_map::mapinto struct
perf tools: Add comm string into structthread_map
perf tools: Add reference counting forcpu_mapobject
perf tools: Add reference counting forthread_mapobject 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 tests: Addthread_mapobject tests
perf stat: Introduceperf_countsfunction
perf stat: Use xyarray for cpu evsel counts
perf stat: Make stats work over the thread dimension
perf stat: Rename structperf_counts::cpumember to values perf stat: Introduceperf_evlist__reset_stats
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|reset)_stats into stat object perf stat: Introduceperf_evsel__alloc_statsfunction
perf stat: Introduceperf_evsel__readfunction
perf stat: Introduceread_countersfunction
perf stat: Separate counters reading and processing
perf stat: Movezero_per_pkginto counter process code
perf stat: Moveperf_statinitialization counter process code perf stat: Removeperf_evsel__read_cbfunction
perf stat: Renameprint_intervaltoprocess_interval
perf stat: Usinginit_statsinstead of memset
perf stat: Introduceprint_countersfunction
perf stat: Introduce --per-thread optiontools/perf/Documentation/perf-stat.txt | 4 + tools/perf/builtin-stat.c | 404 ++++++++++++++-------------- 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 | 8 +- 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 | 26 +- tools/perf/util/cpumap.h | 6 +- tools/perf/util/event.c | 6 +- tools/perf/util/evlist.c | 39 ++- tools/perf/util/evlist.h | 1 - tools/perf/util/evsel.c | 28 +- tools/perf/util/evsel.h | 40 ++- tools/perf/util/parse-events.c | 5 +- tools/perf/util/python-ext-sources | 1 + tools/perf/util/python.c | 4 +- tools/perf/util/record.c | 4 +-
Quoted 8 lines
tools/perf/util/session.c | 2 +- tools/perf/util/stat.c | 132 ++++++++- tools/perf/util/stat.h | 47 +++- tools/perf/util/svghelper.c | 2 +- tools/perf/util/thread_map.c | 118 ++++++-- tools/perf/util/thread_map.h | 35 ++- 33 files changed, 661 insertions(+), 319 deletions(-) create mode 100644 tools/perf/tests/thread-map.c
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Quoted 11 lines · Arnaldo Carvalho de Melo
Em Tue, Jun 23, 2015 at 12:36:01AM +0200, Jiri Olsa escreveu:
Quoted 6 lines
hi,
adding the possibility to display stat data per thread.Allowing following commands and output:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242While testing Adrian's Intel PT patchkit I realised we have --per-thread in 'record', wonder if using a long option with the exact same name but different meanings for 'stat' and 'record' would cause confusion...
I think the name fits for both stat and record.. and both are doing different thing, so both --per-thread are also different.. and well documented ;-)
jirka
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Arnaldo Carvalho de Melo
maintainerEm Tue, Jun 23, 2015 at 09:22:00AM +0200, Jiri Olsa escreveu:
Quoted 6 lines · Arnaldo Carvalho de Melo
Quoted 4 lines
Em Tue, Jun 23, 2015 at 12:36:01AM +0200, Jiri Olsa escreveu:
Quoted 3 lines
adding the possibility to display stat data per thread.
Allowing following commands and output:
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
$ perf stat -e cycles,instructions --per-thread -p 30190,30242While testing Adrian's Intel PT patchkit I realised we have --per-thread in 'record', wonder if using a long option with the exact same name but different meanings for 'stat' and 'record' would cause confusion...
I think the name fits for both stat and record.. and both are doing different
For record it is vague, for stat, it seems to fit.
For record it really should be --mmap-per-thread, but then we start getting what may seem overly long options, but then, its an oddball 'record' option...
We have perf_evsel__open_per_thread(), that is used in builtin-stat.c, and that means: Open a descriptor per thread, but then, perf_target.per_thread only means, hey optimize things when setting up the perf_event_attr, which so far means just use it as one of the things to decide if PERF_SAMPLE_TIME should be set.
Just raising some concerns about consistency...
Quoted 1 line
thing, so both --per-thread are also different.. and well documented ;-)
The fact that something is documented doesn't avoid the initial expectation that since it has the same name, and that its part of a collection of tools, that it should have the same meaning, which means maybe the existing option, being the oddball, should be changed to better reflect what it asks the tool to do.
In fact, when we don't have to read documentation and things make sense, that is the ideal, huh?
We should be more careful with this to avoid breaking too many expectations when switching from one tool to another in the same collection.
What others have to say? Ingo?
- Arnaldo
Adrian Hunter
reviewerQuoted 13 lines · Arnaldo Carvalho de Melo
Em Tue, Jun 23, 2015 at 09:22:00AM +0200, Jiri Olsa escreveu:
Quoted 11 lines · Arnaldo Carvalho de Melo
Quoted 10 lines
Em Tue, Jun 23, 2015 at 12:36:01AM +0200, Jiri Olsa escreveu:
Quoted 5 lines
adding the possibility to display stat data per thread.
Allowing following commands and output:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242While testing Adrian's Intel PT patchkit I realised we have --per-thread in 'record', wonder if using a long option with the exact same name but different meanings for 'stat' and 'record' would cause confusion...
Quoted 7 lines
Quoted 1 line
I think the name fits for both stat and record.. and both are doing different
For record it is vague, for stat, it seems to fit.
For record it really should be --mmap-per-thread, but then we start getting what may seem overly long options, but then, its an oddball 'record' option...
It is not just the mmap, it is also the perf context. So it is central to the way perf works.
Arnaldo Carvalho de Melo
maintainerEm Tue, Jun 23, 2015 at 05:08:07PM +0300, Adrian Hunter escreveu:
Quoted 16 lines · Arnaldo Carvalho de Melo
Quoted 15 lines
Em Tue, Jun 23, 2015 at 09:22:00AM +0200, Jiri Olsa escreveu:
Quoted 13 lines · Arnaldo Carvalho de Melo
Quoted 10 lines
Em Tue, Jun 23, 2015 at 12:36:01AM +0200, Jiri Olsa escreveu:
Quoted 5 lines
adding the possibility to display stat data per thread.
Allowing following commands and output:
$ perf stat -e cycles,instructions --per-thread -p 30190,30242While testing Adrian's Intel PT patchkit I realised we have --per-thread in 'record', wonder if using a long option with the exact same name but different meanings for 'stat' and 'record' would cause confusion...
I think the name fits for both stat and record.. and both are doing different
Quoted 8 lines
Quoted 5 lines
For record it is vague, for stat, it seems to fit.
For record it really should be --mmap-per-thread, but then we start getting what may seem overly long options, but then, its an oddball 'record' option...
It is not just the mmap, it is also the perf context. So it is central to the way perf works.
Ok, so probably it should stay like that :-)
- Arnaldo