Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tool_pmu: More accurately set the cpus for tool events

The user and system time events can record on different CPUs, but for
all other events a single CPU map of just CPU 0 makes sense. In
parse-events detect a tool PMU and then pass the perf_event_attr so
that the tool_pmu can return CPUs specific for the event. This avoids
a CPU map of all online CPUs being used for events like
duration_time. Avoiding this avoids the evlist CPUs containing CPUs
for which duration_time just gives 0. Minimizing the evlist CPUs can
remove unnecessary sched_setaffinity syscalls that delay metric
calculations.

Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
d8d8a0b3 d702c0f4

+27 -2
+7 -2
tools/perf/util/parse-events.c
··· 30 30 #include "util/event.h" 31 31 #include "util/bpf-filter.h" 32 32 #include "util/stat.h" 33 + #include "util/tool_pmu.h" 33 34 #include "util/util.h" 34 35 #include "tracepoint.h" 35 36 #include <api/fs/tracing_path.h> ··· 228 227 if (pmu) { 229 228 is_pmu_core = pmu->is_core; 230 229 pmu_cpus = perf_cpu_map__get(pmu->cpus); 231 - if (perf_cpu_map__is_empty(pmu_cpus)) 232 - pmu_cpus = cpu_map__online(); 230 + if (perf_cpu_map__is_empty(pmu_cpus)) { 231 + if (perf_pmu__is_tool(pmu)) 232 + pmu_cpus = tool_pmu__cpus(attr); 233 + else 234 + pmu_cpus = cpu_map__online(); 235 + } 233 236 } else { 234 237 is_pmu_core = (attr->type == PERF_TYPE_HARDWARE || 235 238 attr->type == PERF_TYPE_HW_CACHE);
+19
tools/perf/util/tool_pmu.c
··· 2 2 #include "cgroup.h" 3 3 #include "counts.h" 4 4 #include "cputopo.h" 5 + #include "debug.h" 5 6 #include "evsel.h" 6 7 #include "pmu.h" 7 8 #include "print-events.h" ··· 14 13 #include <api/fs/fs.h> 15 14 #include <api/io.h> 16 15 #include <internal/threadmap.h> 16 + #include <perf/cpumap.h> 17 17 #include <perf/threadmap.h> 18 18 #include <fcntl.h> 19 19 #include <strings.h> ··· 109 107 const char *evsel__tool_pmu_event_name(const struct evsel *evsel) 110 108 { 111 109 return tool_pmu__event_to_str(evsel->core.attr.config); 110 + } 111 + 112 + struct perf_cpu_map *tool_pmu__cpus(struct perf_event_attr *attr) 113 + { 114 + static struct perf_cpu_map *cpu0_map; 115 + enum tool_pmu_event event = (enum tool_pmu_event)attr->config; 116 + 117 + if (event <= TOOL_PMU__EVENT_NONE || event >= TOOL_PMU__EVENT_MAX) { 118 + pr_err("Invalid tool PMU event config %llx\n", attr->config); 119 + return NULL; 120 + } 121 + if (event == TOOL_PMU__EVENT_USER_TIME || event == TOOL_PMU__EVENT_SYSTEM_TIME) 122 + return cpu_map__online(); 123 + 124 + if (!cpu0_map) 125 + cpu0_map = perf_cpu_map__new_int(0); 126 + return perf_cpu_map__get(cpu0_map); 112 127 } 113 128 114 129 static bool read_until_char(struct io *io, char e)
+1
tools/perf/util/tool_pmu.h
··· 46 46 u64 tool_pmu__cpu_slots_per_cycle(void); 47 47 48 48 bool perf_pmu__is_tool(const struct perf_pmu *pmu); 49 + struct perf_cpu_map *tool_pmu__cpus(struct perf_event_attr *attr); 49 50 50 51 bool evsel__is_tool(const struct evsel *evsel); 51 52 enum tool_pmu_event evsel__tool_event(const struct evsel *evsel);