Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Enable pre-event inherit setting by config terms

This patch allows perf record setting event's attr.inherit bit by
config terms like:

# perf record -e cycles/no-inherit/ ...
# perf record -e cycles/inherit/ ...

So user can control inherit bit for each event separately.

In following example, a.out fork()s in main then do some complex
CPU intensive computations in both of its children.

Basic result with and without inherit:

# perf record -e cycles -e instructions ./a.out
[ perf record: Woken up 9 times to write data ]
[ perf record: Captured and wrote 2.205 MB perf.data (47920 samples) ]
# perf report --stdio
# ...
# Samples: 23K of event 'cycles'
# Event count (approx.): 23641752891
...
# Samples: 24K of event 'instructions'
# Event count (approx.): 30428312415

# perf record -i -e cycles -e instructions ./a.out
[ perf record: Woken up 5 times to write data ]
[ perf record: Captured and wrote 1.111 MB perf.data (24019 samples) ]
...
# Samples: 12K of event 'cycles'
# Event count (approx.): 11699501775
...
# Samples: 12K of event 'instructions'
# Event count (approx.): 15058023559

Cancel inherit for one event when globally enable:

# perf record -e cycles/no-inherit/ -e instructions ./a.out
[ perf record: Woken up 7 times to write data ]
[ perf record: Captured and wrote 1.660 MB perf.data (36004 samples) ]
...
# Samples: 12K of event 'cycles/no-inherit/'
# Event count (approx.): 11895759282
...
# Samples: 24K of event 'instructions'
# Event count (approx.): 30668000441

Enable inherit for one event when globally disable:

# perf record -i -e cycles/inherit/ -e instructions ./a.out
[ perf record: Woken up 7 times to write data ]
[ perf record: Captured and wrote 1.654 MB perf.data (35868 samples) ]
...
# Samples: 23K of event 'cycles/inherit/'
# Event count (approx.): 23285400229
...
# Samples: 11K of event 'instructions'
# Event count (approx.): 14969050259

Committer note:

One can check if the bit was set, in addition to seeing the result in
the perf.data file size as above by doing one of:

# perf record -e cycles -e instructions -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.911 MB perf.data (63 samples) ]
# perf evlist -v
cycles: size: 112, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|ID|CPU|PERIOD, read_format: ID, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
instructions: size: 112, config: 0x1, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|ID|CPU|PERIOD, read_format: ID, disabled: 1, inherit: 1, freq: 1, sample_id_all: 1, exclude_guest: 1
#

So, the inherit bit was set in both, now, if we disable it globally using
--no-inherit:

# perf record --no-inherit -e cycles -e instructions -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.910 MB perf.data (56 samples) ]
# perf evlist -v
cycles: size: 112, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|ID|CPU|PERIOD, read_format: ID, disabled: 1, mmap: 1, comm: 1, freq: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
instructions: size: 112, config: 0x1, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|ID|CPU|PERIOD, read_format: ID, disabled: 1, freq: 1, sample_id_all: 1, exclude_guest: 1

No inherit bit set, then disabling it and setting just on the cycles event:

# perf record --no-inherit -e cycles/inherit/ -e instructions -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.909 MB perf.data (48 samples) ]
# perf evlist -v
cycles/inherit/: size: 112, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|ID|CPU|PERIOD, read_format: ID, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
instructions: size: 112, config: 0x1, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|ID|CPU|PERIOD, read_format: ID, disabled: 1, freq: 1, sample_id_all: 1, exclude_guest: 1
#

We can see it as well in by using a more verbose level of debug messages in
the tool that sets up the perf_event_attr, 'perf record' in this case:

