forked from luck/tmp_suning_uos_patched
perf tools: Add support for exclusive groups/events
Peter suggested that using the exclusive mode in perf could avoid some problems with bad scheduling of groups. Exclusive is implemented in the kernel, but wasn't exposed by the perf tool, so hard to use without custom low level API users. Add support for marking groups or events with :e for exclusive in the perf tool. The implementation is basically the same as the existing pinned attribute. Committer testing: # perf test "parse event" 6: Parse event definition strings : Ok # perf test -v "parse event" |& grep :u*e running test 56 'instructions:uep' running test 57 '{cycles,cache-misses,branch-misses}:e' # # # grep "model name" -m1 /proc/cpuinfo model name : AMD Ryzen 9 3900X 12-Core Processor # # perf stat -a -e '{cycles,cache-misses,branch-misses}:e' sleep 1 Performance counter stats for 'system wide': <not counted> cycles (0.00%) <not counted> cache-misses (0.00%) <not counted> branch-misses (0.00%) 1.001269893 seconds time elapsed Some events weren't counted. Try disabling the NMI watchdog: echo 0 > /proc/sys/kernel/nmi_watchdog perf stat ... echo 1 > /proc/sys/kernel/nmi_watchdog # echo 0 > /proc/sys/kernel/nmi_watchdog # perf stat -a -e '{cycles,cache-misses,branch-misses}:e' sleep 1 Performance counter stats for 'system wide': 1,298,663,141 cycles 30,962,215 cache-misses 5,325,150 branch-misses 1.001474934 seconds time elapsed # # The output for asking for precise events on AMD needs to improve, it # supposedly works only for system wide or per CPU # # perf stat -a -e '{cycles,cache-misses,branch-misses}:uep' sleep 1 Error: The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cycles). /bin/dmesg | grep -i perf may provide additional information. # perf stat -a -e '{cycles,cache-misses,branch-misses}:ue' sleep 1 Performance counter stats for 'system wide': 746,363,126 cycles 16,881,611 cache-misses 2,871,259 branch-misses 1.001636066 seconds time elapsed # Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lore.kernel.org/lkml/20201014144255.22699-1-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
78b2c50c5d
commit
0997a2662f
|
@ -58,6 +58,7 @@ counted. The following modifiers exist:
|
||||||
S - read sample value (PERF_SAMPLE_READ)
|
S - read sample value (PERF_SAMPLE_READ)
|
||||||
D - pin the event to the PMU
|
D - pin the event to the PMU
|
||||||
W - group is weak and will fallback to non-group if not schedulable,
|
W - group is weak and will fallback to non-group if not schedulable,
|
||||||
|
e - group or event are exclusive and do not share the PMU
|
||||||
|
|
||||||
The 'p' modifier can be used for specifying how precise the instruction
|
The 'p' modifier can be used for specifying how precise the instruction
|
||||||
address should be. The 'p' modifier can be specified multiple times:
|
address should be. The 'p' modifier can be specified multiple times:
|
||||||
|
|
|
@ -557,6 +557,7 @@ static int test__checkevent_pmu_events(struct evlist *evlist)
|
||||||
TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
|
||||||
TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
|
TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
|
||||||
TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
|
TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
|
||||||
|
TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -575,6 +576,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist)
|
||||||
TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
|
||||||
TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
|
TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
|
||||||
TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
|
TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
|
||||||
|
TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive);
|
||||||
|
|
||||||
/* cpu/pmu-event/u*/
|
/* cpu/pmu-event/u*/
|
||||||
evsel = evsel__next(evsel);
|
evsel = evsel__next(evsel);
|
||||||
|
@ -587,6 +589,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist)
|
||||||
TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
|
||||||
TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
|
TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
|
||||||
TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
|
TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
|
||||||
|
TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.pinned);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1277,6 +1280,49 @@ static int test__pinned_group(struct evlist *evlist)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test__checkevent_exclusive_modifier(struct evlist *evlist)
|
||||||
|
{
|
||||||
|
struct evsel *evsel = evlist__first(evlist);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
|
||||||
|
TEST_ASSERT_VAL("wrong exclusive", evsel->core.attr.exclusive);
|
||||||
|
|
||||||
|
return test__checkevent_symbolic_name(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test__exclusive_group(struct evlist *evlist)
|
||||||
|
{
|
||||||
|
struct evsel *evsel, *leader;
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries);
|
||||||
|
|
||||||
|
/* cycles - group leader */
|
||||||
|
evsel = leader = evlist__first(evlist);
|
||||||
|
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
|
||||||
|
TEST_ASSERT_VAL("wrong config",
|
||||||
|
PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
|
||||||
|
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
|
||||||
|
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
|
||||||
|
TEST_ASSERT_VAL("wrong exclusive", evsel->core.attr.exclusive);
|
||||||
|
|
||||||
|
/* cache-misses - can not be pinned, but will go on with the leader */
|
||||||
|
evsel = evsel__next(evsel);
|
||||||
|
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
|
||||||
|
TEST_ASSERT_VAL("wrong config",
|
||||||
|
PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config);
|
||||||
|
TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive);
|
||||||
|
|
||||||
|
/* branch-misses - ditto */
|
||||||
|
evsel = evsel__next(evsel);
|
||||||
|
TEST_ASSERT_VAL("wrong config",
|
||||||
|
PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config);
|
||||||
|
TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
static int test__checkevent_breakpoint_len(struct evlist *evlist)
|
static int test__checkevent_breakpoint_len(struct evlist *evlist)
|
||||||
{
|
{
|
||||||
struct evsel *evsel = evlist__first(evlist);
|
struct evsel *evsel = evlist__first(evlist);
|
||||||
|
@ -1765,7 +1811,17 @@ static struct evlist_test test__events[] = {
|
||||||
.name = "cycles:k",
|
.name = "cycles:k",
|
||||||
.check = test__sym_event_dc,
|
.check = test__sym_event_dc,
|
||||||
.id = 55,
|
.id = 55,
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
.name = "instructions:uep",
|
||||||
|
.check = test__checkevent_exclusive_modifier,
|
||||||
|
.id = 56,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "{cycles,cache-misses,branch-misses}:e",
|
||||||
|
.check = test__exclusive_group,
|
||||||
|
.id = 57,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct evlist_test test__events_pmu[] = {
|
static struct evlist_test test__events_pmu[] = {
|
||||||
|
|
|
@ -1775,6 +1775,7 @@ struct event_modifier {
|
||||||
int sample_read;
|
int sample_read;
|
||||||
int pinned;
|
int pinned;
|
||||||
int weak;
|
int weak;
|
||||||
|
int exclusive;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int get_event_modifier(struct event_modifier *mod, char *str,
|
static int get_event_modifier(struct event_modifier *mod, char *str,
|
||||||
|
@ -1790,6 +1791,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
|
||||||
int precise_max = 0;
|
int precise_max = 0;
|
||||||
int sample_read = 0;
|
int sample_read = 0;
|
||||||
int pinned = evsel ? evsel->core.attr.pinned : 0;
|
int pinned = evsel ? evsel->core.attr.pinned : 0;
|
||||||
|
int exclusive = evsel ? evsel->core.attr.exclusive : 0;
|
||||||
|
|
||||||
int exclude = eu | ek | eh;
|
int exclude = eu | ek | eh;
|
||||||
int exclude_GH = evsel ? evsel->exclude_GH : 0;
|
int exclude_GH = evsel ? evsel->exclude_GH : 0;
|
||||||
|
@ -1833,6 +1835,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
|
||||||
sample_read = 1;
|
sample_read = 1;
|
||||||
} else if (*str == 'D') {
|
} else if (*str == 'D') {
|
||||||
pinned = 1;
|
pinned = 1;
|
||||||
|
} else if (*str == 'e') {
|
||||||
|
exclusive = 1;
|
||||||
} else if (*str == 'W') {
|
} else if (*str == 'W') {
|
||||||
weak = 1;
|
weak = 1;
|
||||||
} else
|
} else
|
||||||
|
@ -1866,6 +1870,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
|
||||||
mod->sample_read = sample_read;
|
mod->sample_read = sample_read;
|
||||||
mod->pinned = pinned;
|
mod->pinned = pinned;
|
||||||
mod->weak = weak;
|
mod->weak = weak;
|
||||||
|
mod->exclusive = exclusive;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1879,7 +1884,7 @@ static int check_modifier(char *str)
|
||||||
char *p = str;
|
char *p = str;
|
||||||
|
|
||||||
/* The sizeof includes 0 byte as well. */
|
/* The sizeof includes 0 byte as well. */
|
||||||
if (strlen(str) > (sizeof("ukhGHpppPSDIW") - 1))
|
if (strlen(str) > (sizeof("ukhGHpppPSDIWe") - 1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
|
@ -1921,8 +1926,10 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
|
||||||
evsel->precise_max = mod.precise_max;
|
evsel->precise_max = mod.precise_max;
|
||||||
evsel->weak_group = mod.weak;
|
evsel->weak_group = mod.weak;
|
||||||
|
|
||||||
if (evsel__is_group_leader(evsel))
|
if (evsel__is_group_leader(evsel)) {
|
||||||
evsel->core.attr.pinned = mod.pinned;
|
evsel->core.attr.pinned = mod.pinned;
|
||||||
|
evsel->core.attr.exclusive = mod.exclusive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -210,7 +210,7 @@ name_tag [\'][a-zA-Z_*?\[\]][a-zA-Z0-9_*?\-,\.\[\]:=]*[\']
|
||||||
name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
|
name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
|
||||||
drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
|
drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
|
||||||
/* If you add a modifier you need to update check_modifier() */
|
/* If you add a modifier you need to update check_modifier() */
|
||||||
modifier_event [ukhpPGHSDIW]+
|
modifier_event [ukhpPGHSDIWe]+
|
||||||
modifier_bp [rwx]{1,3}
|
modifier_bp [rwx]{1,3}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
Loading…
Reference in New Issue
Block a user