perf: Allow leader sampling on inherited events
Jiri Olsa
reviewercover perf: Allow leader sampling on inherited events
hi,
Jen-Cheng(Tommy) Huang reported the leader sampling not working on children processes:
http://www.mail-archive.com/[email protected]/msg01644.html
The leader sampling (example below) lets the group leader event (cycles) do the sampling and reads the rest of the group (cache-misses) via PERF_FORMAT_GROUP format.
Example:
$ perf record -e '{cycles,cache-misses}:S' <workload>
$ perf report --groupThe perf report --group allows to see all events group data in single view.
The reason for leader sampling being switched off for inherited events, is that the kernel does no allow PERF_FORMAT_GROUP format on inherited events (which is used by leader sampling).
I switched on the PERF_FORMAT_GROUP format for inherited events with few other fixies in patches:
perf: Deny optimized switch for events read by PERF_SAMPLE_READ
perf: Allow PERF_FORMAT_GROUP format on inherited events
And I fixed perf tool code to be able to process data from children processes.
Anyway, I might have missed some other reason why this was never switched on in kernel, so sending this as RFC.
thanks for comments,
jirka
---
Jiri Olsa (5):
perf: Deny optimized switch for events read by PERF_SAMPLE_READ
perf: Allow PERF_FORMAT_GROUP format on inherited events perf tools: Add support to traverse xyarrays
perf tools: Add hash of periods for struct perf_sample_id perf tools: Allow PERF_FORMAT_GROUP for inherited events
kernel/events/core.c | 25 ++++++++++++++----------- tools/perf/Makefile.perf | 1 + tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/tests.h | 1 + tools/perf/tests/xyarray.c | 33 +++++++++++++++++++++++++++++++++ tools/perf/util/evsel.c | 17 ++++++++++++++--- tools/perf/util/evsel.h | 5 ++++- tools/perf/util/session.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ tools/perf/util/xyarray.c | 4 +++- tools/perf/util/xyarray.h | 6 ++++++ 10 files changed, 167 insertions(+), 22 deletions(-) create mode 100644 tools/perf/tests/xyarray.c
Jiri Olsa
reviewerPATCH 1/5 perf: Deny optimized switch for events read by PERF_SAMPLE_READ
The optimized task context switch for cloned perf events just swaps whole perf event contexts (of current and next process) if it finds them suitable. Events from the 'current' context will now measure data of the 'next' context and vice versa.
This is ok for cases where we are not directly interested in the event->count value of separate child events, like:
- standard sampling, where we take 'period' value for the event count
- counting, where we accumulate all events (children) into a single count value
But in case we read event by using the PERF_SAMPLE_READ sample type, we are interested in direct event->count value meassured in specific task. Switching events within tasks for this kind of measurements corrupts data.
Fixing this by setting/unsetting pin_count for perf event context once event with PERF_SAMPLE_READ read is added/removed. The pin_count value != 0 makes the context not suitable for optimized switch.
--- kernel/events/core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
kernel/events/core.c +12 -0
@@ -1117,6 +1117,12 @@ ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)return &ctx->flexible_groups; } +static bool has_inherit_read (struct perf_event *event) +{ +return event->attr.inherit && + (event->attr.sample_type &PERF_SAMPLE_READ ); +} +/* * Add a event from the lists for its context. * Must be called with ctx->mutex and ctx->lock held.
@@ -1148,6 +1154,9 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)if (has_branch_stack (event)) ctx->nr_branch_stack++; +if (has_inherit_read (event)) + ctx->pin_count++; +list_add_rcu (&event->event_entry, &ctx->event_list);if (!ctx->nr_events)perf_pmu_rotate_start (ctx->pmu);
@@ -1313,6 +1322,9 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)if (has_branch_stack (event)) ctx->nr_branch_stack--; +if (has_inherit_read (event)) + ctx->pin_count--; + ctx->nr_events--;if (event->attr.inherit_stat) ctx->nr_stat--;
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 2/5 perf: Allow PERF_FORMAT_GROUP format on inherited events
In reply to Jiri OlsaI assume the reason for this being disabled is the difficulty to read child events once in perf overflow routine, thus the perf_output_read_group function. The read syscall function perf_event_read_group seems to handle this nicely.
My goal is to be able to read all events in group on leader sample by using the PERF_SAMPLE_READ with PERF_FORMAT_GROUP format. Once the monitored process forks, I need the child processes/events do the same and store samples into parents ring buffer.
So I need all events sample just to report their own value (without child events being included). Thus switching the perf_event_count call for simple read of event->count.
--- kernel/events/core.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-)
kernel/events/core.c +2 -11
@@ -4611,9 +4611,6 @@ static void perf_output_read_one(struct perf_output_handle *handle,__output_copy (handle, values, n *sizeof (u64)); } -/* -* XXX PERF_FORMAT_GROUP vs inherited events seems difficult. -*/ static void perf_output_read_group (struct perf_output_handle *handle,struct perf_event *event,u64 enabled,u64 running)
@@ -4634,7 +4631,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,if (leader != event) leader->pmu->read (leader); - values[n++] =perf_event_count (leader); + values[n++] =local64_read (&leader->count);if (read_format &PERF_FORMAT_ID ) values[n++] =primary_event_id (leader);
@@ -4647,7 +4644,7 @@ static void perf_output_read_group(struct perf_output_handle *handle, (sub->state == PERF_EVENT_STATE_ACTIVE)) sub->pmu->read(sub); - values[n++] =perf_event_count (sub); + values[n++] =local64_read (&sub->count);if (read_format &PERF_FORMAT_ID ) values[n++] =primary_event_id (sub);
@@ -6956,12 +6953,6 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,local64_set (&hwc->period_left, hwc->sample_period); -/* -* we currently do not support PERF_FORMAT_GROUP on inherited events -*/ -if (attr->inherit && (attr->read_format &PERF_FORMAT_GROUP )) - goto err_ns; - pmu =perf_init_event (event);if (!pmu) goto err_ns;
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 3/5 perf tools: Add support to traverse xyarrays
In reply to Jiri OlsaAdding xyarray__for_each define to allow sequentially traverse xyarrays. It will be handy in following patch.
--- tools/perf/Makefile.perf | 1 + tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/tests.h | 1 + tools/perf/tests/xyarray.c | 33 +++++++++++++++++++++++++++++++++ tools/perf/util/xyarray.c | 4 +++- tools/perf/util/xyarray.h | 6 ++++++ 6 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tools/perf/tests/xyarray.c
tools/perf/Makefile.perf +1 -0
@@ -425,6 +425,7 @@ endif endif LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o +LIB_OBJS += $(OUTPUT)tests/xyarray.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
tools/perf/tests/builtin-test.c +4 -0
@@ -154,6 +154,10 @@ static struct test { .func = test__hists_cumulate, }, { + .desc = "Test xyarray", + .func = test__xyarray, + }, + { .func = NULL, }, };
tools/perf/tests/tests.h +1 -0
@@ -48,6 +48,7 @@ int test__mmap_thread_lookup(void);int test__thread_mg_share (void );int test__hists_output (void );int test__hists_cumulate (void ); +int test__xyarray (void );#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/tests/xyarray.c new file +33 -0
@@ -0,0 +1,33 @@ +#include "tests.h" +#include "xyarray.h" +#include "debug.h" + +struct krava { +int a; +}; + +#define X 100 +#define Y 100 + +int test__xyarray (void ) +{ +struct xyarray *a; +struct krava *k; +int x, y; + + a =xyarray__new (X ,Y ,sizeof (struct krava )); +TEST_ASSERT_VAL ("failed to allocate xyarray" , a); + +for (x =0 ; x <X ; x++) { +for (y =0 ; y <Y ; y++) { + k =xyarray__entry (a, x, y); + k->a = x *X + y; + } + } + + y =0 ; +xyarray__for_each (a, k) +TEST_ASSERT_VAL ("wrong array value" , k->a == y++); + +return 0 ; +}
tools/perf/util/xyarray.c +3 -1
@@ -4,11 +4,13 @@struct xyarray *xyarray__new (int xlen,int ylen,size_t entry_size) {size_t row_size = ylen * entry_size; -struct xyarray *xy =zalloc (sizeof (*xy) + xlen * row_size); +size_t size = xlen * row_size; +struct xyarray *xy =zalloc (sizeof (*xy) + size);if (xy !=NULL ) { xy->entry_size = entry_size; xy->row_size = row_size; + xy->size = size; }return xy;
tools/perf/util/xyarray.h +6 -0
@@ -6,6 +6,7 @@struct xyarray {size_t row_size;size_t entry_size; +size_t size;char contents[]; };
@@ -17,4 +18,9 @@ static inline void *xyarray__entry(struct xyarray *xy, int x, int y) return &xy->contents[x * xy->row_size + y * xy->entry_size]; } +#define xyarray__for_each (array, entry) \ + for (entry = (void *) &array->contents[0]; \ + (void *) entry < ((void *) array->contents + array->size); \ + entry++) +#endif /* _PERF_XYARRAY_H_ */
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 4/5 perf tools: Add hash of periods for struct perf_sample_id
In reply to Jiri OlsaWith PERF_FORMAT_GROUP format on inherited events being allowed in kernel, we can now allow leader sampling on inherited events.
But before we actually switch it on, we need to change the sorting of PERF_SAMPLE_READ sample's data. Currently PERF_SAMPLE_READ values are sorted on event id. Now when we'll get data from all children processes we need to add TID as another sort key.
Adding hash of TIDs into each 'struct perf_sample_id' to hold event values for different TIDs.
--- tools/perf/util/evsel.c | 13 +++++++ tools/perf/util/evsel.h | 5 ++- tools/perf/util/session.c | 93 ++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 104 insertions(+), 7 deletions(-)
tools/perf/util/evsel.c +13 -0
@@ -787,8 +787,21 @@ void perf_evsel__free_fd(struct perf_evsel *evsel) evsel->fd =NULL ; } +static void free_sample_id (struct perf_evsel *evsel) +{ +struct perf_sample_id *sid; + +if (evsel->sample_id) { +xyarray__for_each (evsel->sample_id, sid) { +if (sid->periods) +perf_sample_hash__delete (sid->periods); + } + } +} +void perf_evsel__free_id (struct perf_evsel *evsel) { +free_sample_id (evsel);xyarray__delete (evsel->sample_id); evsel->sample_id =NULL ;zfree (&evsel->id);
tools/perf/util/evsel.h +4 -1
@@ -29,6 +29,7 @@ struct perf_counts { };struct perf_evsel ; +struct perf_sample_hash ;/* * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are
@@ -40,9 +41,11 @@ struct perf_sample_id {struct perf_evsel *evsel;/* Holds total ID period value for PERF_SAMPLE_READ processing. */ -u64 period; +struct perf_sample_hash *periods; }; +void perf_sample_hash__delete (struct perf_sample_hash *hash); +/** struct perf_evsel - event selector * * @name - Can be set to retain the original event name passed by the user,
tools/perf/util/session.c +87 -6
116 lines not on this page · raw message
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 5/5 perf tools: Allow PERF_FORMAT_GROUP for inherited events
In reply to Jiri OlsaSwithing on leader sampling on inherited events.
Following command will now get data from all children processes:
$ perf record -e '{cycles,cache-misses}:S' <workload>Use following command to display the data:
$ perf report --group
--- tools/perf/util/evsel.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
tools/perf/util/evsel.c +1 -3
@@ -584,10 +584,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)* Apply group format only if we belong to group * with more than one members. */ -if (leader->nr_members >1 ) { +if (leader->nr_members >1 ) attr->read_format |=PERF_FORMAT_GROUP ; - attr->inherit =0 ; - } }/*
Signature · 1 line
1.8.3.1
Quoted 25 lines · Jiri Olsa
hi,
Jen-Cheng(Tommy) Huang reported the leader sampling not working on children processes:
http://www.mail-archive.com/[email protected]/msg01644.htmlThe leader sampling (example below) lets the group leader event (cycles) do the sampling and reads the rest of the group (cache-misses) via
PERF_FORMAT_GROUPformat.Example:
$ perf record -e '{cycles,cache-misses}:S' <workload> $ perf report --groupThe perf report --group allows to see all events group data in single view.
The reason for leader sampling being switched off for inherited events, is that the kernel does no allow
PERF_FORMAT_GROUPformat on inherited events (which is used by leader sampling).I switched on the
PERF_FORMAT_GROUPformat for inherited events with few other fixies in patches:
perf: Deny optimized switch for events read byPERF_SAMPLE_READ
perf: AllowPERF_FORMAT_GROUPformat on inherited events
Quoted 5 lines
And I fixed perf tool code to be able to process data from children processes.
Anyway, I might have missed some other reason why this was never switched on in kernel, so sending this as RFC.
Also reachable in here:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/core_format_group
jirka
A message that is not in the archive (sent off-list or not yet received): CABooUW0qEpo2YhXfxHsf48mw1acuZ63bq=Fot3kH1eHOfryU-A@mail.gmail.com
Quoted 19 lines · Jen-Cheng(Tommy) Huang
Hi Jiri,
1. Thank you so much for providing the patch.
I am trying to test out the patch.
(I got the source using "git checkout -b perf remotes/origin/perf/core_format_group"
after clone)
However, the perf in your repo seems having issues withsample_read:S. (:S works fine with my original perf that comes with the kernel.) When I do
perf record -e '{instructions,cycles}:S'/bin/lsThe following error is shown
Error:
Thesys_perf_event_open()syscall returned with 22 (Invalid argument) for event (instructions)./bin/dmesgmay provide additional information.
NoCONFIG_PERF_EVENTS=ykernel support configured?
Quoted 3 lines
This error does not occur without :S.
perf record -e '{instructions,cycles}'/bin/ls
This shows no errors.
have u boot the new kernel? there're 2 kernel patches within the patchset
but right, the perf code should detect the kernel change and keep old behaviour if it's not detected..
Quoted 5 lines
2. Another issue I have is to show the sample value using 'perf script'. Currently, I am using perf report -D to show the sample read values, the format is not what I need. Could you give me some hints on where to modify to show the sample values using perf script?
there's no support in perf script to display the sample read values.. I'll check if that could be added
thanks,
jirka