linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: Adrian Hunter <adrian.hunter@intel.com>,
	 Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	 Arnaldo Carvalho de Melo <acme@kernel.org>,
	Benjamin Gray <bgray@linux.ibm.com>,
	 Caleb Biggers <caleb.biggers@intel.com>,
	Edward Baker <edward.baker@intel.com>,
	 Ian Rogers <irogers@google.com>, Ingo Molnar <mingo@redhat.com>,
	 James Clark <james.clark@linaro.org>,
	Jing Zhang <renyu.zj@linux.alibaba.com>,
	 Jiri Olsa <jolsa@kernel.org>,
	John Garry <john.g.garry@oracle.com>, Leo Yan <leo.yan@arm.com>,
	 Namhyung Kim <namhyung@kernel.org>,
	Perry Taylor <perry.taylor@intel.com>,
	 Peter Zijlstra <peterz@infradead.org>,
	Samantha Alt <samantha.alt@intel.com>,
	 Sandipan Das <sandipan.das@amd.com>,
	Thomas Falcon <thomas.falcon@intel.com>,
	 Weilin Wang <weilin.wang@intel.com>, Xu Yang <xu.yang_2@nxp.com>,
	linux-kernel@vger.kernel.org,  linux-perf-users@vger.kernel.org
Subject: [PATCH v9 14/48] perf jevents: Add load event json to verify and allow fallbacks
Date: Tue,  2 Dec 2025 09:50:09 -0800	[thread overview]
Message-ID: <20251202175043.623597-15-irogers@google.com> (raw)
In-Reply-To: <20251202175043.623597-1-irogers@google.com>

Add a LoadEvents function that loads all event json files in a
directory. In the Event constructor ensure all events are defined in
the event json except for legacy events like "cycles". If the initial
event isn't found then legacy_event1 is used, and if that isn't found
legacy_event2 is used. This allows a single Event to have multiple
event names as models will often rename the same event over time. If
the event doesn't exist an exception is raised.

So that references to metrics can be added, add the MetricRef
class. This doesn't validate as an event name and so provides an
escape hatch for metrics to refer to each other.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Thomas Falcon <thomas.falcon@intel.com>
---
 tools/perf/pmu-events/Build            | 12 ++--
 tools/perf/pmu-events/amd_metrics.py   |  7 ++-
 tools/perf/pmu-events/arm64_metrics.py |  7 ++-
 tools/perf/pmu-events/intel_metrics.py |  7 ++-
 tools/perf/pmu-events/metric.py        | 83 +++++++++++++++++++++++++-
 5 files changed, 101 insertions(+), 15 deletions(-)

diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index c9df78ee003c..f7d67d03d055 100644
--- a/tools/perf/pmu-events/Build
+++ b/tools/perf/pmu-events/Build
@@ -53,11 +53,11 @@ ZEN_METRICGROUPS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metricgroups.json)
 
 $(ZEN_METRICS): pmu-events/amd_metrics.py $(GEN_METRIC_DEPS)
 	$(call rule_mkdir)
-	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call model_name,$@) arch > $@
+	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call model_name,$@) pmu-events/arch > $@
 
 $(ZEN_METRICGROUPS): pmu-events/amd_metrics.py $(GEN_METRIC_DEPS)
 	$(call rule_mkdir)
