acln0/perf

(*perf.Group).Options are not respected after g.Add()

Opened this issue · 3 comments

In #4 (comment) I commented that I was getting perf: failed to open event leader: perf_event_open: permission denied with perf.perf_event_paranoid=2.

Stepping through perf_event_open with a kernel debugger I isolated the cause. The ExcludeKernel option isn't being passed through.

Here's the code I wrote where I expected the option to be set:

	var g perf.Group
	g.CountFormat = perf.CountFormat{
		Running: true,
		ID:      true,
	}

	g.Options.ExcludeKernel = true
	g.Options.ExcludeHypervisor = true
	
	g.Add(perf.Instructions, perf.CPUCycles)

Indeed, if I look at the leader attributes being used:

perf/group.go

Lines 73 to 75 in e7587bd

leaderattr := g.attrs[0]
leaderattr.CountFormat.Group = true
leader, err := Open(leaderattr, pid, cpu, nil)

... I find that g.Options aren't being respected.

Apologies, I've just realised that the code I presented above was not the code that I was running.

In my erroneous code, I was doing this:

	g.Add(perf.Instructions, perf.CPUCycles)

	g.Options.ExcludeKernel = true
	g.Options.ExcludeHypervisor = true

In the issue body, the code actually works, so they are being passed through.

I didn't realise that the options need to be set before add is called. I wonder if there is a way to make this less error prone or catch this kind of user mistake.

acln0 commented

Good catch.

https://godoc.org/acln.ro/perf#Group.Add says:

For each Configurator, a new *Attr is created, the group-specific settings are applied, then Configure is called on the *Attr to produce the final event attributes.

This may not be the best design indeed. The current design makes doing another pass of applying settings just before registering the event tricky. Perhaps Add should defer applying settings until the call to Open.

acln0 commented

I'm going to fix this as soon as I have a little time to review and merge #4 also. Thanks.