perf group read for inherited events
A message that is not in the archive (sent off-list or not yet received): [email protected]
Peter Zijlstra
maintainerQuoted 14 lines · Andi Kleen
I have a need for read group reads for inherited events.
It looks like the perf group read code already has all the code to handle inheritance,
__perf_read_group_addwalks the children list and adds them all up.4409 4410 list_for_each_entry(sub, &leader->sibling_list, group_entry) { 4411 values[n++] += perf_event_count(sub); 4412 if (read_format & PERF_FORMAT_ID) 4413 values[n++] = primary_event_id(sub); 4414 }
Quoted 4 lines
I disabled the check that forbids this and it seems to work from some simple testing.
Again do I miss something why this was disabled?
The thing that seems difficult is PERF_SAMPLE_READ vs inherited, irrespective of PERF_FORMAT_GROUP.
The error seems to be in that patch you fingered:
3dab77fb1bf8 ("perf: Rework/fix the whole read vs group stuff")
- PERF_SAMPLE_GROUP = 1U << 4, + PERF_SAMPLE_READ = 1U << 4,
- if (attr->inherit && (attr->sample_type & PERF_SAMPLE_GROUP))
+ if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
is a clear fail :/
Quoted 8 lines
Perhaps some locking issue? There are some comments on it, but I'm not sure I understand all the subtleties:
/* * By locking the child_mutex of the leader we effectively * lock the child list of all siblings.. XXX explain how. */ mutex_lock(&leader->child_mutex);
This is more recent. Here I failed to find a coherent text to explain the locking. It is correct through. I think its something like:
@@ -4426,8 +4426,9 @@ static int perf_read_group(struct perf_event *event,
values[0] = 1 + leader->nr_siblings;
/*
- * By locking the child_mutex of the leader we effectively
- * lock the child list of all siblings.. XXX explain how.
+ * By locking the child_mutex of the leader we effectively lock the
+ * child list of all siblings. Since inherit_group() will first clone
+ * the leader and will this be blocked on us holding its child_mutex.
*/
mutex_lock(&leader->child_mutex);
Quoted 1 line
Or is the simple patch below good enough?
The below seems to be the correct thing. It is rather unfortunate that this would break/significantly change existing semantics :/
--- kernel/events/core.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
kernel/events/core.c +9 -5
@@ -5722,9 +5722,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)
@@ -5769,6 +5766,12 @@ static void perf_output_read_group(struct perf_output_handle *handle,#define PERF_FORMAT_TOTAL_TIMES (PERF_FORMAT_TOTAL_TIME_ENABLED|\ PERF_FORMAT_TOTAL_TIME_RUNNING) +/* +* XXX PERF_SAMPLE_READ vs inherited events seems difficult. +* +* The problem is that its both hard and excessively expensive to iterate the +* child list from interrupt/NMI context. +*/ static void perf_output_read (struct perf_output_handle *handle,struct perf_event *event) {
@@ -9434,9 +9437,10 @@ 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 +* We currently do not support PERF_SAMPLE_READ on inherited events. +* See perf_output_read(). */ -if (attr->inherit && (attr->read_format &PERF_FORMAT_GROUP )) +if (attr->inherit && (attr->sample_type &PERF_SAMPLE_READ )) goto err_ns;if (!has_branch_stack (event))
Quoted 4 lines · Peter Zijlstra
Quoted 1 line
Or is the simple patch below good enough?
The below seems to be the correct thing. It is rather unfortunate that this would break/significantly change existing semantics :/
The "existing semantics" as in ignoring the PERF_SAMPLE_READ in sample_type, even though it wasn't implemented? It seems reasonable to me.
If you really worry about it could drop a printk_once in and see if it triggers anywhere (and if yes drop the if completely)
The patch looks good to me. Please consider adding it. I have some patches to use this in perf stat, will submit later.
-Andi
Peter Zijlstra
maintainerQuoted 8 lines · Andi Kleen
Quoted 4 lines · Peter Zijlstra
Quoted 1 line
Or is the simple patch below good enough?
The below seems to be the correct thing. It is rather unfortunate that this would break/significantly change existing semantics :/
The "existing semantics" as in ignoring the
PERF_SAMPLE_READinsample_type, even though it wasn't implemented? It seems reasonable to me.
Right, so where we used to accept PERF_SAMPLE_READ on inherited events, we now no longer will.
Note that it currently doesn't work right, even if it doesn't fail like with the proposed patch.
Typically Vince will (rightly) complain when I change things like this. But seeing how even if we accept it, it is fairly terminally buggered in any case, we could change it.
Vince, do you know of anybody that would be immediately affected by this?
Quoted 16 lines · Peter Zijlstra
Quoted 8 lines · Andi Kleen
Quoted 4 lines · Peter Zijlstra
Quoted 1 line
Or is the simple patch below good enough?
The below seems to be the correct thing. It is rather unfortunate that this would break/significantly change existing semantics :/
The "existing semantics" as in ignoring the
PERF_SAMPLE_READinsample_type, even though it wasn't implemented? It seems reasonable to me.Right, so where we used to accept
PERF_SAMPLE_READon inherited events, we now no longer will.Note that it currently doesn't work right, even if it doesn't fail like with the proposed patch.
Quoted 6 lines
Typically Vince will (rightly) complain when I change things like this. But seeing how even if we accept it, it is fairly terminally buggered in any case, we could change it.
Vince, do you know of anybody that would be immediately affected by this?
I often only hear about breakage months later after it's too late.
So the issue is currently if you were sampling, and you were sampling on an event group, and you had set PERF_SAMPLE_READ to get all counts for a group, and the event was also inherited.... perf_event_open() would let you do this even though the results would probably be wrong?
I'm not aware of anyone trying to do this, or at least I should say PAPI isn't trying to do this (PAPI currently has pretty simplistic sampling support, though that's getting a major overhaul this summer).
Vince
Peter Zijlstra
maintainerQuoted 3 lines · Vince Weaver
So the issue is currently if you were sampling, and you were sampling on an event group, and you had set
PERF_SAMPLE_READto get all counts for a group, and the event was also inherited....
No, anything PERF_SAMPLE_READ (group or not) on inherited events is wrong.
It would only report the event count of the current task count + all dead child counts (if you hit the parent event). It would not include the current count of any other live tasks in the hierarchy.
And the problem is that fixing this is rather tricky and iterating the hierarchy can be excessively expensive in any case (imagine having to iterate several hundred tasks tasks from that NMI/interrupt).
And since its from NMI/interrupt context it is impossible to get the current count of any other live tasks that are running on another CPU.
Quoted 2 lines
perf_event_open()would let
you do this even though the results would probably be wrong?
Right, currently we have the filter on PERF_FORMAT_GROUP, but it should be PERF_SAMPLE_READ.
So a !group SAMPLE_READ on inherited is currently allowed but returns 'interesting' values.
Quoted 7 lines · Peter Zijlstra
Quoted 3 lines · Vince Weaver
So the issue is currently if you were sampling, and you were sampling on an event group, and you had set
PERF_SAMPLE_READto get all counts for a group, and the event was also inherited....No, anything
PERF_SAMPLE_READ(group or not) on inherited events is wrong.
ah, yes. I should fix the wording in the manpage as it's a bit confusing.
Quoted 8 lines
Quoted 2 lines
perf_event_open()would let
you do this even though the results would probably be wrong?Right, currently we have the filter on
PERF_FORMAT_GROUP, but it should bePERF_SAMPLE_READ.So a !group
SAMPLE_READon inherited is currently allowed but returns 'interesting' values.
I'm not aware of anything that will break on fixing this.
Especially if we are always returning bad results then it would be better to break things so we find people (if any) who are depending on the wrong results.
Vince
tip-bot for Peter Zijlstra
merge bot[tip:perf/core] perf/core: Correct event creation with PERF_FORMAT_GROUP
In reply to Peter Zijlstraperf/core: Correct event creation with PERF_FORMAT_GROUP
Commit-ID: ba5213ae6b88fb170c4771fef6553f759c7d8cdd Gitweb: http://git.kernel.org/tip/ba5213ae6b88fb170c4771fef6553f759c7d8cdd Author: Peter Zijlstra <[email protected]> AuthorDate: Tue, 30 May 2017 11:45:12 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 8 Jun 2017 10:12:38 +0200
perf/core: Correct event creation with PERF_FORMAT_GROUP
Andi was asking about PERF_FORMAT_GROUP vs inherited events, which led to the discovery of a bug from commit:
3dab77fb1bf8 ("perf: Rework/fix the whole read vs group stuff")
- PERF_SAMPLE_GROUP = 1U << 4, + PERF_SAMPLE_READ = 1U << 4,
- if (attr->inherit && (attr->sample_type & PERF_SAMPLE_GROUP))
+ if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
is a clear fail :/
While this changes user visible behaviour; it was previously possible to create an inherited event with PERF_SAMPLE_READ; this is deemed acceptible because its results were always incorrect.
--- kernel/events/core.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
kernel/events/core.c +10 -5
@@ -5729,9 +5729,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)
@@ -5776,6 +5773,13 @@ static void perf_output_read_group(struct perf_output_handle *handle,#define PERF_FORMAT_TOTAL_TIMES (PERF_FORMAT_TOTAL_TIME_ENABLED|\ PERF_FORMAT_TOTAL_TIME_RUNNING) +/* +* XXX PERF_SAMPLE_READ vs inherited events seems difficult. +* +* The problem is that its both hard and excessively expensive to iterate the +* child list, not to mention that its impossible to IPI the children running +* on another CPU, from interrupt/NMI context. +*/ static void perf_output_read (struct perf_output_handle *handle,struct perf_event *event) {
@@ -9462,9 +9466,10 @@ 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 +* We currently do not support PERF_SAMPLE_READ on inherited events. +* See perf_output_read(). */ -if (attr->inherit && (attr->read_format &PERF_FORMAT_GROUP )) +if (attr->inherit && (attr->sample_type &PERF_SAMPLE_READ )) goto err_ns;if (!has_branch_stack (event))