perf stat: Introduce --per-task option
Jiri Olsa
reviewercover perf stat: Introduce --per-task option
hi,
adding the possibility to display stat data per thread. Allowing following commands and output:
$ perf stat -e cycles,instructions --per-task -p 12451,16173 ^C Performance counter stats for process id '12451,16173':
TASK-12451 77,784 cycles TASK-16173 64,809 cycles TASK-12451 14,432 instructions TASK-16173 14,452 instructions
3.854957122 seconds time elapsed
Also woks under interval mode:
$ ./perf stat -e cycles,instructions --per-task -p 16431,16173 -I 1000
# time task counts unit events
1.000085816 TASK-16173 0 cycles
1.000085816 TASK-16431 3,358,360,926 cycles
1.000085816 TASK-16173 0 instructions
1.000085816 TASK-16431 9,062,422,086 instructions
2.000212262 TASK-16173 65,386 cycles
2.000212262 TASK-16431 3,349,355,309 cycles
2.000212262 TASK-16173 12,151 instructions
2.000212262 TASK-16431 9,039,401,422 instructions
3.000333402 TASK-16173 62,797 cycles
3.000333402 TASK-16431 3,357,140,183 cycles
3.000333402 TASK-16173 12,208 instructions
3.000333402 TASK-16431 9,058,080,762 instructions
^C 3.375949851 TASK-16173 0 cycles
3.375949851 TASK-16431 1,264,764,804 cycles
3.375949851 TASK-16173 0 instructions
3.375949851 TASK-16431 3,414,532,317 instructionsthanks for comments,
jirka
---
Jiri Olsa (25):
perf tools: Fix python code with missing stat dependency
perf tools: Introduce xyarray__zero function
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 stat: Introduce perf_counts__(alloc|free|reset) functions perf stat: Introduce perf_counts function
perf stat: Use xyarray for cpu evsel counts
perf stat: Make stats work over the thread dimension
perf stat: Rename struct perf_counts::cpu member to values perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into evsel object perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into evsel object perf stat: Move perf_evlist__(alloc|free)_stats into evlist object perf stat: Introduce perf_evsel__alloc_stats function
perf stat: Introduce perf_evsel__read function
perf stat: Introduce read_counters function
perf stat: Separate counters reading and processing
perf stat: Move zero_per_pkg into counter process code
perf stat: Move perf_stat initialization counter process code perf stat: Remove perf_evsel__read_cb function
perf stat: Rename print_interval to process_interval
perf stat: Introduce print_counters function
perf stat: Introduce --per-task option
tools/perf/builtin-stat.c | 388 +++++++++++++++++++++++++++++-------------------------------- 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.c | 6 +- tools/perf/tests/switch-tracking.c | 4 +- tools/perf/util/cpumap.c | 24 +++- tools/perf/util/cpumap.h | 5 +- tools/perf/util/evlist.c | 61 +++++++++- tools/perf/util/evlist.h | 2 + tools/perf/util/evsel.c | 128 ++++++++++++++++---- tools/perf/util/evsel.h | 48 ++++++-- 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.h | 1 + tools/perf/util/svghelper.c | 2 +- tools/perf/util/thread_map.c | 28 ++++- tools/perf/util/thread_map.h | 6 +- tools/perf/util/xyarray.c | 8 ++ tools/perf/util/xyarray.h | 2 + 25 files changed, 484 insertions(+), 267 deletions(-)
Jiri Olsa
reviewerPATCH 1/25 perf tools: Fix python code with missing stat dependency
The evsel object now depends on stat object and breaks python code because of missing stat object dependency. Putting stat.c object into python object list.
--- tools/perf/util/python-ext-sources | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/python-ext-sources +1 -0
@@ -18,4 +18,5 @@ util/cgroup.c util/rblist.c util/strlist.c util/trace-event.c +util/stat.c ../../lib/rbtree.c
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 01/25] perf tools: Fix python code with missing stat dependency
Em Wed, Jun 10, 2015 at 08:10:34PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
The evsel object now depends on stat object and breaks python code because of missing stat object dependency. Putting
stat.cobject into python object list.
Applied, but 'perf test python' was Okaying me before and after this change, strange :-\
- Arnaldo
Quoted 18 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/python-ext-sources | 1 + 1 file changed, 1 insertion(+)tools/perf/util/python-ext-sources +1
-0@@ -18,4 +18,5 @@ util/cgroup.c util/rblist.c util/strlist.c util/trace-event.c +util/stat.c ../../lib/rbtree.cSignature · 1 line
1.9.3
Re: [PATCH 01/25] perf tools: Fix python code with missing stat dependency
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:34PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
The evsel object now depends on stat object and breaks python code because of missing stat object dependency. Putting
stat.cobject into python object list.Applied, but 'perf test python' was Okaying me before and after this change, strange :-\
did you do 'make clean' ? there's not perfect dependency checking for python binding building ;-)
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 01/25] perf tools: Fix python code with missing stat dependency
Em Wed, Jun 10, 2015 at 10:23:48PM +0200, Jiri Olsa escreveu:
Quoted 11 lines · Arnaldo Carvalho de Melo
Quoted 7 lines
Em Wed, Jun 10, 2015 at 08:10:34PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
The evsel object now depends on stat object and breaks python code because of missing stat object dependency. Putting
stat.cobject into python object list.Applied, but 'perf test python' was Okaying me before and after this change, strange :-\
did you do 'make clean' ? there's not perfect dependency checking for python binding building ;-)
I guess I did that, yes ;-)
But to make sure:
[acme@zoo linux]$ type perf
perf is /home/acme/bin/perf
[acme@zoo linux]$ rm -f ~/bin/perf
[acme@zoo linux]$ type perf
bash: type: perf: not found
[acme@zoo linux]$ rm -rf /tmp/build/perf
[acme@zoo linux]$ perf
bash: perf: command not found...
Install package 'perf' to provide command 'perf'? [N/y] n [acme@zoo linux]$ mkdir -p /tmp/build/perf
[acme@zoo linux]$ alias m
alias m='time make O=/tmp/build/perf -C tools/perf install-bin' [acme@zoo linux]$ m
make: Entering directory '/home/git/linux/tools/perf'
BUILD: Doing 'make -j4' parallel build
Auto-detecting system features:
... dwarf: [ on ] ... glibc: [ on ] ... gtk2: [ on ] ... libaudit: [ on ] ... libbfd: [ on ] ... libelf: [ on ] ... libnuma: [ on ] ... libperl: [ on ] ... libpython: [ on ] ... libslang: [ on ] ... libunwind: [ on ] ... libdw-dwarf-unwind: [ on ] ... zlib: [ on ] ... lzma: [ on ]
MKDIR /tmp/build/perf/util/ CC /tmp/build/perf/util/abspath.o MKDIR /tmp/build/perf/fd/ CC /tmp/build/perf/fd/array.o CC /tmp/build/perf/event-parse.o <SNIP> INSTALL perl-scripts INSTALL python-scripts INSTALL perf_completion-script
make: Leaving directory '/home/git/linux/tools/perf'
real 0m9.785s
user 0m15.868s
sys 0m5.756s
[acme@zoo linux]$
[acme@zoo linux]$ perf test python
17: Try 'import perf' in python, checking link problems : Ok
[acme@zoo linux]$ su -
Password:
[root@zoo ~]# perf test python
17: Try 'import perf' in python, checking link problems : Ok
[root@zoo ~]# type perf
perf is hashed (/root/bin/perf)
[root@zoo ~]# ls -la ~/bin/perf
lrwxrwxrwx. 1 root root 19 Apr 29 15:58 /root/bin/perf -> /home/acme/bin/perf [root@zoo ~]#
So, it still works well, without your patch.
- Arnaldo
Re: [PATCH 01/25] perf tools: Fix python code with missing stat dependency
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 10:23:48PM +0200, Jiri Olsa escreveu:
Quoted 6 lines · Arnaldo Carvalho de Melo
Quoted 5 lines
Em Wed, Jun 10, 2015 at 08:10:34PM +0200, Jiri Olsa escreveu:
Quoted 3 lines
The evsel object now depends on stat object and breaks python code because of missing stat object dependency. Putting
stat.cobject into python object list.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Applied, but 'perf test python' was Okaying me before and after this change, strange :-\
did you do 'make clean' ? there's not perfect dependency checking for python binding building ;-)
I guess I did that, yes ;-)
ugh, the new version is all stat specific.. so no evsel dependency sry for the noise ;-)
jirka
Jiri Olsa
reviewerPATCH 2/25 perf tools: Introduce xyarray__zero function
In reply to Jiri OlsaTo zero all the xyarray contents. It will be used
in following patches.
--- tools/perf/util/xyarray.c | 8 ++++++++ tools/perf/util/xyarray.h | 2 ++ 2 files changed, 10 insertions(+)
tools/perf/util/xyarray.c +8 -0
@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)if (xy !=NULL ) { xy->entry_size = entry_size; xy->row_size = row_size; + xy->entries = xlen * ylen; }return xy; } +void xyarray__zero (struct xyarray *xy) +{ +size_t n = xy->entries * xy->entry_size; + +memset (xy->contents,0 , n); +} +void xyarray__delete (struct xyarray *xy) {free (xy);
tools/perf/util/xyarray.h +2 -0
@@ -6,11 +6,13 @@struct xyarray {size_t row_size;size_t entry_size; +size_t entries;char contents[]; };struct xyarray *xyarray__new (int xlen,int ylen,size_t entry_size);void xyarray__delete (struct xyarray *xy); +void xyarray__zero (struct xyarray *xy);static inline void *xyarray__entry (struct xyarray *xy,int x,int y) {
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/25] perf tools: Introduce xyarray__zero function
Em Wed, Jun 10, 2015 at 08:10:35PM +0200, Jiri Olsa escreveu:
Quoted 2 lines
To zero all the xyarray contents. It will be used
in following patches.
I guess I would prefer xyarray__memset(), similar semantics as 'memset()', but I did a quick look and this is used in the kernel in things like bitmap_zero() and wrappers to it have that semantic...
Interesting that we don't have anymore a bzero() like function, but then, looking at 'man bzero':
----------------------------
CONFORMING TO
4.3BSD. This function is deprecated (marked as LEGACY in
POSIX.1-2001): use memset(3) in new programs. POSIX.1-2008 removes the specification of bzero().
-----------------------------
Guess we should use 'xyarray__memset()', ok?
- Arnaldo
Quoted 51 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/xyarray.c | 8 ++++++++ tools/perf/util/xyarray.h | 2 ++ 2 files changed, 10 insertions(+)tools/perf/util/xyarray.c +8
-0@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)if (xy !=NULL ) { xy->entry_size = entry_size; xy->row_size = row_size; + xy->entries = xlen * ylen; }return xy; } +void xyarray__zero (struct xyarray *xy) +{ +size_t n = xy->entries * xy->entry_size; + +memset (xy->contents,0 , n); +} +void xyarray__delete (struct xyarray *xy) {free (xy);tools/perf/util/xyarray.h +2
-0@@ -6,11 +6,13 @@struct xyarray {size_t row_size;size_t entry_size; +size_t entries;char contents[]; };struct xyarray *xyarray__new (int xlen,int ylen,size_t entry_size);void xyarray__delete (struct xyarray *xy); +void xyarray__zero (struct xyarray *xy);static inline void *xyarray__entry (struct xyarray *xy,int x,int y) {Signature · 1 line
1.9.3
Re: [PATCH 02/25] perf tools: Introduce xyarray__zero function
Quoted 14 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:35PM +0200, Jiri Olsa escreveu:
Quoted 2 lines
To zero all the xyarray contents. It will be used
in following patches.I guess I would prefer
xyarray__memset(), similar semantics as 'memset()', but I did a quick look and this is used in the kernel in things likebitmap_zero()and wrappers to it have that semantic...Interesting that we don't have anymore a
bzero()like function, but then, looking at 'man bzero':----------------------------
CONFORMING TO
Quoted 7 lines
4.3BSD. This function is deprecated (marked as LEGACY in
POSIX.1-2001): use memset(3) in new programs. POSIX.1-2008 removes the specification ofbzero().-----------------------------
Guess we should use '
xyarray__memset()', ok?
hum, how about xyarray__reset ?
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/25] perf tools: Introduce xyarray__zero function
Em Wed, Jun 10, 2015 at 10:01:38PM +0200, Jiri Olsa escreveu:
Quoted 8 lines · Arnaldo Carvalho de Melo
Quoted 5 lines
Em Wed, Jun 10, 2015 at 08:10:35PM +0200, Jiri Olsa escreveu:
Quoted 2 lines
To zero all the xyarray contents. It will be used
in following patches.Guess we should use '
xyarray__memset()', ok?hum, how about
xyarray__reset?
I am ok with it, its already used in many places:
[acme@zoo linux]$ find tools -name "*.[ch]" | xargs grep __reset | wc -l 60
[acme@zoo linux]$
- Arnaldo
Jiri Olsa
reviewerPATCH 3/25 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 | 24 ++++++++++++++++++++++-- tools/perf/util/cpumap.h | 5 ++++- 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, 42 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 +22 -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; + 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); + cpus->refcnt =1 ; }return cpus;
@@ -194,14 +197,30 @@ struct cpu_map *cpu_map__dummy_new(void)if (cpus !=NULL ) { cpus->nr =1 ; cpus->map[0 ] =-1 ; + 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 (map->refcnt !=0 ,"cpu map refcnt disbalanced\n" ); +free (map); + } +} + +struct cpu_map *cpu_map__get (struct cpu_map *map) +{ + map->refcnt++; +return map; +} + +void cpu_map__put (struct cpu_map *map) +{ +if (map && --map->refcnt ==0 ) +cpu_map__delete (map); }int cpu_map__get_socket (struct cpu_map *map,int idx)
@@ -263,6 +282,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); + c->refcnt =1 ; *res = c;return 0 ; }
tools/perf/util/cpumap.h +4 -1
@@ -8,13 +8,13 @@#include "util/debug.h" struct cpu_map { +int 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 +22,9 @@ int cpu_map__get_core(struct cpu_map *map, int idx);int cpu_map__build_socket_map (struct cpu_map *cpus,struct cpu_map **sockp);int cpu_map__build_core_map (struct cpu_map *cpus,struct cpu_map **corep); +struct cpu_map *cpu_map__get (struct cpu_map *map); +void cpu_map__put (struct cpu_map *map); +static inline int cpu_map__socket (struct cpu_map *sock,int s) {if (!sock || s > sock->nr || s <0 )
tools/perf/util/evlist.c +2 -2
@@ -114,7 +114,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) {perf_evlist__munmap (evlist);perf_evlist__close (evlist); -cpu_map__delete (evlist->cpus); +cpu_map__put (evlist->cpus);thread_map__delete (evlist->threads); evlist->cpus =NULL ; evlist->threads =NULL ;
@@ -1337,7 +1337,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) out:return err; out_free_cpus: -cpu_map__delete (evlist->cpus); +cpu_map__put (evlist->cpus); evlist->cpus =NULL ; goto out; }
tools/perf/util/evsel.c +1 -0
@@ -902,6 +902,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)perf_evsel__free_fd (evsel);perf_evsel__free_id (evsel);close_cgroup (evsel->cgrp); +cpu_map__put (evsel->cpus);zfree (&evsel->group_name);zfree (&evsel->name); perf_evsel__object.fini (evsel);
tools/perf/util/parse-events.c +4 -1
@@ -17,6 +17,7 @@#include "parse-events-flex.h" #include "pmu.h" #include "thread_map.h" +#include "cpumap.h" #include "asm/bug.h" #define MAX_NAME_LEN 100
@@ -285,7 +286,9 @@ __add_event(struct list_head *list, int *idx,if (!evsel)return NULL ; - evsel->cpus = cpus; +if (cpus) + evsel->cpus =cpu_map__get (cpus); +if (name) evsel->name =strdup (name);list_add_tail (&evsel->node, list);
tools/perf/util/python.c +1 -1
@@ -384,7 +384,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,static void pyrf_cpu_map__delete (struct pyrf_cpu_map *pcpus) { -cpu_map__delete (pcpus->cpus); +cpu_map__put (pcpus->cpus); pcpus->ob_type->tp_free ((PyObject *)pcpus); }
tools/perf/util/record.c +2 -2
@@ -64,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn)if (!cpus)return false; cpu = cpus->map[0 ]; -cpu_map__delete (cpus); +cpu_map__put (cpus); do { ret = perf_do_probe_api(fn, cpu, try[i++]);
@@ -226,7 +226,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)struct cpu_map *cpus =cpu_map__new (NULL ); cpu = cpus ? cpus->map[0 ] :0 ; -cpu_map__delete (cpus); +cpu_map__put (cpus); }else { cpu = evlist->cpus->map[0 ]; }
tools/perf/util/session.c +1 -1
@@ -1838,7 +1838,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, err =0 ; out_delete_map: -cpu_map__delete (map); +cpu_map__put (map);return err; }
tools/perf/util/svghelper.c +1 -1
@@ -748,7 +748,7 @@ static int str_to_bitmap(char *s, cpumask_t *b)set_bit (c,cpumask_bits (b)); } -cpu_map__delete (m); +cpu_map__put (m);return ret; }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 03/25] perf tools: Add reference counting for cpu_map object
Em Wed, Jun 10, 2015 at 08:10:36PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding refference counting for
cpu_mapobject, so
it could be easily shared among other objects.Using
cpu_map__putinsteadcpu_map__deleteand makingcpu_map__deletestatic.
Please use atomic.h, as was done recently for the 'map', 'dso' and 'thread' structs, but other than that, its fine.
- Arnaldo
Quoted 288 lines
Signed-off-by Jiri Olsa <[email protected]>--- 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 | 24 ++++++++++++++++++++++-- tools/perf/util/cpumap.h | 5 ++++- 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, 42 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 +22
-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; + 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); + cpus->refcnt =1 ; }return cpus;@@ -194,14 +197,30 @@ struct cpu_map *cpu_map__dummy_new(void)if (cpus !=NULL ) { cpus->nr =1 ; cpus->map[0 ] =-1 ; + 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 (map->refcnt !=0 ,"cpu map refcnt disbalanced\n" ); +free (map); + } +} + +struct cpu_map *cpu_map__get (struct cpu_map *map) +{ + map->refcnt++; +return map; +} + +void cpu_map__put (struct cpu_map *map) +{ +if (map && --map->refcnt ==0 ) +cpu_map__delete (map); }int cpu_map__get_socket (struct cpu_map *map,int idx)@@ -263,6 +282,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); + c->refcnt =1 ; *res = c;return 0 ; }tools/perf/util/cpumap.h +4
-1@@ -8,13 +8,13 @@#include "util/debug.h" struct cpu_map { +int 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 +22,9 @@ int cpu_map__get_core(struct cpu_map *map, int idx);int cpu_map__build_socket_map (struct cpu_map *cpus,struct cpu_map **sockp);int cpu_map__build_core_map (struct cpu_map *cpus,struct cpu_map **corep); +struct cpu_map *cpu_map__get (struct cpu_map *map); +void cpu_map__put (struct cpu_map *map); +static inline int cpu_map__socket (struct cpu_map *sock,int s) {if (!sock || s > sock->nr || s <0 )tools/perf/util/evlist.c +2
-2@@ -114,7 +114,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) {perf_evlist__munmap (evlist);perf_evlist__close (evlist); -cpu_map__delete (evlist->cpus); +cpu_map__put (evlist->cpus);thread_map__delete (evlist->threads); evlist->cpus =NULL ; evlist->threads =NULL ;@@ -1337,7 +1337,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) out:return err; out_free_cpus: -cpu_map__delete (evlist->cpus); +cpu_map__put (evlist->cpus); evlist->cpus =NULL ; goto out; }tools/perf/util/evsel.c +1
-0@@ -902,6 +902,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)perf_evsel__free_fd (evsel);perf_evsel__free_id (evsel);close_cgroup (evsel->cgrp); +cpu_map__put (evsel->cpus);zfree (&evsel->group_name);zfree (&evsel->name); perf_evsel__object.fini (evsel);tools/perf/util/parse-events.c +4
-1@@ -17,6 +17,7 @@#include "parse-events-flex.h" #include "pmu.h" #include "thread_map.h" +#include "cpumap.h" #include "asm/bug.h" #define MAX_NAME_LEN 100@@ -285,7 +286,9 @@ __add_event(struct list_head *list, int *idx,if (!evsel)return NULL ; - evsel->cpus = cpus; +if (cpus) + evsel->cpus =cpu_map__get (cpus); +if (name) evsel->name =strdup (name);list_add_tail (&evsel->node, list);tools/perf/util/python.c +1
-1@@ -384,7 +384,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,static void pyrf_cpu_map__delete (struct pyrf_cpu_map *pcpus) { -cpu_map__delete (pcpus->cpus); +cpu_map__put (pcpus->cpus); pcpus->ob_type->tp_free ((PyObject *)pcpus); }tools/perf/util/record.c +2
-2@@ -64,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn)if (!cpus)return false; cpu = cpus->map[0 ]; -cpu_map__delete (cpus); +cpu_map__put (cpus); do { ret = perf_do_probe_api(fn, cpu, try[i++]);@@ -226,7 +226,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)struct cpu_map *cpus =cpu_map__new (NULL ); cpu = cpus ? cpus->map[0 ] :0 ; -cpu_map__delete (cpus); +cpu_map__put (cpus); }else { cpu = evlist->cpus->map[0 ]; }tools/perf/util/session.c +1
-1@@ -1838,7 +1838,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, err =0 ; out_delete_map: -cpu_map__delete (map); +cpu_map__put (map);return err; }tools/perf/util/svghelper.c +1
-1@@ -748,7 +748,7 @@ static int str_to_bitmap(char *s, cpumask_t *b)set_bit (c,cpumask_bits (b)); } -cpu_map__delete (m); +cpu_map__put (m);return ret; }Signature · 1 line
1.9.3
Re: [PATCH 03/25] perf tools: Add reference counting for cpu_map object
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:36PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding refference counting for
cpu_mapobject, so
it could be easily shared among other objects.Using
cpu_map__putinsteadcpu_map__deleteand makingcpu_map__deletestatic.Please use
atomic.h, as was done recently for the 'map', 'dso' and 'thread' structs, but other than that, its fine.
ook,
jirka
Jiri Olsa
reviewerPATCH 4/25 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 | 28 ++++++++++++++++++++++++++-- tools/perf/util/thread_map.h | 6 ++++-- 11 files changed, 40 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); -thread_map__delete (map); +thread_map__put (map);return err; }
tools/perf/tests/openat-syscall-all-cpus.c +1 -1
@@ -110,6 +110,6 @@ out_close_fd: out_evsel_delete:perf_evsel__delete (evsel); out_thread_map_delete: -thread_map__delete (threads); +thread_map__put (threads);return err; }
tools/perf/tests/openat-syscall.c +1 -1
@@ -56,6 +56,6 @@ out_close_fd: out_evsel_delete:perf_evsel__delete (evsel); out_thread_map_delete: -thread_map__delete (threads); +thread_map__put (threads);return err; }
tools/perf/tests/switch-tracking.c +1 -1
@@ -561,7 +561,7 @@ out:perf_evlist__delete (evlist); }else {cpu_map__put (cpus); -thread_map__delete (threads); +thread_map__put (threads); }return err;
tools/perf/util/evlist.c +2 -2
@@ -115,7 +115,7 @@ void perf_evlist__delete(struct perf_evlist *evlist)perf_evlist__munmap (evlist);perf_evlist__close (evlist);cpu_map__put (evlist->cpus); -thread_map__delete (evlist->threads); +thread_map__put (evlist->threads); evlist->cpus =NULL ; evlist->threads =NULL ;perf_evlist__purge (evlist);
@@ -1104,7 +1104,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)return 0 ; out_delete_threads: -thread_map__delete (evlist->threads); +thread_map__put (evlist->threads); evlist->threads =NULL ;return -1 ; }
tools/perf/util/python.c +1 -1
@@ -453,7 +453,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,static void pyrf_thread_map__delete (struct pyrf_thread_map *pthreads) { -thread_map__delete (pthreads->threads); +thread_map__put (pthreads->threads); pthreads->ob_type->tp_free ((PyObject *)pthreads); }
tools/perf/util/thread_map.c +26 -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"
@@ -38,6 +39,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)for (i =0 ; i < items; i++) threads->map[i] =atoi (namelist[i]->d_name); threads->nr = items; + threads->refcnt =1 ; }for (i=0 ; i<items; i++)
@@ -54,6 +56,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)if (threads !=NULL ) { threads->map[0 ] = tid; threads->nr =1 ; + threads->refcnt =1 ; }return threads;
@@ -75,6 +78,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) goto out_free_threads; threads->nr =0 ; + threads->refcnt =1 ;while (!readdir_r (proc, &dirent, &next) && next) {char *end;
@@ -202,6 +206,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) out:strlist__delete (slist); +if (threads) + threads->refcnt =1 ;return threads; out_free_namelist:
@@ -221,6 +227,7 @@ struct thread_map *thread_map__new_dummy(void)if (threads !=NULL ) { threads->map[0 ] =-1 ; threads->nr =1 ; + threads->refcnt =1 ; }return threads; }
@@ -263,6 +270,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) threads->nr = ntasks; } out: +if (threads) + threads->refcnt =1 ;return threads; out_free_threads:
@@ -282,9 +291,24 @@ 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 (threads->refcnt !=0 ,"thread map refcnt disbalanced\n" ); +free (threads); + } +} + +struct thread_map *thread_map__get (struct thread_map *map) +{ + map->refcnt++; +return map; +} + +void thread_map__put (struct thread_map *map) +{ +if (map && --map->refcnt ==0 ) +thread_map__delete (map); }size_t thread_map__fprintf (struct thread_map *threads,FILE *fp)
tools/perf/util/thread_map.h +4 -2
@@ -5,6 +5,7 @@#include <stdio.h> struct thread_map { +int refcnt;int nr;pid_t map[]; };
@@ -15,11 +16,12 @@ struct thread_map *thread_map__new_by_tid(pid_t tid);struct thread_map *thread_map__new_by_uid (uid_t uid);struct thread_map *thread_map__new (pid_t pid,pid_t tid,uid_t uid); +struct thread_map *thread_map__get (struct thread_map *map); +void thread_map__put (struct thread_map *map); +struct thread_map *thread_map__new_str (const char *pid,const char *tid,uid_t uid); -void thread_map__delete (struct thread_map *threads); -size_t thread_map__fprintf (struct thread_map *threads,FILE *fp);static inline int thread_map__nr (struct thread_map *threads)
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 04/25] perf tools: Add reference counting for thread_map object
Em Wed, Jun 10, 2015 at 08:10:37PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding refference counting for
thread_mapobject, so it could be easily shared among other objects.Using
thread_map__putinsteadthread_map__deleteand makingthread_map__deletestatic.
Please use atomic.h, as was done recently for the 'map', 'dso' and 'thread' structs, but other than that, its fine.
Quoted 257 lines
Signed-off-by Jiri Olsa <[email protected]>--- 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 | 28 ++++++++++++++++++++++++++-- tools/perf/util/thread_map.h | 6 ++++-- 11 files changed, 40 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); -thread_map__delete (map); +thread_map__put (map);return err; }tools/perf/tests/openat-syscall-all-cpus.c +1
-1@@ -110,6 +110,6 @@ out_close_fd: out_evsel_delete:perf_evsel__delete (evsel); out_thread_map_delete: -thread_map__delete (threads); +thread_map__put (threads);return err; }tools/perf/tests/openat-syscall.c +1
-1@@ -56,6 +56,6 @@ out_close_fd: out_evsel_delete:perf_evsel__delete (evsel); out_thread_map_delete: -thread_map__delete (threads); +thread_map__put (threads);return err; }tools/perf/tests/switch-tracking.c +1
-1@@ -561,7 +561,7 @@ out:perf_evlist__delete (evlist); }else {cpu_map__put (cpus); -thread_map__delete (threads); +thread_map__put (threads); }return err;tools/perf/util/evlist.c +2
-2@@ -115,7 +115,7 @@ void perf_evlist__delete(struct perf_evlist *evlist)perf_evlist__munmap (evlist);perf_evlist__close (evlist);cpu_map__put (evlist->cpus); -thread_map__delete (evlist->threads); +thread_map__put (evlist->threads); evlist->cpus =NULL ; evlist->threads =NULL ;perf_evlist__purge (evlist);@@ -1104,7 +1104,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)return 0 ; out_delete_threads: -thread_map__delete (evlist->threads); +thread_map__put (evlist->threads); evlist->threads =NULL ;return -1 ; }tools/perf/util/python.c +1
-1@@ -453,7 +453,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,static void pyrf_thread_map__delete (struct pyrf_thread_map *pthreads) { -thread_map__delete (pthreads->threads); +thread_map__put (pthreads->threads); pthreads->ob_type->tp_free ((PyObject *)pthreads); }tools/perf/util/thread_map.c +26
-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" @@ -38,6 +39,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)for (i =0 ; i < items; i++) threads->map[i] =atoi (namelist[i]->d_name); threads->nr = items; + threads->refcnt =1 ; }for (i=0 ; i<items; i++)@@ -54,6 +56,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)if (threads !=NULL ) { threads->map[0 ] = tid; threads->nr =1 ; + threads->refcnt =1 ; }return threads;@@ -75,6 +78,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) goto out_free_threads; threads->nr =0 ; + threads->refcnt =1 ;while (!readdir_r (proc, &dirent, &next) && next) {char *end;@@ -202,6 +206,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) out:strlist__delete (slist); +if (threads) + threads->refcnt =1 ;return threads; out_free_namelist:@@ -221,6 +227,7 @@ struct thread_map *thread_map__new_dummy(void)if (threads !=NULL ) { threads->map[0 ] =-1 ; threads->nr =1 ; + threads->refcnt =1 ; }return threads; }@@ -263,6 +270,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) threads->nr = ntasks; } out: +if (threads) + threads->refcnt =1 ;return threads; out_free_threads:@@ -282,9 +291,24 @@ 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 (threads->refcnt !=0 ,"thread map refcnt disbalanced\n" ); +free (threads); + } +} + +struct thread_map *thread_map__get (struct thread_map *map) +{ + map->refcnt++; +return map; +} + +void thread_map__put (struct thread_map *map) +{ +if (map && --map->refcnt ==0 ) +thread_map__delete (map); }size_t thread_map__fprintf (struct thread_map *threads,FILE *fp)tools/perf/util/thread_map.h +4
-2@@ -5,6 +5,7 @@#include <stdio.h> struct thread_map { +int refcnt;int nr;pid_t map[]; };@@ -15,11 +16,12 @@ struct thread_map *thread_map__new_by_tid(pid_t tid);struct thread_map *thread_map__new_by_uid (uid_t uid);struct thread_map *thread_map__new (pid_t pid,pid_t tid,uid_t uid); +struct thread_map *thread_map__get (struct thread_map *map); +void thread_map__put (struct thread_map *map); +struct thread_map *thread_map__new_str (const char *pid,const char *tid,uid_t uid); -void thread_map__delete (struct thread_map *threads); -size_t thread_map__fprintf (struct thread_map *threads,FILE *fp);static inline int thread_map__nr (struct thread_map *threads)Signature · 1 line
1.9.3
Re: [PATCH 04/25] perf tools: Add reference counting for thread_map object
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:37PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Adding refference counting for
thread_mapobject, so it could be easily shared among other objects.Using
thread_map__putinsteadthread_map__deleteand makingthread_map__deletestatic.Please use
atomic.h, as was done recently for the 'map', 'dso' and 'thread' structs, but other than that, its fine.
ook
jirka
Jiri Olsa
reviewerPATCH 5/25 perf tools: Propagate cpu maps through the evlist
In reply to Jiri OlsaPropagate evlist's cpu_map object through all the evsel objects, while keeping already configured evsel->cpus.
It'll be handy to access evsel's cpus directly
in following patches.
--- tools/perf/util/evlist.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +23 -1
@@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); } +static int propagate_maps (struct perf_evlist *evlist,struct target *target) +{ +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +/* +* We already have cpus for evsel (via PMU sysfs) so +* keep it, if there's no target cpu list defined. +*/ +if (evsel->cpus && target->cpu_list) +cpu_map__put (evsel->cpus); + +if (!evsel->cpus || target->cpu_list) + evsel->cpus =cpu_map__get (evlist->cpus); + +if (!evsel->cpus) +return -ENOMEM ; + } + +return 0 ; +} +int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid,
@@ -1101,7 +1123,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return 0 ; +return propagate_maps (evlist, target); out_delete_threads:thread_map__put (evlist->threads);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 05/25] perf tools: Propagate cpu maps through the evlist
Em Wed, Jun 10, 2015 at 08:10:38PM +0200, Jiri Olsa escreveu:
Quoted 19 lines
Propagate evlist's
cpu_mapobject through all the evsel objects, while keeping already configuredevsel->cpus.It'll be handy to access evsel's cpus directly
in following patches.Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/evlist.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)tools/perf/util/evlist.c +0
-0@@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); }
tools/perf/util/evlist.c int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · line 1096
Quoted 10 lines
tools/perf/util/evlist.c +9
-0+static int propagate_maps (struct perf_evlist *evlist,struct target *target) +{ +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +/* +* We already have cpus for evsel (via PMU sysfs) so +* keep it, if there's no target cpu list defined. +*/
There was some discussion about this with Stephane, lost track, will try to dig it... :-\
- Arnaldo
Quoted 27 lines
tools/perf/util/evlist.c +14
-1+if (evsel->cpus && target->cpu_list) +cpu_map__put (evsel->cpus); + +if (!evsel->cpus || target->cpu_list) + evsel->cpus =cpu_map__get (evlist->cpus); + +if (!evsel->cpus) +return -ENOMEM ; + } + +return 0 ; +} +int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid,@@ -1101,7 +1123,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)if (evlist->cpus ==NULL ) goto out_delete_threads; -return 0 ; +return propagate_maps (evlist, target); out_delete_threads:thread_map__put (evlist->threads);Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 6/25 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.
--- tools/perf/util/evlist.c | 4 +++- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +3 -1
@@ -1100,7 +1100,9 @@ static int propagate_maps(struct perf_evlist *evlist, struct target *target)if (!evsel->cpus || target->cpu_list) evsel->cpus =cpu_map__get (evlist->cpus); -if (!evsel->cpus) + evsel->threads =thread_map__get (evlist->threads); + +if (!evsel->cpus || !evsel->threads)return -ENOMEM ; }
tools/perf/util/evsel.c +1 -0
@@ -903,6 +903,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)perf_evsel__free_id (evsel);close_cgroup (evsel->cgrp);cpu_map__put (evsel->cpus); +thread_map__put (evsel->threads);zfree (&evsel->group_name);zfree (&evsel->name); perf_evsel__object.fini (evsel);
tools/perf/util/evsel.h +1 -0
@@ -82,6 +82,7 @@ struct perf_evsel {struct cgroup_sel *cgrp;void *handler;struct cpu_map *cpus; +struct thread_map *threads;unsigned int sample_size;int id_pos;int is_pos;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 06/25] perf tools: Propagate thread maps through the evlist
Em Wed, Jun 10, 2015 at 08:10:39PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Propagate evlist's
thread_mapobject through all the evsel objects.It'll be handy to access evsel's threads directly
in following patches.
Handy in what way? I.e. I should know one example without having to look at future patches ;-)
- Arnaldo
Quoted 49 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/evlist.c | 4 +++- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-)tools/perf/util/evlist.c +3
-1@@ -1100,7 +1100,9 @@ static int propagate_maps(struct perf_evlist *evlist, struct target *target)if (!evsel->cpus || target->cpu_list) evsel->cpus =cpu_map__get (evlist->cpus); -if (!evsel->cpus) + evsel->threads =thread_map__get (evlist->threads); + +if (!evsel->cpus || !evsel->threads)return -ENOMEM ; }tools/perf/util/evsel.c +1
-0@@ -903,6 +903,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)perf_evsel__free_id (evsel);close_cgroup (evsel->cgrp);cpu_map__put (evsel->cpus); +thread_map__put (evsel->threads);zfree (&evsel->group_name);zfree (&evsel->name); perf_evsel__object.fini (evsel);tools/perf/util/evsel.h +1
-0@@ -82,6 +82,7 @@ struct perf_evsel {struct cgroup_sel *cgrp;void *handler;struct cpu_map *cpus; +struct thread_map *threads;unsigned int sample_size;int id_pos;int is_pos;Signature · 1 line
1.9.3
Re: [PATCH 06/25] perf tools: Propagate thread maps through the evlist
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:39PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Propagate evlist's
thread_mapobject through all the evsel objects.It'll be handy to access evsel's threads directly
in following patches.Handy in what way? I.e. I should know one example without having to look at future patches ;-)
there's no link to evlist which hold threads map now, and it's not always available.. I'll update the changelog in v2
jirka
Namhyung Kim
maintainerRe: [PATCH 06/25] perf tools: Propagate thread maps through the evlist
Hi Jiri,
Quoted 8 lines · Jiri Olsa
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:39PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Propagate evlist's
thread_mapobject through all the evsel objects.It'll be handy to access evsel's threads directly
in following patches.
Quoted 6 lines
Quoted 2 lines
Handy in what way? I.e. I should know one example without having to look at future patches ;-)
there's no link to evlist which hold threads map now, and it's not always available.. I'll update the changelog in v2
What about adding a link to evlist in evsel then?
Thanks,
Namhyung
Re: [PATCH 06/25] perf tools: Propagate thread maps through the evlist
Quoted 11 lines · Namhyung Kim
Hi Jiri,
Quoted 8 lines · Jiri Olsa
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:39PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Propagate evlist's
thread_mapobject through all the evsel objects.It'll be handy to access evsel's threads directly
in following patches.
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
Handy in what way? I.e. I should know one example without having to look at future patches ;-)
there's no link to evlist which hold threads map now, and it's not always available.. I'll update the changelog in v2
What about adding a link to evlist in evsel then?
I guess thats possiuble, but we already have it for cpu map in evsel, so I wanted to stay consistent with thread map.. and it's just pointer with extra refcnt increased
jirka
Jiri Olsa
reviewerPATCH 7/25 perf tools: Make perf_evsel__(nr_)cpus generic
In reply to Jiri OlsaBecause we now propagate all evlist's cpu_maps and thread_map objects through all evsels, the perf_evsel__(nr_)cpus no longer need to be specific to stat object and check evlist and target objects.
--- tools/perf/builtin-stat.c | 10 ---------- tools/perf/util/evsel.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-)
tools/perf/builtin-stat.c +0 -10
@@ -141,16 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static inline struct cpu_map *perf_evsel__cpus (struct perf_evsel *evsel) -{ -return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; -} - -static inline int perf_evsel__nr_cpus (struct perf_evsel *evsel) -{ -return perf_evsel__cpus (evsel)->nr; -} -static void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) {int i;
tools/perf/util/evsel.h +11 -0
@@ -8,6 +8,7 @@#include <linux/types.h> #include "xyarray.h" #include "symbol.h" +#include "cpumap.h" struct perf_counts_values { union {
@@ -114,6 +115,16 @@ struct thread_map;struct perf_evlist ;struct record_opts ; +static inline struct cpu_map *perf_evsel__cpus (struct perf_evsel *evsel) +{ +return evsel->cpus; +} + +static inline int perf_evsel__nr_cpus (struct perf_evsel *evsel) +{ +return perf_evsel__cpus (evsel)->nr; +} +void perf_counts_values__scale (struct perf_counts_values *count,bool scale,s8 *pscaled);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 8/25 perf stat: Introduce perf_counts__(alloc|free|reset) functions
In reply to Jiri OlsaMove 'struct perf_counts' allocation|free|reset code into separate functions.
--- tools/perf/builtin-stat.c | 19 +++++++------------ tools/perf/util/evsel.c | 28 +++++++++++++++++++++++----- tools/perf/util/evsel.h | 3 +++ 3 files changed, 33 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +7 -12
@@ -168,24 +168,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel) { -void *addr; -size_t sz; +struct perf_counts *counts; - sz =sizeof (*evsel->counts) + - (perf_evsel__nr_cpus (evsel) *sizeof (struct perf_counts_values )); + counts =perf_counts__alloc (perf_evsel__nr_cpus (evsel)); +if (counts) + evsel->prev_raw_counts = counts; - addr =zalloc (sz); -if (!addr) -return -ENOMEM ; - - evsel->prev_raw_counts = addr; - -return 0 ; +return counts ?0 : -ENOMEM ; }static void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel) { -zfree (&evsel->prev_raw_counts); +perf_counts__free (evsel->prev_raw_counts); + evsel->prev_raw_counts =NULL ; }static void perf_evlist__free_stats (struct perf_evlist *evlist)
tools/perf/util/evsel.c +23 -5
@@ -851,16 +851,33 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } +struct perf_counts *perf_counts__alloc (int ncpus) +{ +int size =sizeof (struct perf_counts ) + + ncpus *sizeof (struct perf_counts_values ); + +return zalloc (size); +} + +void perf_counts__free (struct perf_counts *counts) +{ +free (counts); +} + +static void perf_counts__reset (struct perf_counts *counts,int ncpus) +{ +memset (counts,0 , (sizeof (*counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) { -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); +perf_counts__reset (evsel->counts, ncpus); }int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) { - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); + evsel->counts =perf_counts__alloc (ncpus);return evsel->counts !=NULL ?0 : -ENOMEM ; }
@@ -893,7 +910,8 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)void perf_evsel__free_counts (struct perf_evsel *evsel) { -zfree (&evsel->counts); +perf_counts__free (evsel->counts); + evsel->counts =NULL ; }void perf_evsel__exit (struct perf_evsel *evsel)
tools/perf/util/evsel.h +3 -0
@@ -131,6 +131,9 @@ void perf_counts_values__scale(struct perf_counts_values *count,void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu,struct perf_counts_values *count); +struct perf_counts *perf_counts__alloc (int ncpus); +void perf_counts__free (struct perf_counts *counts); +int perf_evsel__object_config (size_t object_size,int (*init)(struct perf_evsel *evsel),void (*fini)(struct perf_evsel *evsel));
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 08/25] perf stat: Introduce perf_counts__(alloc|free|reset) functions
Em Wed, Jun 10, 2015 at 08:10:41PM +0200, Jiri Olsa escreveu:
Quoted 10 lines
Move 'struct
perf_counts' allocation|free|reset code into separate functions.Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/builtin-stat.c | 19 +++++++------------ tools/perf/util/evsel.c | 28 +++++++++++++++++++++++----- tools/perf/util/evsel.h | 3 +++ 3 files changed, 33 insertions(+), 17 deletions(-)
But please do not move it to 'evsel.[ch]', i.e. you're introducing a new class, i.e. "perf_counts", you might as well put them in a separate file, i.e. tools/perf/util/counts.[ch].
And please rename perf_counts__alloc() to perf_counds__new(), ditto for __free() -> __delete(),
Quoted 104 lines
tools/perf/builtin-stat.c +7
-12@@ -168,24 +168,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)static int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel) { -void *addr; -size_t sz; +struct perf_counts *counts; - sz =sizeof (*evsel->counts) + - (perf_evsel__nr_cpus (evsel) *sizeof (struct perf_counts_values )); + counts =perf_counts__alloc (perf_evsel__nr_cpus (evsel)); +if (counts) + evsel->prev_raw_counts = counts; - addr =zalloc (sz); -if (!addr) -return -ENOMEM ; - - evsel->prev_raw_counts = addr; - -return 0 ; +return counts ?0 : -ENOMEM ; }static void perf_evsel__free_prev_raw_counts (struct perf_evsel *evsel) { -zfree (&evsel->prev_raw_counts); +perf_counts__free (evsel->prev_raw_counts); + evsel->prev_raw_counts =NULL ; }static void perf_evlist__free_stats (struct perf_evlist *evlist)tools/perf/util/evsel.c +23
-5@@ -851,16 +851,33 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } +struct perf_counts *perf_counts__alloc (int ncpus) +{ +int size =sizeof (struct perf_counts ) + + ncpus *sizeof (struct perf_counts_values ); + +return zalloc (size); +} + +void perf_counts__free (struct perf_counts *counts) +{ +free (counts); +} + +static void perf_counts__reset (struct perf_counts *counts,int ncpus) +{ +memset (counts,0 , (sizeof (*counts) + + (ncpus *sizeof (struct perf_counts_values )))); +} +void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus) { -memset (evsel->counts,0 , (sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); +perf_counts__reset (evsel->counts, ncpus); }int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus) { - evsel->counts =zalloc ((sizeof (*evsel->counts) + - (ncpus *sizeof (struct perf_counts_values )))); + evsel->counts =perf_counts__alloc (ncpus);return evsel->counts !=NULL ?0 : -ENOMEM ; }@@ -893,7 +910,8 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)void perf_evsel__free_counts (struct perf_evsel *evsel) { -zfree (&evsel->counts); +perf_counts__free (evsel->counts); + evsel->counts =NULL ; }void perf_evsel__exit (struct perf_evsel *evsel)tools/perf/util/evsel.h +3
-0@@ -131,6 +131,9 @@ void perf_counts_values__scale(struct perf_counts_values *count,void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu,struct perf_counts_values *count); +struct perf_counts *perf_counts__alloc (int ncpus); +void perf_counts__free (struct perf_counts *counts); +int perf_evsel__object_config (size_t object_size,int (*init)(struct perf_evsel *evsel),void (*fini)(struct perf_evsel *evsel));Signature · 1 line
1.9.3
Re: [PATCH 08/25] perf stat: Introduce perf_counts__(alloc|free|reset) functions
Quoted 12 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:41PM +0200, Jiri Olsa escreveu:
Quoted 10 lines
Move 'struct
perf_counts' allocation|free|reset code into separate functions.Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/builtin-stat.c | 19 +++++++------------ tools/perf/util/evsel.c | 28 +++++++++++++++++++++++----- tools/perf/util/evsel.h | 3 +++ 3 files changed, 33 insertions(+), 17 deletions(-)
Quoted 6 lines
But please do not move it to 'evsel.[ch]', i.e. you're introducing a new class, i.e. "
perf_counts", you might as well put them in a separate file, i.e. tools/perf/util/counts.[ch].And please rename
perf_counts__alloc()toperf_counds__new(), ditto for__free()->__delete(),
ok
jirka
Jiri Olsa
reviewerPATCH 9/25 perf stat: Introduce perf_counts function
In reply to Jiri OlsaIntroducing perf_counts function, that returns 'struct perf_counts_values' pointer for given cpu.
--- 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 | 6 ++++++ 5 files changed, 19 insertions(+), 13 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 ;
@@ -802,9 +802,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)
@@ -912,9 +912,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
@@ -97,9 +97,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
@@ -945,8 +945,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;
@@ -1007,7 +1007,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 +6 -0
@@ -134,6 +134,12 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,struct perf_counts *perf_counts__alloc (int ncpus);void perf_counts__free (struct perf_counts *counts); +static inline struct perf_counts_values * +perf_counts (struct perf_counts *counts,int cpu) +{ +return &counts->cpu[cpu]; +} +int perf_evsel__object_config (size_t object_size,int (*init)(struct perf_evsel *evsel),void (*fini)(struct perf_evsel *evsel));
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 10/25 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/evsel.c | 31 ++++++++++++++++++++++--------- tools/perf/util/evsel.h | 6 +++--- 4 files changed, 27 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/evsel.c +22 -9
@@ -853,26 +853,39 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)struct perf_counts *perf_counts__alloc (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__free (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__zero (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/evsel.h +3 -3
@@ -24,7 +24,7 @@ struct perf_counts_values {struct perf_counts {s8 scaled;struct perf_counts_values aggr; -struct perf_counts_values cpu[]; +struct xyarray *cpu; };struct perf_evsel ;
@@ -137,7 +137,7 @@ void perf_counts__free(struct perf_counts *counts);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 ); } int perf_evsel__object_config(size_t object_size,
@@ -192,7 +192,7 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); +void perf_evsel__reset_counts (struct perf_evsel *evsel);void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 11/25 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 | 20 +++++++++---------- tools/perf/util/evsel.h | 10 +++++----- 5 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__alloc (perf_evsel__nr_cpus (evsel)); + counts =perf_counts__alloc (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++)
@@ -802,9 +806,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)
@@ -912,9 +916,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
@@ -77,7 +77,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; }
@@ -97,9 +97,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 +10 -10
@@ -851,14 +851,14 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } -struct perf_counts *perf_counts__alloc (int ncpus) +struct perf_counts *perf_counts__alloc (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 ;
@@ -888,9 +888,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__alloc (ncpus); + evsel->counts =perf_counts__alloc (ncpus, nthreads);return evsel->counts !=NULL ?0 : -ENOMEM ; }
@@ -946,7 +946,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;
@@ -958,8 +958,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;
@@ -1012,15 +1012,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 +5 -5
@@ -128,16 +128,16 @@ 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); -struct perf_counts *perf_counts__alloc (int ncpus); +struct perf_counts *perf_counts__alloc (int ncpus,int nthreads);void perf_counts__free (struct perf_counts *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); } int perf_evsel__object_config(size_t object_size,
@@ -191,7 +191,7 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);int perf_evsel__group_desc (struct perf_evsel *evsel,char *buf,size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads); -int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus); +int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus,int nthreads);void perf_evsel__reset_counts (struct perf_evsel *evsel);void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 12/25 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/evsel.c | 12 ++++++------ tools/perf/util/evsel.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/util/evsel.c +6 -6
@@ -856,15 +856,15 @@ struct perf_counts *perf_counts__alloc(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;
@@ -873,14 +873,14 @@ struct perf_counts *perf_counts__alloc(int ncpus, int nthreads)void perf_counts__free (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__zero (counts->cpu); +xyarray__zero (counts->values); }void perf_evsel__reset_counts (struct perf_evsel *evsel)
tools/perf/util/evsel.h +2 -2
@@ -24,7 +24,7 @@ struct perf_counts_values {struct perf_counts {s8 scaled;struct perf_counts_values aggr; -struct xyarray *cpu; +struct xyarray *values; };struct perf_evsel ;
@@ -137,7 +137,7 @@ void perf_counts__free(struct perf_counts *counts);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); } int perf_evsel__object_config(size_t object_size,
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 13/25 perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into evsel object
In reply to Jiri OlsaMoving perf_evsel__(alloc|free|reset)_stat_priv into evsel object, so it could be used outside stat object in following patches.
--- tools/perf/builtin-stat.c | 25 ------------------------- tools/perf/util/evsel.c | 26 ++++++++++++++++++++++++++ tools/perf/util/evsel.h | 5 +++++ 3 files changed, 31 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/evsel.c +26 -0
@@ -26,6 +26,7 @@#include "perf_regs.h" #include "debug.h" #include "trace-event.h" +#include "stat.h" static struct { bool sample_id_all;
@@ -851,6 +852,31 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } +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); +} +struct perf_counts *perf_counts__alloc (int ncpus,int nthreads) {struct perf_counts *counts =zalloc (sizeof (*counts));
tools/perf/util/evsel.h +5 -0
@@ -192,6 +192,11 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus,int nthreads); + +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); +void perf_evsel__reset_counts (struct perf_evsel *evsel);void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 13/25] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into evsel object
Em Wed, Jun 10, 2015 at 08:10:46PM +0200, Jiri Olsa escreveu:
Quoted 5 lines
Moving perf_evsel__(alloc|free|reset)_stat_priv into evsel object, so it could be used outside stat object in following patches.
+++
b/tools/perf/util/evsel.c
tools/perf/util/evsel.c int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) · line 864
Quoted 10 lines
tools/perf/util/evsel.c +10
-0+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); +}
Please move this to some 'stat' specific place, so that evsel.c has nothing that is tool specific, like references to 'struct perf_stat'.
- Arnaldo
Quoted 35 lines
tools/perf/util/evsel.c +14
-0+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); +} +struct perf_counts *perf_counts__alloc (int ncpus,int nthreads) {struct perf_counts *counts =zalloc (sizeof (*counts));tools/perf/util/evsel.h +5
-0@@ -192,6 +192,11 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus,int nthreads); + +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); +void perf_evsel__reset_counts (struct perf_evsel *evsel);void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads);Signature · 1 line
1.9.3
Re: [PATCH 13/25] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into evsel object
Quoted 6 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:46PM +0200, Jiri Olsa escreveu:
Quoted 4 lines
Moving perf_evsel__(alloc|free|reset)_stat_priv into evsel object, so it could be used outside stat object in following patches.
+++
b/tools/perf/util/evsel.c
Quoted 13 lines
tools/perf/util/evsel.c int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) · line 864
Quoted 10 lines
tools/perf/util/evsel.c +10
-0+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); +}Please move this to some 'stat' specific place, so that
evsel.chas nothing that is tool specific, like references to 'structperf_stat'.
ok, util/stat.c then
jirka
Jiri Olsa
reviewerPATCH 14/25 perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into evsel object
In reply to Jiri OlsaMoving perf_evsel__(alloc|free)_prev_raw_counts into evsel object, so it could be used in following patches.
--- tools/perf/builtin-stat.c | 18 ------------------ tools/perf/util/evsel.c | 18 ++++++++++++++++++ tools/perf/util/evsel.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__alloc (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__free (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/evsel.c +18 -0
@@ -852,6 +852,24 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)return 0 ; } +int perf_evsel__alloc_prev_raw_counts (struct perf_evsel *evsel, +int ncpus,int nthreads) +{ +struct perf_counts *counts; + + counts =perf_counts__alloc (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__free (evsel->prev_raw_counts); + evsel->prev_raw_counts =NULL ; +} +void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) {int i;
tools/perf/util/evsel.h +4 -0
@@ -193,6 +193,10 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus,int nthreads); +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); +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);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 15/25 perf stat: Move perf_evlist__(alloc|free)_stats into evlist object
In reply to Jiri OlsaMoving perf_evlist__(alloc|free)_stats into evsel object, so it could be used in following patches.
--- tools/perf/builtin-stat.c | 32 -------------------------------- tools/perf/util/evlist.c | 32 ++++++++++++++++++++++++++++++++ tools/perf/util/evlist.h | 2 ++ 3 files changed, 34 insertions(+), 32 deletions(-)
tools/perf/builtin-stat.c +0 -32
@@ -141,38 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static void perf_evlist__free_stats (struct perf_evlist *evlist) -{ -struct perf_evsel *evsel; - -evlist__for_each (evlist, evsel) { -perf_evsel__free_stat_priv (evsel); -perf_evsel__free_counts (evsel); -perf_evsel__free_prev_raw_counts (evsel); - } -} - -static int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) -{ -struct perf_evsel *evsel; -int nthreads =thread_map__nr (evsel_list->threads); - -evlist__for_each (evlist, evsel) { -int ncpus =perf_evsel__nr_cpus (evsel); - -if (perf_evsel__alloc_stat_priv (evsel) <0 || -perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || - (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) - goto out_free; - } - -return 0 ; - -out_free: -perf_evlist__free_stats (evlist); -return -1 ; -} -static void perf_stat__reset_stats (struct perf_evlist *evlist) {struct perf_evsel *evsel;
tools/perf/util/evlist.c +32 -0
@@ -1651,3 +1651,35 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist, tracking_evsel->tracking = true; } + +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) +{ +struct perf_evsel *evsel; +int nthreads =thread_map__nr (evlist->threads); + +evlist__for_each (evlist, evsel) { +int ncpus =perf_evsel__nr_cpus (evsel); + +if (perf_evsel__alloc_stat_priv (evsel) <0 || +perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || + (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) + goto out_free; + } + +return 0 ; + +out_free: +perf_evlist__free_stats (evlist); +return -1 ; +} + +void perf_evlist__free_stats (struct perf_evlist *evlist) +{ +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +perf_evsel__free_stat_priv (evsel); +perf_evsel__free_counts (evsel); +perf_evsel__free_prev_raw_counts (evsel); + } +}
tools/perf/util/evlist.h +2 -0
@@ -288,4 +288,6 @@ void perf_evlist__to_front(struct perf_evlist *evlist,void perf_evlist__set_tracking_event (struct perf_evlist *evlist,struct perf_evsel *tracking_evsel); +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw); +void perf_evlist__free_stats (struct perf_evlist *evlist);#endif /* __PERF_EVLIST_H */
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 15/25] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object
Em Wed, Jun 10, 2015 at 08:10:48PM +0200, Jiri Olsa escreveu:
Quoted 2 lines
Moving perf_evlist__(alloc|free)_stats into evsel object, so it could be used in following patches.
Can this go into the new counts.[ch] file too? As it is specific to counting tools?
- Arnaldo
Quoted 104 lines
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/builtin-stat.c | 32 -------------------------------- tools/perf/util/evlist.c | 32 ++++++++++++++++++++++++++++++++ tools/perf/util/evlist.h | 2 ++ 3 files changed, 34 insertions(+), 32 deletions(-)tools/perf/builtin-stat.c +0
-32@@ -141,38 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static void perf_evlist__free_stats (struct perf_evlist *evlist) -{ -struct perf_evsel *evsel; - -evlist__for_each (evlist, evsel) { -perf_evsel__free_stat_priv (evsel); -perf_evsel__free_counts (evsel); -perf_evsel__free_prev_raw_counts (evsel); - } -} - -static int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) -{ -struct perf_evsel *evsel; -int nthreads =thread_map__nr (evsel_list->threads); - -evlist__for_each (evlist, evsel) { -int ncpus =perf_evsel__nr_cpus (evsel); - -if (perf_evsel__alloc_stat_priv (evsel) <0 || -perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || - (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) - goto out_free; - } - -return 0 ; - -out_free: -perf_evlist__free_stats (evlist); -return -1 ; -} -static void perf_stat__reset_stats (struct perf_evlist *evlist) {struct perf_evsel *evsel;tools/perf/util/evlist.c +32
-0@@ -1651,3 +1651,35 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist, tracking_evsel->tracking = true; } + +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw) +{ +struct perf_evsel *evsel; +int nthreads =thread_map__nr (evlist->threads); + +evlist__for_each (evlist, evsel) { +int ncpus =perf_evsel__nr_cpus (evsel); + +if (perf_evsel__alloc_stat_priv (evsel) <0 || +perf_evsel__alloc_counts (evsel, ncpus, nthreads) <0 || + (alloc_raw &&perf_evsel__alloc_prev_raw_counts (evsel, ncpus, nthreads) <0 )) + goto out_free; + } + +return 0 ; + +out_free: +perf_evlist__free_stats (evlist); +return -1 ; +} + +void perf_evlist__free_stats (struct perf_evlist *evlist) +{ +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +perf_evsel__free_stat_priv (evsel); +perf_evsel__free_counts (evsel); +perf_evsel__free_prev_raw_counts (evsel); + } +}tools/perf/util/evlist.h +2
-0@@ -288,4 +288,6 @@ void perf_evlist__to_front(struct perf_evlist *evlist,void perf_evlist__set_tracking_event (struct perf_evlist *evlist,struct perf_evsel *tracking_evsel); +int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw); +void perf_evlist__free_stats (struct perf_evlist *evlist);#endif /* __PERF_EVLIST_H */ Signature · 1 line
1.9.3
Re: [PATCH 15/25] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object
Quoted 6 lines · Arnaldo Carvalho de Melo
Em Wed, Jun 10, 2015 at 08:10:48PM +0200, Jiri Olsa escreveu:
Quoted 2 lines
Moving perf_evlist__(alloc|free)_stats into evsel object, so it could be used in following patches.
Can this go into the new counts.[ch] file too? As it is specific to counting tools?
ook
jirka
Jiri Olsa
reviewerPATCH 16/25 perf stat: Introduce perf_evsel__alloc_stats function
In reply to Jiri OlsaMove all stat allocation logic related to evsel
object under single function. This way we can
use it separately for evsel object out of evlist
object.
--- tools/perf/util/evlist.c | 7 +------ tools/perf/util/evsel.c | 13 +++++++++++++ tools/perf/util/evsel.h | 2 ++ 3 files changed, 16 insertions(+), 6 deletions(-)
tools/perf/util/evlist.c +1 -6
@@ -1655,14 +1655,9 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,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/evsel.c +13 -0
@@ -938,6 +938,19 @@ int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)return evsel->counts !=NULL ?0 : -ENOMEM ; } +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 ; +} +static void perf_evsel__free_fd (struct perf_evsel *evsel) {xyarray__delete (evsel->fd);
tools/perf/util/evsel.h +2 -0
@@ -201,6 +201,8 @@ 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_stats (struct perf_evsel *evsel,bool alloc_raw); +void perf_evsel__reset_counts (struct perf_evsel *evsel);void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 17/25 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
@@ -1060,6 +1060,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
@@ -275,6 +275,9 @@ typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel,int perf_evsel__read_cb (struct perf_evsel *evsel,int cpu,int thread,perf_evsel__read_cb_t cb); +int perf_evsel__read (struct perf_evsel *evsel,int cpu,int thread, +struct perf_counts_values *count); +int __perf_evsel__read_on_cpu (struct perf_evsel *evsel,int cpu,int thread,bool scale);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 18/25 perf stat: Introduce read_counters function
In reply to Jiri OlsaMoving read counters logic into single read_counters function, which will be called for both interval and overall processing legs.
The reason is to split reading and processing (following patches) counters code, so we could read counters from other sources (like perf.data) and process them in the same way as 'perf stat' command does.
--- tools/perf/builtin-stat.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-)
tools/perf/builtin-stat.c +22 -25
@@ -329,27 +329,35 @@ static int read_counter(struct perf_evsel *counter)return 0 ; } -static void print_interval (void ) +static void read_counters (bool close) { -static int num_print_interval;struct perf_evsel *counter;struct perf_stat *ps; -struct timespec ts, rs; -char prefix[64 ]; -if (aggr_mode ==AGGR_GLOBAL ) { -evlist__for_each (evsel_list, counter) { - ps = counter->priv; -memset (ps->res_stats,0 ,sizeof (ps->res_stats)); +evlist__for_each (evsel_list, counter) { + ps = counter->priv; +memset (ps->res_stats,0 ,sizeof (ps->res_stats)); + +if (aggr_mode ==AGGR_GLOBAL )read_counter_aggr (counter); - } - }else { -evlist__for_each (evsel_list, counter) { - ps = counter->priv; -memset (ps->res_stats,0 ,sizeof (ps->res_stats)); +else read_counter (counter); + +if (close) { +perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter), +thread_map__nr (evsel_list->threads)); } } +} + +static void print_interval (void ) +{ +static int num_print_interval; +struct perf_evsel *counter; +struct timespec ts, rs; +char prefix[64 ]; + +read_counters (false);clock_gettime (CLOCK_MONOTONIC , &ts);diff_timespec (&rs, &ts, &ref_time);
@@ -528,18 +536,7 @@ static int __run_perf_stat(int argc, const char **argv)update_stats (&walltime_nsecs_stats, t1 - t0); -if (aggr_mode ==AGGR_GLOBAL ) { -evlist__for_each (evsel_list, counter) { -read_counter_aggr (counter); -perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter), -thread_map__nr (evsel_list->threads)); - } - }else { -evlist__for_each (evsel_list, counter) { -read_counter (counter); -perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter),1 ); - } - } +read_counters (true);return WEXITSTATUS (status); }
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 19/25 perf stat: Separate counters reading and processing
In reply to Jiri OlsaSeparating counters reading and processing so we could use the processing part in following patches.
Using simple reading via perf_evsel__read function to read counters now, because part of the processing was in the read_cb callback.
--- tools/perf/builtin-stat.c | 56 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +39 -17
@@ -223,8 +223,9 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)return 0 ; } -static int read_cb (struct perf_evsel *evsel,int cpu,int thread, -struct perf_counts_values *count) +static int +process_counter_values (struct perf_evsel *evsel,int cpu,int thread, +struct perf_counts_values *count) {struct perf_counts_values *aggr = &evsel->counts->aggr;static struct perf_counts_values zero;
@@ -245,7 +246,6 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread,if (!evsel->snapshot)perf_evsel__compute_deltas (evsel, cpu, thread, count);perf_counts_values__scale (count, scale,NULL ); - *perf_counts (evsel->counts, cpu, thread) = *count;if (aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->values, cpu);break ;
@@ -262,23 +262,41 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread,return 0 ; } -static int read_counter (struct perf_evsel *counter); +static int process_counter_maps (struct perf_evsel *counter) +{ +int nthreads =thread_map__nr (counter->threads); +int ncpus =perf_evsel__nr_cpus (counter); +int cpu, thread; -/* -* Read out the results of a single counter: -* aggregate counts across CPUs in system-wide mode -*/ -static int read_counter_aggr (struct perf_evsel *counter) +if (counter->system_wide) + nthreads =1 ; + +for (thread =0 ; thread < nthreads; thread++) { +for (cpu =0 ; cpu < ncpus; cpu++) { +if (process_counter_values (counter, cpu, thread, +perf_counts (counter->counts, cpu, thread))) +return -1 ; + } + } + +return 0 ; +} + +static int process_counter (struct perf_evsel *counter) {struct perf_counts_values *aggr = &counter->counts->aggr;struct perf_stat *ps = counter->priv;u64 *count = counter->counts->aggr.values; -int i; +int i, ret; aggr->val = aggr->ena = aggr->run =0 ; -if (read_counter (counter)) -return -1 ; + ret =process_counter_maps (counter); +if (ret) +return ret; + +if (aggr_mode !=AGGR_GLOBAL ) +return 0 ;if (!counter->snapshot)perf_evsel__compute_deltas (counter,-1 ,-1 , aggr);
@@ -321,7 +339,10 @@ static int read_counter(struct perf_evsel *counter)for (thread =0 ; thread < nthreads; thread++) {for (cpu =0 ; cpu < ncpus; cpu++) { -if (perf_evsel__read_cb (counter, cpu, thread, read_cb)) +struct perf_counts_values *count; + + count =perf_counts (counter->counts, cpu, thread); +if (perf_evsel__read (counter, cpu, thread, count))return -1 ; } }
@@ -338,10 +359,11 @@ static void read_counters(bool close) ps = counter->priv;memset (ps->res_stats,0 ,sizeof (ps->res_stats)); -if (aggr_mode ==AGGR_GLOBAL ) -read_counter_aggr (counter); -else -read_counter (counter); +if (read_counter (counter)) +pr_warning ("failed to read counter %s\n" , counter->name); + +if (process_counter (counter)) +pr_warning ("failed to process counter %s\n" , counter->name);if (close) { perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 20/25 perf stat: Move zero_per_pkg into counter process code
In reply to Jiri OlsaMoving zero_per_pkg into counter process code.
--- tools/perf/builtin-stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/builtin-stat.c +3 -3
@@ -291,6 +291,9 @@ static int process_counter(struct perf_evsel *counter) aggr->val = aggr->ena = aggr->run =0 ; +if (counter->per_pkg) +zero_per_pkg (counter); + ret =process_counter_maps (counter);if (ret)return ret;
@@ -334,9 +337,6 @@ static int read_counter(struct perf_evsel *counter)if (counter->system_wide) nthreads =1 ; -if (counter->per_pkg) -zero_per_pkg (counter); -for (thread =0 ; thread < nthreads; thread++) {for (cpu =0 ; cpu < ncpus; cpu++) {struct perf_counts_values *count;
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 21/25 perf stat: Move perf_stat initialization counter process code
In reply to Jiri OlsaMoving perf_stat initialization counter process code.
--- tools/perf/builtin-stat.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
tools/perf/builtin-stat.c +1 -4
@@ -290,6 +290,7 @@ static int process_counter(struct perf_evsel *counter)int i, ret; aggr->val = aggr->ena = aggr->run =0 ; +memset (ps->res_stats,0 ,sizeof (ps->res_stats));if (counter->per_pkg)zero_per_pkg (counter);
@@ -353,12 +354,8 @@ static int read_counter(struct perf_evsel *counter)static void read_counters (bool close) {struct perf_evsel *counter; -struct perf_stat *ps;evlist__for_each (evsel_list, counter) { - ps = counter->priv; -memset (ps->res_stats,0 ,sizeof (ps->res_stats)); -if (read_counter (counter))pr_warning ("failed to read counter %s\n" , counter->name);
Signature · 1 line
1.9.3
Re: [PATCH 21/25] perf stat: Move perf_stat initialization counter process code
tools/perf/builtin-stat.c static int process_counter(struct perf_evsel *counter) · line 294
Quoted 10 lines · Jiri Olsa
tools/perf/builtin-stat.c +1
-0@@ -290,6 +290,7 @@ static int process_counter(struct perf_evsel *counter)int i, ret; aggr->val = aggr->ena = aggr->run =0 ; +memset (ps->res_stats,0 ,sizeof (ps->res_stats));
init_stats()?
Re: [PATCH 21/25] perf stat: Move perf_stat initialization counter process code
Quoted 8 lines · David Ahern
Quoted 7 lines · Jiri Olsa
tools/perf/builtin-stat.c +0
-0@@ -290,6 +290,7 @@ static int process_counter(struct perf_evsel *counter)int i, ret;
Quoted 6 lines
tools/perf/builtin-stat.c static int process_counter(struct perf_evsel *counter) · line 294
Quoted 3 lines
tools/perf/builtin-stat.c +1
-0aggr->val = aggr->ena = aggr->run =0 ; +memset (ps->res_stats,0 ,sizeof (ps->res_stats));
init_stats()?
right, thanks
jirka
Quoted 3 lines · Jiri Olsa
hi,
adding the possibility to display stat data per thread. Allowing following commands and output:
available in here:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/per_task
jirka
Quoted 91 lines
$ perf stat -e cycles,instructions --per-task -p 12451,16173 ^C Performance counter stats for process id '12451,16173':TASK-12451 77,784 cycles TASK-16173 64,809 cycles TASK-12451 14,432 instructions TASK-16173 14,452 instructions3.854957122 seconds time elapsedAlso woks under interval mode:
$ ./perf stat -e cycles,instructions --per-task -p 16431,16173 -I 1000 # time task counts unit events 1.000085816 TASK-16173 0 cycles 1.000085816 TASK-16431 3,358,360,926 cycles 1.000085816 TASK-16173 0 instructions 1.000085816 TASK-16431 9,062,422,086 instructions 2.000212262 TASK-16173 65,386 cycles 2.000212262 TASK-16431 3,349,355,309 cycles 2.000212262 TASK-16173 12,151 instructions 2.000212262 TASK-16431 9,039,401,422 instructions 3.000333402 TASK-16173 62,797 cycles 3.000333402 TASK-16431 3,357,140,183 cycles 3.000333402 TASK-16173 12,208 instructions 3.000333402 TASK-16431 9,058,080,762 instructions ^C 3.375949851 TASK-16173 0 cycles 3.375949851 TASK-16431 1,264,764,804 cycles 3.375949851 TASK-16173 0 instructions 3.375949851 TASK-16431 3,414,532,317 instructionsthanks for comments,
jirka---
Jiri Olsa (25):
perf tools: Fix python code with missing stat dependency
perf tools: Introducexyarray__zerofunction
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 stat: Introduceperf_counts__(alloc|free|reset)functions 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: Move perf_evsel__(alloc|free|reset)_stat_priv into evsel object perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into evsel object perf stat: Move perf_evlist__(alloc|free)_stats into evlist 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: Introduceprint_countersfunction
perf stat: Introduce --per-task optiontools/perf/builtin-stat.c | 388 +++++++++++++++++++++++++++++-------------------------------- 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.c | 6 +- tools/perf/tests/switch-tracking.c | 4 +- tools/perf/util/cpumap.c | 24 +++- tools/perf/util/cpumap.h | 5 +- tools/perf/util/evlist.c | 61 +++++++++- tools/perf/util/evlist.h | 2 + tools/perf/util/evsel.c | 128 ++++++++++++++++---- tools/perf/util/evsel.h | 48 ++++++-- 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.h | 1 + tools/perf/util/svghelper.c | 2 +- tools/perf/util/thread_map.c | 28 ++++- tools/perf/util/thread_map.h | 6 +- tools/perf/util/xyarray.c | 8 ++ tools/perf/util/xyarray.h | 2 + 25 files changed, 484 insertions(+), 267 deletions(-)
Jiri Olsa
reviewerPATCH 22/25 perf stat: Remove perf_evsel__read_cb function
In reply to Jiri OlsaIt's no longer used, the stat command usesperf_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
@@ -1044,22 +1044,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
@@ -268,13 +268,6 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, (a)->attr.type == (b)->attr.type && \ (a)->attr.config == (b)->attr.config) -typedef int (perf_evsel__read_cb_t )(struct perf_evsel *evsel, -int cpu,int thread, -struct perf_counts_values *count); - -int perf_evsel__read_cb (struct perf_evsel *evsel,int cpu,int thread, -perf_evsel__read_cb_t cb); -int perf_evsel__read (struct perf_evsel *evsel,int cpu,int thread,struct perf_counts_values *count);
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 23/25 perf stat: Rename print_interval to process_interval
In reply to Jiri OlsaIt suits better, because the function also reads counter's data.
Also the 'print_interval' name will be used in following generalization of counters display.
--- tools/perf/builtin-stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/builtin-stat.c +3 -3
@@ -369,7 +369,7 @@ static void read_counters(bool close) } } -static void print_interval (void ) +static void process_interval (void ) {static int num_print_interval;struct perf_evsel *counter;
@@ -529,7 +529,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);
@@ -547,7 +547,7 @@ static int __run_perf_stat(int argc, const char **argv)while (!done) {nanosleep (&ts,NULL );if (interval) -print_interval (); +process_interval (); } }
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 24/25 perf stat: Introduce print_counters function
In reply to Jiri OlsaCentralize counters print code into singleprint_counters function.
--- tools/perf/builtin-stat.c | 127 +++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 63 deletions(-)
tools/perf/builtin-stat.c +64 -63
@@ -67,10 +67,7 @@#define CNTR_NOT_SUPPORTED "<not supported>"#define CNTR_NOT_COUNTED "<not counted>" -static void print_stat (int argc,const char **argv); -static void print_counter_aggr (struct perf_evsel *counter,char *prefix); -static void print_counter (struct perf_evsel *counter,char *prefix); -static void print_aggr (char *prefix); +static void print_counters (struct timespec *ts,int argc,const char **argv);/* Default events used for perf stat -T */ static const char *transaction_attrs = {
@@ -371,53 +368,14 @@ static void read_counters(bool close)static void process_interval (void ) { -static int num_print_interval; -struct perf_evsel *counter;struct timespec ts, rs; -char prefix[64 ];read_counters (false);clock_gettime (CLOCK_MONOTONIC , &ts);diff_timespec (&rs, &ts, &ref_time); -sprintf (prefix,"%6lu.%09lu%s" , rs.tv_sec, rs.tv_nsec, csv_sep); - -if (num_print_interval ==0 && !csv_output) { -switch (aggr_mode) { -case AGGR_SOCKET : -fprintf (output,"# time socket cpus counts %*s events\n" , unit_width,"unit" ); -break ; -case AGGR_CORE : -fprintf (output,"# time core cpus counts %*s events\n" , unit_width,"unit" ); -break ; -case AGGR_NONE : -fprintf (output,"# time CPU counts %*s events\n" , unit_width,"unit" ); -break ; -case AGGR_GLOBAL : -default : -fprintf (output,"# time counts %*s events\n" , unit_width,"unit" ); - } - } - -if (++num_print_interval ==25 ) - num_print_interval =0 ; -switch (aggr_mode) { -case AGGR_CORE : -case AGGR_SOCKET : -print_aggr (prefix); -break ; -case AGGR_NONE : -evlist__for_each (evsel_list, counter) -print_counter (counter, prefix); -break ; -case AGGR_GLOBAL : -default : -evlist__for_each (evsel_list, counter) -print_counter_aggr (counter, prefix); - } - -fflush (output); +print_counters (&rs,0 ,NULL ); }static void handle_initial_delay (void )
@@ -904,9 +862,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);
@@ -932,36 +916,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 ;
@@ -1410,13 +1411,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) status =run_perf_stat (argc, argv);if (forever && status !=-1 ) { -print_stat (argc, argv); +print_counters (NULL , argc, argv);perf_stat__reset_stats (evsel_list); } }if (!forever && status !=-1 && !interval) -print_stat (argc, argv); +print_counters (NULL , argc, argv);perf_evlist__free_stats (evsel_list); out:
Signature · 1 line
1.9.3
Jiri Olsa
reviewerPATCH 25/25 perf stat: Introduce --per-task option
In reply to Jiri OlsaCurrently all the -p option PID arguments tasks values get aggregated and printed as single values.
Adding --per-tasks option to print values per task.
$ perf stat -e cycles,instructions --per-task -p 12451,16173 ^C Performance counter stats for process id '12451,16173':
TASK-12451 77,784 cycles TASK-16173 64,809 cycles TASK-12451 14,432 instructions TASK-16173 14,452 instructions
3.854957122 seconds time elapsed
Also woks under interval mode:
$ ./perf stat -e cycles,instructions --per-task -p 16431,16173 -I 1000
# time task counts unit events
1.000085816 TASK-16173 0 cycles
1.000085816 TASK-16431 3,358,360,926 cycles
1.000085816 TASK-16173 0 instructions
1.000085816 TASK-16431 9,062,422,086 instructions
2.000212262 TASK-16173 65,386 cycles
2.000212262 TASK-16431 3,349,355,309 cycles
2.000212262 TASK-16173 12,151 instructions
2.000212262 TASK-16431 9,039,401,422 instructions
3.000333402 TASK-16173 62,797 cycles
3.000333402 TASK-16431 3,357,140,183 cycles
3.000333402 TASK-16173 12,208 instructions
3.000333402 TASK-16431 9,058,080,762 instructions
^C 3.375949851 TASK-16173 0 cycles
3.375949851 TASK-16431 1,264,764,804 cycles
3.375949851 TASK-16173 0 instructions
3.375949851 TASK-16431 3,414,532,317 instructions--- tools/perf/builtin-stat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/stat.h | 1 + 2 files changed, 56 insertions(+), 2 deletions(-)
tools/perf/builtin-stat.c +55 -2
@@ -237,6 +237,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread, count = &zero;switch (aggr_mode) { +case AGGR_TASK :case AGGR_CORE :case AGGR_SOCKET :case AGGR_NONE :
@@ -605,6 +606,11 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_output ?0 :-4 , perf_evsel__cpus(evsel)->map[id], csv_sep);break ; +case AGGR_TASK : +fprintf (output,"TASK-%*d%s" , + csv_output ?0 :-8 , + evsel->threads->map[id], csv_sep); +break ;case AGGR_GLOBAL :default :break ;
@@ -753,6 +759,40 @@ static void print_aggr(char *prefix) } } +static void print_aggr_task (struct perf_evsel *counter,char *prefix) +{ +int nthreads =thread_map__nr (counter->threads); +int ncpus =cpu_map__nr (counter->cpus); +int cpu, thread; +double uval; + +for (thread =0 ; thread < nthreads; thread++) { +u64 ena =0 , run =0 , val =0 ; + +for (cpu =0 ; cpu < ncpus; cpu++) { + val +=perf_counts (counter->counts, cpu, thread)->val; + ena +=perf_counts (counter->counts, cpu, thread)->ena; + run +=perf_counts (counter->counts, cpu, thread)->run; + } + +if (prefix) +fprintf (output,"%s" , prefix); + + uval = val * counter->scale; + +if (nsec_counter (counter)) +nsec_printout (thread,0 , counter, uval); +else +abs_printout (thread,0 , counter, uval); + +if (!csv_output) +print_noise (counter,1.0 ); + +print_running (run, ena); +fputc ('\n' , output); + } +} +/* * Print out the results of a single counter: * aggregated counts in system-wide mode
@@ -879,6 +919,9 @@ static void print_interval(char *prefix, struct timespec *ts)case AGGR_NONE :fprintf (output,"# time CPU counts %*s events\n" , unit_width,"unit" );break ; +case AGGR_TASK : +fprintf (output,"# time task counts %*s events\n" , unit_width,"unit" ); +break ;case AGGR_GLOBAL :default :fprintf (output,"# time counts %*s events\n" , unit_width,"unit" );
@@ -947,6 +990,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)case AGGR_SOCKET :print_aggr (prefix);break ; +case AGGR_TASK : +evlist__for_each (evsel_list, counter) +print_aggr_task (counter, prefix); +break ;case AGGR_GLOBAL :evlist__for_each (evsel_list, counter)print_counter_aggr (counter, prefix);
@@ -1034,6 +1081,7 @@ static int perf_stat_init_aggr_mode(void)break ;case AGGR_NONE :case AGGR_GLOBAL : +case AGGR_TASK :default :break ; }
@@ -1258,6 +1306,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "aggregate counts per processor socket", AGGR_SOCKET),OPT_SET_UINT (0 ,"per-core" , &aggr_mode,"aggregate counts per physical processor core" ,AGGR_CORE ), +OPT_SET_UINT (0 ,"per-task" , &aggr_mode, +"aggregate counts per task" ,AGGR_TASK ),OPT_UINTEGER ('D' ,"delay" , &initial_delay,"ms to wait before starting measurement after program start" ),OPT_END ()
@@ -1349,8 +1399,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) run_count =1 ; } -/* no_aggr, cgroup are for system-wide only */ -if ((aggr_mode !=AGGR_GLOBAL || nr_cgroups) && +/* +* no_aggr, cgroup are for system-wide only +* --per-task is aggregated per task, we dont mix it with cpu mode +*/ +if (((aggr_mode !=AGGR_GLOBAL && aggr_mode !=AGGR_TASK ) || nr_cgroups) && !target__has_cpu (&target)) {fprintf (stderr,"both cgroup and no-aggregation " "modes only available in system-wide mode\n" );
tools/perf/util/stat.h +1 -0
@@ -29,6 +29,7 @@ enum aggr_mode {AGGR_GLOBAL ,AGGR_SOCKET ,AGGR_CORE , + AGGR_TASK, };void update_stats (struct stats *stats,u64 val);
Signature · 1 line
1.9.3
Quoted 28 lines · Jiri Olsa
Currently all the -p option PID arguments tasks values get aggregated and printed as single values.
Adding --per-tasks option to print values per task.
$ perf stat -e cycles,instructions --per-task -p 12451,16173 ^C Performance counter stats for process id '12451,16173':TASK-12451 77,784 cycles TASK-16173 64,809 cycles TASK-12451 14,432 instructions TASK-16173 14,452 instructions3.854957122 seconds time elapsedAlso woks under interval mode:
$ ./perf stat -e cycles,instructions --per-task -p 16431,16173 -I 1000 # time task counts unit events 1.000085816 TASK-16173 0 cycles 1.000085816 TASK-16431 3,358,360,926 cycles 1.000085816 TASK-16173 0 instructions 1.000085816 TASK-16431 9,062,422,086 instructions 2.000212262 TASK-16173 65,386 cycles 2.000212262 TASK-16431 3,349,355,309 cycles 2.000212262 TASK-16173 12,151 instructions 2.000212262 TASK-16431 9,039,401,422 instructions
Quoted 9 lines
3.000333402 TASK-16173 62,797 cycles
3.000333402 TASK-16431 3,357,140,183 cycles
3.000333402 TASK-16173 12,208 instructions
3.000333402 TASK-16431 9,058,080,762 instructions
^C 3.375949851 TASK-16173 0 cycles
3.375949851 TASK-16431 1,264,764,804 cycles
3.375949851 TASK-16173 0 instructions
3.375949851 TASK-16431 3,414,532,317 instructionsWhy not print $comm-$pid versus TASK-$pid?
On Wed, Jun 10, 2015 at 12:44:34PM -0600, David Ahern wrote:
SNIP
Quoted 11 lines
Quoted 10 lines
2.000212262 TASK-16431 9,039,401,422 instructions 3.000333402 TASK-16173 62,797 cycles 3.000333402 TASK-16431 3,357,140,183 cycles 3.000333402 TASK-16173 12,208 instructions 3.000333402 TASK-16431 9,058,080,762 instructions ^C 3.375949851 TASK-16173 0 cycles 3.375949851 TASK-16431 1,264,764,804 cycles 3.375949851 TASK-16173 0 instructions 3.375949851 TASK-16431 3,414,532,317 instructions
Quoted 2 lines
Why not print $comm-$pid versus TASK-$pid?
yep, good idea
jirka
Arnaldo Carvalho de Melo
maintainerEm Wed, Jun 10, 2015 at 12:44:34PM -0600, David Ahern escreveu:
Quoted 11 lines · Jiri Olsa
Quoted 9 lines
Also woks under interval mode:
$ ./perf stat -e cycles,instructions --per-task -p 16431,16173 -I 1000 # time task counts unit events 1.000085816 TASK-16173 0 cycles 1.000085816 TASK-16431 3,358,360,926 cycles 3.375949851 TASK-16173 0 instructions 3.375949851 TASK-16431 3,414,532,317 instructions
Quoted 1 line
Why not print $comm-$pid versus TASK-$pid?
Agreed.
- Arnaldo