-	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) arch > $@
+	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@
 
 # Generate ARM Json
 ARMS = $(shell ls -d pmu-events/arch/arm64/arm/*)
@@ -66,11 +66,11 @@ ARM_METRICGROUPS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metricgroups.json)
 
 $(ARM_METRICS): pmu-events/arm64_metrics.py $(GEN_METRIC_DEPS)
 	$(call rule_mkdir)
-	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call vendor_name,$@) $(call model_name,$@) arch > $@
+	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call vendor_name,$@) $(call model_name,$@) pmu-events/arch > $@
 
 $(ARM_METRICGROUPS): pmu-events/arm64_metrics.py $(GEN_METRIC_DEPS)
 	$(call rule_mkdir)
-	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call vendor_name,$@) $(call model_name,$@) arch > $@
+	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call vendor_name,$@) $(call model_name,$@) pmu-events/arch > $@
 
 # Generate Intel Json
 INTELS = $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv)
@@ -79,11 +79,11 @@ INTEL_METRICGROUPS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metricgroups.json
 
 $(INTEL_METRICS): pmu-events/intel_metrics.py $(GEN_METRIC_DEPS)
 	$(call rule_mkdir)
-	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call model_name,$@) arch > $@
+	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call model_name,$@) pmu-events/arch > $@
 
 $(INTEL_METRICGROUPS): pmu-events/intel_metrics.py $(GEN_METRIC_DEPS)
 	$(call rule_mkdir)
-	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) arch > $@
+	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@
 
 GEN_JSON = $(patsubst %,$(OUTPUT)%,$(JSON)) \
             $(LEGACY_CACHE_JSON) \
diff --git a/tools/perf/pmu-events/amd_metrics.py b/tools/perf/pmu-events/amd_metrics.py
index 5f44687d8d20..bc91d9c120fa 100755
--- a/tools/perf/pmu-events/amd_metrics.py
+++ b/tools/perf/pmu-events/amd_metrics.py
@@ -2,8 +2,8 @@
 # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 import argparse
 import os
-from metric import (
-    JsonEncodeMetric, JsonEncodeMetricGroupDescriptions, MetricGroup)
+from metric import (JsonEncodeMetric, JsonEncodeMetricGroupDescriptions, LoadEvents,
+                    MetricGroup)
 
 # Global command line arguments.
 _args = None
@@ -30,6 +30,9 @@ def main() -> None:
     )
     _args = parser.parse_args()
 
+    directory = f"{_args.events_path}/x86/{_args.model}/"
+    LoadEvents(directory)
+
     all_metrics = MetricGroup("", [])
 
     if _args.metricgroups:
diff --git a/tools/perf/pmu-events/arm64_metrics.py b/tools/perf/pmu-events/arm64_metrics.py
index 204b3b08c680..ac717ca3513a 100755
--- a/tools/perf/pmu-events/arm64_metrics.py
+++ b/tools/perf/pmu-events/arm64_metrics.py
@@ -2,8 +2,8 @@
 # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 import argparse
 import os
-from metric import (
-    JsonEncodeMetric, JsonEncodeMetricGroupDescriptions, MetricGroup)
+from metric import (JsonEncodeMetric, JsonEncodeMetricGroupDescriptions, LoadEvents,
+                    MetricGroup)
 
 # Global command line arguments.
 _args = None
@@ -31,6 +31,9 @@ def main() -> None:
     )
     _args = parser.parse_args()
 
+    directory = f"{_args.events_path}/arm64/{_args.vendor}/{_args.model}/"
+    LoadEvents(directory)
+
     all_metrics = MetricGroup("", [])
 
     if _args.metricgroups:
diff --git a/tools/perf/pmu-events/intel_metrics.py b/tools/perf/pmu-events/intel_metrics.py
index 65ada006d05a..b287ef115193 100755
--- a/tools/perf/pmu-events/intel_metrics.py
+++ b/tools/perf/pmu-events/intel_metrics.py
@@ -2,8 +2,8 @@
 # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 import argparse
 import os
-from metric import (
-    JsonEncodeMetric, JsonEncodeMetricGroupDescriptions, MetricGroup)
+from metric import (JsonEncodeMetric, JsonEncodeMetricGroupDescriptions, LoadEvents,
+                    MetricGroup)
 
 # Global command line arguments.
 _args = None
@@ -30,6 +30,9 @@ def main() -> None:
     )
     _args = parser.parse_args()
 
+    directory = f"{_args.events_path}/x86/{_args.model}/"
+    LoadEvents(directory)
+
     all_metrics = MetricGroup("", [])
 
     if _args.metricgroups:
diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py
index dd8fd06940e6..e33e163b2815 100644
--- a/tools/perf/pmu-events/metric.py
+++ b/tools/perf/pmu-events/metric.py
@@ -3,10 +3,56 @@
 import ast
 import decimal
 import json
+import os
 import re
 from enum import Enum
 from typing import Dict, List, Optional, Set, Tuple, Union
 
+all_events = set()
+
+def LoadEvents(directory: str) -> None:
+  """Populate a global set of all known events for the purpose of validating Event names"""
+  global all_events
+  all_events = {
+      "context\\-switches",
+      "cpu\\-cycles",
+      "cycles",
+      "duration_time",
+      "instructions",
+      "l2_itlb_misses",
+  }
+  for file in os.listdir(os.fsencode(directory)):
+    filename = os.fsdecode(file)
+    if filename.endswith(".json"):
+      try:
+        for x in json.load(open(f"{directory}/{filename}")):
+          if "EventName" in x:
+            all_events.add(x["EventName"])
+          elif "ArchStdEvent" in x:
+            all_events.add(x["ArchStdEvent"])
+      except json.decoder.JSONDecodeError:
+        # The generated directory may be the same as the input, which
+        # causes partial json files. Ignore errors.
+        pass
+
+
+def CheckEvent(name: str) -> bool:
+  """Check the event name exists in the set of all loaded events"""
+  global all_events
+  if len(all_events) == 0:
+    # No events loaded so assume any event is good.
+    return True
+
+  if ':' in name:
+    # Remove trailing modifier.
+    name = name[:name.find(':')]
+  elif '/' in name:
+    # Name could begin with a PMU or an event, for now assume it is good.
+    return True
+
+  return name in all_events
+
+
 class MetricConstraint(Enum):
   GROUPED_EVENTS = 0
   NO_GROUP_EVENTS = 1
@@ -317,9 +363,18 @@ def _FixEscapes(s: str) -> str:
 class Event(Expression):
   """An event in an expression."""
 
-  def __init__(self, name: str, legacy_name: str = ''):
-    self.name = _FixEscapes(name)
-    self.legacy_name = _FixEscapes(legacy_name)
+  def __init__(self, *args: str):
+    error = ""
+    for name in args:
+      if CheckEvent(name):
+        self.name = _FixEscapes(name)
+        return
+      if error:
+        error += " or " + name
+      else:
+        error = name
+    global all_events
+    raise Exception(f"No event {error} in:\n{all_events}")
 
   def ToPerfJson(self):
     result = re.sub('/', '@', self.name)
@@ -338,6 +393,28 @@ class Event(Expression):
     return self
 
 
+class MetricRef(Expression):
+  """A metric reference in an expression."""
+
+  def __init__(self, name: str):
+    self.name = _FixEscapes(name)
+
+  def ToPerfJson(self):
+    return self.name
+
+  def ToPython(self):
+    return f'MetricRef(r"{self.name}")'
+
+  def Simplify(self) -> Expression:
+    return self
+
+  def Equals(self, other: Expression) -> bool:
+    return isinstance(other, MetricRef) and self.name == other.name
+
+  def Substitute(self, name: str, expression: Expression) -> Expression:
+    return self
+
+
 class Constant(Expression):
   """A constant within the expression tree."""
 
-- 
2.52.0.158.g65b55ccf14-goog


  parent reply	other threads:[~2025-12-02 17:52 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-02 17:49 [PATCH v9 00/48] AMD, ARM, Intel metric generation with Python Ian Rogers
2025-12-02 17:49 ` [PATCH v9 01/48] perf python: Correct copying of metric_leader in an evsel Ian Rogers
2025-12-02 17:49 ` [PATCH v9 02/48] perf ilist: Be tolerant of reading a metric on the wrong CPU Ian Rogers
2025-12-02 17:49 ` [PATCH v9 03/48] perf jevents: Allow multiple metricgroups.json files Ian Rogers
2025-12-02 17:49 ` [PATCH v9 04/48] perf jevents: Update metric constraint support Ian Rogers
2025-12-02 17:50 ` [PATCH v9 05/48] perf jevents: Add descriptions to metricgroup abstraction Ian Rogers
2025-12-02 17:50 ` [PATCH v9 06/48] perf jevents: Allow metric groups not to be named Ian Rogers
2025-12-02 17:50 ` [PATCH v9 07/48] perf jevents: Support parsing negative exponents Ian Rogers
2025-12-02 17:50 ` [PATCH v9 08/48] perf jevents: Term list fix in event parsing Ian Rogers
2025-12-02 17:50 ` [PATCH v9 09/48] perf jevents: Add threshold expressions to Metric Ian Rogers
2025-12-02 17:50 ` [PATCH v9 10/48] perf jevents: Move json encoding to its own functions Ian Rogers
2025-12-02 17:50 ` [PATCH v9 11/48] perf jevents: Drop duplicate pending metrics Ian Rogers
2025-12-02 17:50 ` [PATCH v9 12/48] perf jevents: Skip optional metrics in metric group list Ian Rogers
2025-12-02 17:50 ` [PATCH v9 13/48] perf jevents: Build support for generating metrics from python Ian Rogers
2025-12-02 17:50 ` Ian Rogers [this message]
2025-12-02 17:50 ` [PATCH v9 15/48] perf jevents: Add RAPL event metric for AMD zen models Ian Rogers
2025-12-02 17:50 ` [PATCH v9 16/48] perf jevents: Add idle " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 17/48] perf jevents: Add upc metric for uops per cycle for AMD Ian Rogers
2025-12-08  9:46   ` Sandipan Das
2025-12-02 17:50 ` [PATCH v9 18/48] perf jevents: Add br metric group for branch statistics on AMD Ian Rogers
2025-12-08 12:42   ` Sandipan Das
2025-12-02 17:50 ` [PATCH v9 19/48] perf jevents: Add itlb metric group for AMD Ian Rogers
2025-12-02 17:50 ` [PATCH v9 20/48] perf jevents: Add dtlb " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 21/48] perf jevents: Add uncore l3 " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 22/48] perf jevents: Add load store breakdown metrics ldst " Ian Rogers
2025-12-08  9:21   ` Sandipan Das
2025-12-02 17:50 ` [PATCH v9 23/48] perf jevents: Add context switch metrics " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 24/48] perf jevents: Add RAPL metrics for all Intel models Ian Rogers
2025-12-02 17:50 ` [PATCH v9 25/48] perf jevents: Add idle metric for " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 26/48] perf jevents: Add CheckPmu to see if a PMU is in loaded json events Ian Rogers
2025-12-02 17:50 ` [PATCH v9 27/48] perf jevents: Add smi metric group for Intel models Ian Rogers
2025-12-02 17:50 ` [PATCH v9 28/48] perf jevents: Mark metrics with experimental events as experimental Ian Rogers
2025-12-02 17:50 ` [PATCH v9 29/48] perf jevents: Add tsx metric group for Intel models Ian Rogers
2025-12-02 17:50 ` [PATCH v9 30/48] perf jevents: Add br metric group for branch statistics on Intel Ian Rogers
2025-12-02 17:50 ` [PATCH v9 31/48] perf jevents: Add software prefetch (swpf) metric group for Intel Ian Rogers
2025-12-02 17:50 ` [PATCH v9 32/48] perf jevents: Add ports metric group giving utilization on Intel Ian Rogers
2025-12-02 17:50 ` [PATCH v9 33/48] perf jevents: Add L2 metrics for Intel Ian Rogers
2025-12-02 17:50 ` [PATCH v9 34/48] perf jevents: Add load store breakdown metrics ldst " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 35/48] perf jevents: Add ILP metrics " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 36/48] perf jevents: Add context switch " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 37/48] perf jevents: Add FPU " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 38/48] perf jevents: Add Miss Level Parallelism (MLP) metric " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 39/48] perf jevents: Add mem_bw " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 40/48] perf jevents: Add local/remote "mem" breakdown metrics " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 41/48] perf jevents: Add dir " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 42/48] perf jevents: Add C-State metrics from the PCU PMU " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 43/48] perf jevents: Add local/remote miss latency metrics " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 44/48] perf jevents: Add upi_bw metric " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 45/48] perf jevents: Add mesh bandwidth saturation " Ian Rogers
2025-12-02 17:50 ` [PATCH v9 46/48] perf jevents: Add collection of topdown like metrics for arm64 Ian Rogers
2025-12-09 11:31   ` James Clark
2025-12-09 21:23     ` Ian Rogers
2025-12-02 17:50 ` [PATCH v9 47/48] perf jevents: Add cycles breakdown metric for arm64/AMD/Intel Ian Rogers
2025-12-02 17:50 ` [PATCH v9 48/48] perf jevents: Validate that all names given an Event Ian Rogers
2025-12-03 17:59 ` [PATCH v9 00/48] AMD, ARM, Intel metric generation with Python Namhyung Kim

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251202175043.623597-15-irogers@google.com \
    --to=irogers@google.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=bgray@linux.ibm.com \
    --cc=caleb.biggers@intel.com \
    --cc=edward.baker@intel.com \
    --cc=james.clark@linaro.org \
    --cc=john.g.garry@oracle.com \
    --cc=jolsa@kernel.org \
    --cc=leo.yan@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=perry.taylor@intel.com \
    --cc=peterz@infradead.org \
    --cc=renyu.zj@linux.alibaba.com \
    --cc=samantha.alt@intel.com \
    --cc=sandipan.das@amd.com \
    --cc=thomas.falcon@intel.com \
    --cc=weilin.wang@intel.com \
    --cc=xu.yang_2@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).