[root@zoo ~]# perf record -vv --no-inherit -e cycles/inherit/ -e instructions -a usleep 1
------------------------------------------------------------
perf_event_attr:
size 112
{ sample_period, sample_freq } 4000
sample_type IP|TID|TIME|ID|CPU|PERIOD
read_format ID
disabled 1
inherit 1
mmap 1
comm 1
freq 1
task 1
sample_id_all 1
exclude_guest 1
mmap2 1
comm_exec 1
------------------------------------------------------------
sys_perf_event_open: pid -1 cpu 0 group_fd -1 flags 0x8
sys_perf_event_open: pid -1 cpu 1 group_fd -1 flags 0x8
sys_perf_event_open: pid -1 cpu 2 group_fd -1 flags 0x8
sys_perf_event_open: pid -1 cpu 3 group_fd -1 flags 0x8
------------------------------------------------------------
perf_event_attr:
size 112
config 0x1
{ sample_period, sample_freq } 4000
sample_type IP|TID|TIME|ID|CPU|PERIOD
read_format ID
disabled 1
freq 1
sample_id_all 1
exclude_guest 1
------------------------------------------------------------
sys_perf_event_open: pid -1 cpu 0 group_fd -1 flags 0x8

<SNIP>

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Li Zefan <lizefan@huawei.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1446029705-199659-2-git-send-email-wangnan0@huawei.com
[ s/u64/bool/ for the perf_evsel_config_term inherit field - jolsa]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Wang Nan and committed by
Arnaldo Carvalho de Melo
374ce938 5baecbcd

+29
+9
tools/perf/util/evsel.c
··· 652 652 case PERF_EVSEL__CONFIG_TERM_STACK_USER: 653 653 dump_size = term->val.stack_user; 654 654 break; 655 + case PERF_EVSEL__CONFIG_TERM_INHERIT: 656 + /* 657 + * attr->inherit should has already been set by 658 + * perf_evsel__config. If user explicitly set 659 + * inherit using config terms, override global 660 + * opt->no_inherit setting. 661 + */ 662 + attr->inherit = term->val.inherit ? 1 : 0; 663 + break; 655 664 default: 656 665 break; 657 666 }
+2
tools/perf/util/evsel.h
··· 43 43 PERF_EVSEL__CONFIG_TERM_TIME, 44 44 PERF_EVSEL__CONFIG_TERM_CALLGRAPH, 45 45 PERF_EVSEL__CONFIG_TERM_STACK_USER, 46 + PERF_EVSEL__CONFIG_TERM_INHERIT, 46 47 PERF_EVSEL__CONFIG_TERM_MAX, 47 48 }; 48 49 ··· 56 55 bool time; 57 56 char *callgraph; 58 57 u64 stack_user; 58 + bool inherit; 59 59 } val; 60 60 }; 61 61
+14
tools/perf/util/parse-events.c
··· 666 666 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 667 667 CHECK_TYPE_VAL(NUM); 668 668 break; 669 + case PARSE_EVENTS__TERM_TYPE_INHERIT: 670 + CHECK_TYPE_VAL(NUM); 671 + break; 672 + case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 673 + CHECK_TYPE_VAL(NUM); 674 + break; 669 675 case PARSE_EVENTS__TERM_TYPE_NAME: 670 676 CHECK_TYPE_VAL(STR); 671 677 break; ··· 707 701 switch (term->type_term) { 708 702 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 709 703 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 704 + case PARSE_EVENTS__TERM_TYPE_INHERIT: 705 + case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 710 706 return config_term_common(attr, term, err); 711 707 default: 712 708 if (err) { ··· 771 763 break; 772 764 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 773 765 ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); 766 + break; 767 + case PARSE_EVENTS__TERM_TYPE_INHERIT: 768 + ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0); 769 + break; 770 + case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 771 + ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); 774 772 break; 775 773 default: 776 774 break;
+2
tools/perf/util/parse-events.h
··· 67 67 PARSE_EVENTS__TERM_TYPE_TIME, 68 68 PARSE_EVENTS__TERM_TYPE_CALLGRAPH, 69 69 PARSE_EVENTS__TERM_TYPE_STACKSIZE, 70 + PARSE_EVENTS__TERM_TYPE_NOINHERIT, 71 + PARSE_EVENTS__TERM_TYPE_INHERIT 70 72 }; 71 73 72 74 struct parse_events_term {
+2
tools/perf/util/parse-events.l
··· 187 187 time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 188 188 call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } 189 189 stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } 190 + inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } 191 + no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 190 192 , { return ','; } 191 193 "/" { BEGIN(INITIAL); return '/'; } 192 194 {name_minus} { return str(yyscanner, PE_NAME); }