From nobody Sun Feb 8 17:42:57 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FA2730E831 for ; Fri, 6 Feb 2026 22:25:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770416720; cv=none; b=JaUXmDVGNb3jVtzEde9XA4dGi+pcwzFXIqsIINfYHT/kSZy/N1m26C6ZcWguLnLabTy7jbBuVUecCRiTKGCMWJYX8urKta6rqKP/oMi83R4f56/YTj4RIhbSvXEhih6Xk7EEmdD0ubqplGNCLUA7mfrczS+TvHOahs0PcEPGf4c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770416720; c=relaxed/simple; bh=m6NLJ4Vb0UEPbPzi83NUsogmV6qs5B+5r17ynjkDPV0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Sff1S3Rcg2h/vMs5TY1ZagpNOSG7NJDG/KgDfK8kkzSWA6z7T03qR7KAf1/hCjWs1fH44mZ9vnh1uvbETQ9XwYPso6/AcXP8VQKt3DMsBrLVFVY7E9rmF1JAUqXo124/SO1aOEQVgX0893hFUiEgB9BlcSHr+JrOAGSX6A12ziA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=u8bD5HVm; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="u8bD5HVm" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2b7ef896edcso18164989eec.0 for ; Fri, 06 Feb 2026 14:25:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770416719; x=1771021519; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=sOJSg9cHyId65pfgpXUFicdk0Bjz5b4dGSwLC1Zzl3E=; b=u8bD5HVmhQajjE3oyND73AFehXriXgPhGRIHDQc4ZTTodZmI//XbaibrhPgrEp3AU/ 6g1lYrczlz8yHu5Hyzck/fQGOD8Jum4rXana1qqhUUCpOdq6iDFR/QKIMtQ+DJZfiTQa l3/Tqg376wTkuVzcvKCpjicOua5I1Llo/hP8GT7sRxqBw9bz+nN0A5Li1bUfZrHEjLU3 PKI4xSvdA+jLyaxwgXicbqF8I3C8ZAi40XBkPBT+yUPf8awrF0F3HjHX+i+7cMkwFOvm Tp10YCUAXnbphPV3ZZCg3gPTFWFiAaEMqFniFwJj96KJy3b4hqpv21kOoqAYFzMOQicu Hysw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770416719; x=1771021519; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=sOJSg9cHyId65pfgpXUFicdk0Bjz5b4dGSwLC1Zzl3E=; b=LRKuFkotlhGqgAIK77UWUE9gZ6W6sppZd4SQDT2hTVxsFkJqH42zyFIOjkInFFxTJw 5wknmMytfbpgCBdQaXcaywdSSy+1xFZ3tYn0hklos1C3x6i215+rz53gNpz2gbQTtdQ2 Ij/BdRNaL53qTQeGZ9+7L7KvfjdwlCSHLzAgBjQff6SCtI92MW8cnCwE3Flic/8Y9Hp1 ofL+ZCRXg/ngRIFg6f46kiCc/ypc/LAAkyHUEu8e1Qq/qkzYmPusjy28mNdBW0JeMj1w 81vbjRsjjU51M0zdtsiV5nsoyLD5JmS93bgBt/DkzmTXFv/A79bOZsj7lDy367jYpWkE 8qsA== X-Forwarded-Encrypted: i=1; AJvYcCUZBsRql9iVudX1BR9RwdX0AZICpU9V+qUJxBKuYpXDyBiu4we3d2LiugbOqfdjsJyg5n1Gbez0eNbrK28=@vger.kernel.org X-Gm-Message-State: AOJu0YxeOOHPP80OcCA8xkfbFaVbc4H/vTE+0u0bo40wI1HmY2elgsGD tQq9Hp0sih7WhUS2+b1j2XrlfRNdEWSZDY7yIxMKcNFW8VIUaLf/axoguPRXoOTwxucjTgcKSMV c5CUqfcEOkw== X-Received: from dlbcq14.prod.google.com ([2002:a05:7022:248e:b0:121:7afb:490]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:6b88:b0:11e:f6ef:4988 with SMTP id a92af1059eb24-127041789f4mr1887886c88.36.1770416719225; Fri, 06 Feb 2026 14:25:19 -0800 (PST) Date: Fri, 6 Feb 2026 14:25:06 -0800 In-Reply-To: <20260206222509.982489-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260206222509.982489-1-irogers@google.com> X-Mailer: git-send-email 2.53.0.rc2.204.g2597b5adb4-goog Message-ID: <20260206222509.982489-4-irogers@google.com> Subject: [PATCH v8 3/6] perf evlist: Special map propagation for tool events that read on 1 CPU From: Ian Rogers To: acme@kernel.org Cc: adrian.hunter@intel.com, ak@linux.intel.com, alexander.shishkin@linux.intel.com, andres@anarazel.de, dapeng1.mi@linux.intel.com, irogers@google.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, linux@treblig.org, mingo@redhat.com, namhyung@kernel.org, peterz@infradead.org, thomas.falcon@intel.com, tmricht@linux.ibm.com, yang.lee@linux.alibaba.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Tool events like duration_time don't need a perf_cpu_map that contains all online CPUs. Having such a perf_cpu_map causes overheads when iterating between events for CPU affinity. During parsing mark events that just read on a single CPU map index as such, then during map propagation set up the evsel's CPUs and thereby the evlists accordingly. The setting cannot be done early in parsing as user CPUs are only fully known when evlist__create_maps is called. Signed-off-by: Ian Rogers --- tools/lib/perf/evlist.c | 36 ++++++++++++++++++++++--- tools/lib/perf/include/internal/evsel.h | 2 ++ tools/perf/util/parse-events.c | 1 + tools/perf/util/pmu.c | 11 ++++++++ tools/perf/util/pmu.h | 2 ++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c index 3ed023f4b190..1f210dadd666 100644 --- a/tools/lib/perf/evlist.c +++ b/tools/lib/perf/evlist.c @@ -101,6 +101,28 @@ static void __perf_evlist__propagate_maps(struct perf_= evlist *evlist, evsel->cpus =3D perf_cpu_map__get(evlist->user_requested_cpus); } =20 + /* + * Tool events may only read on the first CPU index to avoid double + * counting things like duration_time. Make the evsel->cpus contain just + * that single entry otherwise we may spend time changing affinity to + * CPUs that just have tool events, etc. + */ + if (evsel->reads_only_on_cpu_idx0 && perf_cpu_map__nr(evsel->cpus) > 0) { + struct perf_cpu_map *srcs[3] =3D { + evlist->all_cpus, + evlist->user_requested_cpus, + evsel->pmu_cpus, + }; + for (size_t i =3D 0; i < ARRAY_SIZE(srcs); i++) { + if (!srcs[i]) + continue; + + perf_cpu_map__put(evsel->cpus); + evsel->cpus =3D perf_cpu_map__new_int(perf_cpu_map__cpu(srcs[i], 0).cpu= ); + break; + } + } + /* Sanity check assert before the evsel is potentially removed. */ assert(!evsel->requires_cpu || !perf_cpu_map__has_any_cpu(evsel->cpus)); =20 @@ -133,16 +155,22 @@ static void __perf_evlist__propagate_maps(struct perf= _evlist *evlist, =20 static void perf_evlist__propagate_maps(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *n; - evlist->needs_map_propagation =3D true; =20 /* Clear the all_cpus set which will be merged into during propagation. */ perf_cpu_map__put(evlist->all_cpus); evlist->all_cpus =3D NULL; =20 - list_for_each_entry_safe(evsel, n, &evlist->entries, node) - __perf_evlist__propagate_maps(evlist, evsel); + /* 2 rounds so that reads_only_on_cpu_idx0 benefit from knowing the other= CPU maps. */ + for (int round =3D 0; round < 2; round++) { + struct perf_evsel *evsel, *n; + + list_for_each_entry_safe(evsel, n, &evlist->entries, node) { + if ((!evsel->reads_only_on_cpu_idx0 && round =3D=3D 0) || + (evsel->reads_only_on_cpu_idx0 && round =3D=3D 1)) + __perf_evlist__propagate_maps(evlist, evsel); + } + } } =20 void perf_evlist__add(struct perf_evlist *evlist, diff --git a/tools/lib/perf/include/internal/evsel.h b/tools/lib/perf/inclu= de/internal/evsel.h index fefe64ba5e26..b988034f1371 100644 --- a/tools/lib/perf/include/internal/evsel.h +++ b/tools/lib/perf/include/internal/evsel.h @@ -128,6 +128,8 @@ struct perf_evsel { bool requires_cpu; /** Is the PMU for the event a core one? Effects the handling of own_cpus= . */ bool is_pmu_core; + /** Does the evsel on read on the first CPU index such as tool time event= s? */ + bool reads_only_on_cpu_idx0; int idx; }; =20 diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index f631bf7a919f..b9efb296bba5 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -269,6 +269,7 @@ __add_event(struct list_head *list, int *idx, evsel->core.pmu_cpus =3D pmu_cpus; evsel->core.requires_cpu =3D pmu ? pmu->is_uncore : false; evsel->core.is_pmu_core =3D is_pmu_core; + evsel->core.reads_only_on_cpu_idx0 =3D perf_pmu__reads_only_on_cpu_idx0(a= ttr); evsel->pmu =3D pmu; evsel->alternate_hw_config =3D alternate_hw_config; evsel->first_wildcard_match =3D first_wildcard_match; diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index bb399a47d2b4..81ab74681c9b 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -2718,3 +2718,14 @@ const char *perf_pmu__name_from_config(struct perf_p= mu *pmu, u64 config) } return NULL; } + +bool perf_pmu__reads_only_on_cpu_idx0(const struct perf_event_attr *attr) +{ + enum tool_pmu_event event; + + if (attr->type !=3D PERF_PMU_TYPE_TOOL) + return false; + + event =3D (enum tool_pmu_event)attr->config; + return event !=3D TOOL_PMU__EVENT_USER_TIME && event !=3D TOOL_PMU__EVENT= _SYSTEM_TIME; +} diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 7ef90b54a149..41c21389f393 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -350,6 +350,8 @@ void perf_pmu__delete(struct perf_pmu *pmu); const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config); bool perf_pmu__is_fake(const struct perf_pmu *pmu); =20 +bool perf_pmu__reads_only_on_cpu_idx0(const struct perf_event_attr *attr); + static inline enum pmu_kind perf_pmu__kind(const struct perf_pmu *pmu) { __u32 type; --=20 2.53.0.rc2.204.g2597b5adb4-goog