Skip to content

Commit

Permalink
Make exclude guest flag from perf event attrs configurable.
Browse files Browse the repository at this point in the history
Signed-off-by: Paweł Szulik <pawel.szulik@intel.com>
  • Loading branch information
Paweł Szulik committed Sep 11, 2020
1 parent 6eda0c4 commit a58eb48
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 31 deletions.
12 changes: 8 additions & 4 deletions docs/runtime_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ measure them in transactional manner: all the events in a group must be accounte
in mind that it is impossible to group more events that there are counters available.
* `uncore events` - events which can be counted by PMUs outside core.
* `PMU` - Performance Monitoring Unit
* `exclude_guest` - parameter from ``man perf_event_open``.

#### Getting config values
Using perf tools:
Expand Down Expand Up @@ -199,7 +200,8 @@ perf_event_attr:
"config": [
"0x304"
],
"name": "event_name"
"name": "event_name",
"exclude_guest": true
}
]
},
Expand All @@ -213,7 +215,8 @@ perf_event_attr:
"config": [
"0x304"
],
"name": "event_name"
"name": "event_name",
"exclude_guest": true
}
]
}
Expand Down Expand Up @@ -243,7 +246,8 @@ Let's explain this by example:
"config": [
"0x304"
],
"name": "uncore_imc_0/cas_count_write"
"name": "uncore_imc_0/cas_count_write",
"exclude_guest": true
},
{
"type": 19,
Expand All @@ -261,7 +265,7 @@ Let's explain this by example:
it would be counted by **all** Integrated Memory Controller PMUs with config provided from libpfm package.
(using this function: https://man7.org/linux/man-pages/man3/pfm_get_os_event_encoding.3.html)

- `uncore_imc_0/cas_count_write` - because of `uncore_imc_0` type and entry in custom events it would be counted by `uncore_imc_0` PMU with provided config.
- `uncore_imc_0/cas_count_write` - because of `uncore_imc_0` type and entry in custom events it would be counted by `uncore_imc_0` PMU with provided config and exclude_guest param.

- `uncore_imc_1/cas_count_all` - because of entry in custom events with type field, event would be counted by PMU with **19** type and provided config.

Expand Down
15 changes: 10 additions & 5 deletions perf/collector_libpfm.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func (c *collector) setup() error {
customEvent, ok := c.eventToCustomEvent[event]
if ok {
config := c.createConfigFromRawEvent(customEvent)
leaderFileDescriptors, err = c.registerEvent(eventInfo{string(customEvent.Name), config, cgroupFd, i, isGroupLeader}, leaderFileDescriptors)
leaderFileDescriptors, err = c.registerEvent(eventInfo{string(customEvent.Name), config, cgroupFd, i, isGroupLeader, customEvent.ExcludeGuest}, leaderFileDescriptors)
if err != nil {
return err
}
Expand All @@ -206,7 +206,7 @@ func (c *collector) setup() error {
if err != nil {
return err
}
leaderFileDescriptors, err = c.registerEvent(eventInfo{string(event), config, cgroupFd, i, isGroupLeader}, leaderFileDescriptors)
leaderFileDescriptors, err = c.registerEvent(eventInfo{string(event), config, cgroupFd, i, isGroupLeader, false}, leaderFileDescriptors)
if err != nil {
return err
}
Expand Down Expand Up @@ -253,6 +253,7 @@ type eventInfo struct {
pid int
groupIndex int
isGroupLeader bool
excludeGuest bool
}

func (c *collector) registerEvent(event eventInfo, leaderFileDescriptors map[int]int) (map[int]int, error) {
Expand All @@ -266,7 +267,7 @@ func (c *collector) registerEvent(event eventInfo, leaderFileDescriptors map[int
flags = unix.PERF_FLAG_FD_CLOEXEC
}

setAttributes(event.config, event.isGroupLeader)
setAttributes(event.config, event.isGroupLeader, event.excludeGuest)

for _, cpu := range c.onlineCPUs {
fd, err := unix.PerfEventOpen(event.config, pid, cpu, leaderFileDescriptors[cpu], flags)
Expand Down Expand Up @@ -342,16 +343,20 @@ func createPerfEventAttr(event CustomEvent) *unix.PerfEventAttr {
return config
}

func setAttributes(config *unix.PerfEventAttr, leader bool) {
func setAttributes(config *unix.PerfEventAttr, leader bool, excludeGuest bool) {
config.Sample_type = perfSampleIdentifier
config.Read_format = unix.PERF_FORMAT_TOTAL_TIME_ENABLED | unix.PERF_FORMAT_TOTAL_TIME_RUNNING | unix.PERF_FORMAT_GROUP | unix.PERF_FORMAT_ID
config.Bits = perfAttrBitsInherit | perfAttrBitsExcludeGuest
config.Bits = perfAttrBitsInherit

// Group leader should have this flag set to disable counting until all group would be prepared.
if leader {
config.Bits |= unix.PerfBitDisabled
}

if excludeGuest {
config.Bits |= unix.PerfBitExcludeGuest
}

config.Size = uint32(unsafe.Sizeof(unix.PerfEventAttr{}))
}

Expand Down
57 changes: 44 additions & 13 deletions perf/collector_libpfm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"encoding/binary"
"testing"

"golang.org/x/sys/unix"

"github.com/stretchr/testify/assert"

info "github.com/google/cadvisor/info/v1"
Expand Down Expand Up @@ -146,19 +148,48 @@ func TestCollector_UpdateStats(t *testing.T) {
})
}

var createPerfEventAttrCases = []struct {
event CustomEvent
perfEventAttr unix.PerfEventAttr
}{
{
CustomEvent{
Type: 0x1,
Config: Config{0x2, 0x3, 0x4},
Name: "fake_event",
ExcludeGuest: false,
},
unix.PerfEventAttr{
Type: 0x1,
Config: 0x2,
Ext1: 0x3,
Ext2: 0x4,
},
},
{
CustomEvent{
Type: 0x4,
Config: Config{0x5, 0x1, 0x4},
Name: "another_fake_event",
ExcludeGuest: true,
},
unix.PerfEventAttr{
Type: 0x4,
Config: 0x5,
Ext1: 0x1,
Ext2: 0x4,
},
},
}

func TestCreatePerfEventAttr(t *testing.T) {
event := CustomEvent{
Type: 0x1,
Config: Config{uint64(0x2), uint64(0x3), uint64(0x4)},
Name: "fake_event",
for _, testCase := range createPerfEventAttrCases {
attributes := createPerfEventAttr(testCase.event)
assert.Equal(t, testCase.perfEventAttr.Type, attributes.Type)
assert.Equal(t, testCase.perfEventAttr.Config, attributes.Config)
assert.Equal(t, testCase.perfEventAttr.Ext1, attributes.Ext1)
assert.Equal(t, testCase.perfEventAttr.Ext2, attributes.Ext2)
}

attributes := createPerfEventAttr(event)

assert.Equal(t, uint32(1), attributes.Type)
assert.Equal(t, uint64(2), attributes.Config)
assert.Equal(t, uint64(3), attributes.Ext1)
assert.Equal(t, uint64(4), attributes.Ext2)
}

func TestSetGroupAttributes(t *testing.T) {
Expand All @@ -169,13 +200,13 @@ func TestSetGroupAttributes(t *testing.T) {
}

attributes := createPerfEventAttr(event)
setAttributes(attributes, true)
setAttributes(attributes, true, true)
assert.Equal(t, uint64(65536), attributes.Sample_type)
assert.Equal(t, uint64(0xf), attributes.Read_format)
assert.Equal(t, uint64(0x100003), attributes.Bits)

attributes = createPerfEventAttr(event)
setAttributes(attributes, false)
setAttributes(attributes, false, true)
assert.Equal(t, uint64(65536), attributes.Sample_type)
assert.Equal(t, uint64(0xf), attributes.Read_format)
assert.Equal(t, uint64(0x100002), attributes.Bits)
Expand Down
3 changes: 3 additions & 0 deletions perf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ type CustomEvent struct {

// Human readable name of metric that will be created from the event.
Name Event `json:"name"`

// See exclude_guest parameter documentation at man perf_event_open.
ExcludeGuest bool `json:"exclude_guest,omitempty"`
}

type Config []uint64
Expand Down
6 changes: 6 additions & 0 deletions perf/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ func TestConfigParsing(t *testing.T) {
assert.Equal(t, false, events.Core.Events[1].array)
assert.Equal(t, Event("cycles"), events.Core.Events[1].events[0])

assert.Len(t, events.Core.CustomEvents, 1)
assert.Equal(t, Config{0x5300c0}, events.Core.CustomEvents[0].Config)
assert.Equal(t, uint32(0x04), events.Core.CustomEvents[0].Type)
assert.Equal(t, Event("instructions_retired"), events.Core.CustomEvents[0].Name)
assert.Equal(t, true, events.Core.CustomEvents[0].ExcludeGuest)

assert.Len(t, events.Uncore.Events, 3)
assert.Equal(t, Event("cas_count_write"), events.Uncore.Events[0].events[0])
assert.Equal(t, Event("uncore_imc_0/UNC_M_CAS_COUNT:RD"), events.Uncore.Events[1].events[0])
Expand Down
6 changes: 4 additions & 2 deletions perf/testing/perf.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"config": [
"0x5300c0"
],
"name": "instructions_retired"
"name": "instructions_retired",
"exclude_guest": true
}
]
},
Expand All @@ -26,7 +27,8 @@
"config": [
"0x5300"
],
"name": "cas_count_write"
"name": "cas_count_write",
"exclude_guest": false
}
]
}
Expand Down
8 changes: 4 additions & 4 deletions perf/uncore_libpfm.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,8 @@ func (c *uncoreCollector) setupEvent(name string, pmus uncorePMUs, groupIndex in
for _, pmu := range pmus {
config.Type = pmu.typeOf
isGroupLeader := leaderFileDescriptors[pmu.name][pmu.cpus[0]] == groupLeaderFileDescriptor
setAttributes(config, isGroupLeader)
leaderFileDescriptors[pmu.name], err = c.registerEvent(eventInfo{name, config, uncorePID, groupIndex, isGroupLeader}, pmu, leaderFileDescriptors[pmu.name])
setAttributes(config, isGroupLeader, false)
leaderFileDescriptors[pmu.name], err = c.registerEvent(eventInfo{name, config, uncorePID, groupIndex, isGroupLeader, false}, pmu, leaderFileDescriptors[pmu.name])
if err != nil {
return err
}
Expand Down Expand Up @@ -468,9 +468,9 @@ func (c *uncoreCollector) setupRawEvent(event *CustomEvent, pmus uncorePMUs, gro
}
config := createPerfEventAttr(newEvent)
isGroupLeader := leaderFileDescriptors[pmu.name][pmu.cpus[0]] == groupLeaderFileDescriptor
setAttributes(config, isGroupLeader)
setAttributes(config, isGroupLeader, event.ExcludeGuest)
var err error
leaderFileDescriptors[pmu.name], err = c.registerEvent(eventInfo{string(newEvent.Name), config, uncorePID, groupIndex, isGroupLeader}, pmu, leaderFileDescriptors[pmu.name])
leaderFileDescriptors[pmu.name], err = c.registerEvent(eventInfo{string(newEvent.Name), config, uncorePID, groupIndex, isGroupLeader, event.ExcludeGuest}, pmu, leaderFileDescriptors[pmu.name])
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions perf/uncore_libpfm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ func TestUncoreCollectorSetup(t *testing.T) {
{[]Event{"uncore_imc_0/cas_count_write", "uncore_imc_0/cas_count_read"}, true},
},
CustomEvents: []CustomEvent{
{19, Config{0x01, 0x02}, "uncore_imc_1/cas_count_read"},
{0, Config{0x02, 0x03}, "uncore_imc_0/cas_count_write"},
{18, Config{0x01, 0x02}, "uncore_imc_0/cas_count_read"},
{19, Config{0x01, 0x02}, "uncore_imc_1/cas_count_read", false},
{0, Config{0x02, 0x03}, "uncore_imc_0/cas_count_write", false},
{18, Config{0x01, 0x02}, "uncore_imc_0/cas_count_read", false},
},
},
}
Expand Down

0 comments on commit a58eb48

Please sign in to comment.