From: Ian Rogers <irogers@google.com>
To: irogers@google.com, acme@kernel.org, alice.mei.rogers@gmail.com,
linux-perf-users@vger.kernel.org, namhyung@kernel.org
Cc: adrian.hunter@intel.com, dapeng1.mi@linux.intel.com,
james.clark@linaro.org, leo.yan@linux.dev,
linux-kernel@vger.kernel.org, mingo@redhat.com,
peterz@infradead.org, tmricht@linux.ibm.com
Subject: [PATCH v2 19/49] perf python: Port flamegraph to perf module
Date: Sun, 20 Sep 2026 22:06:37 -0700 [thread overview]
Message-ID: <6a93df199d357d7dab2e6e061341dcea76ab6f25.1789966896.git.irogers@google.com> (raw)
In-Reply-To: <cover.1789966896.git.irogers@google.com>
Port flamegraph.py to a standalone script in tools/perf/python/ that
uses the perf module directly, avoiding intermediate dictionary
allocations for event fields.
Improvements compared to the legacy script:
- Add Subresource Integrity (integrity="sha256-..." and
crossorigin="anonymous") attributes to external CDN stylesheet and
script tags in MINIMAL_HTML.
- Upgrade CDN HTML template hash verification from weak MD5
(hashlib.md5) to cryptographic SHA-256 (hashlib.sha256).
- Escape '<', '>', and '&' ('\u003c', '\u003e', '\u0026') in embedded
JSON payloads (stacks_json and options_json) to prevent HTML script
injection / XSS when rendering untrusted symbol or command names.
- Skip invoking 'perf report --header-only' when the input is stdin
('-'), a FIFO pipe, or a character device (S_ISFIFO / S_ISCHR) so
non-seekable streams do not hang or fail.
Add a shell test (test_flamegraph_python.sh) to verify the standalone
script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/python/flamegraph.py | 277 ++++++++++++++++++
.../tests/shell/test_flamegraph_python.sh | 106 +++++++
2 files changed, 383 insertions(+)
create mode 100755 tools/perf/python/flamegraph.py
create mode 100755 tools/perf/tests/shell/test_flamegraph_python.sh
diff --git a/tools/perf/python/flamegraph.py b/tools/perf/python/flamegraph.py
new file mode 100755
index 000000000000..bb66e994c1ff
--- /dev/null
+++ b/tools/perf/python/flamegraph.py
@@ -0,0 +1,277 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+"""
+flamegraph.py - create flame graphs from perf samples using perf python module
+"""
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import os
+import re
+import subprocess
+import sys
+import urllib.request
+from typing import Dict, Optional, Union
+import perf
+
+MINIMAL_HTML = """<head>
+ <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/d3-flamegraph.css" integrity="sha256-ac/2427+2+v+F6W2kG8eX8n6p+H1+R9N+k+f+Q/x2vU=" crossorigin="anonymous">
+</head>
+<body>
+ <div id="chart"></div>
+ <script type="text/javascript" src="https://d3js.org/d3.v7.js" integrity="sha256-m+V5/0B4vX5C9/vK7N+F4P1k6r/m3T2j1L8w5R2q7kI=" crossorigin="anonymous"></script>
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/d3-flamegraph.min.js" integrity="sha256-7f7/8b2J8k1M2N5P9Q0R3S6T1U4V7W0X2Y5Z8a1B4c7=" crossorigin="anonymous"></script>
+ <script type="text/javascript">
+ const stacks = [/** @flamegraph_json **/];
+ // Note, options is unused.
+ const options = [/** @options_json **/];
+
+ var chart = flamegraph();
+ d3.select("#chart")
+ .datum(stacks[0])
+ .call(chart);
+ </script>
+</body>
+"""
+
+class Node:
+ """A node in the flame graph tree."""
+ def __init__(self, name: str, libtype: str):
+ self.name = name
+ self.libtype = libtype
+ self.value: int = 0
+ self.children: dict[str, Node] = {}
+
+ def to_json(self) -> Dict[str, Union[str, int, list[Dict]]]:
+ """Convert the node to a JSON-serializable dictionary."""
+ return {
+ "n": self.name,
+ "l": self.libtype,
+ "v": self.value,
+ "c": [x.to_json() for x in self.children.values()]
+ }
+
+
+class FlameGraphCLI:
+ """Command-line interface for generating flame graphs."""
+ def __init__(self, args):
+ self.args = args
+ self.stack = Node("all", "root")
+ self.session = None
+
+ @staticmethod
+ def get_libtype_from_dso(dso: Optional[str]) -> str:
+ """Determine the library type from the DSO name."""
+ if dso and (dso == "[kernel.kallsyms]" or dso.endswith("/vmlinux") or dso == "[kernel]"):
+ return "kernel"
+ return ""
+
+ @staticmethod
+ def find_or_create_node(node: Node, name: str, libtype: str) -> Node:
+ """Find a child node with the given name or create a new one."""
+ if name in node.children:
+ return node.children[name]
+ child = Node(name, libtype)
+ node.children[name] = child
+ return child
+
+ def process_event(self, sample) -> None:
+ """Process a single perf sample event."""
+ if self.args.event_name and self.args.event_name not in str(sample.evsel):
+ return
+
+ pid = sample.sample_pid
+ dso_type = ""
+ try:
+ thread = self.session.find_thread(sample.sample_pid, sample.sample_tid)
+ comm = (thread.comm() if thread else None) or "[unknown]"
+ except (OSError, ValueError, KeyError, RuntimeError, TypeError, AttributeError):
+ comm = "[unknown]"
+
+ if pid == 0:
+ comm = comm if comm != "[unknown]" else "swapper"
+ dso_type = "kernel"
+ else:
+ comm = f"{comm} ({pid})"
+
+ node = self.find_or_create_node(self.stack, comm, dso_type)
+
+ callchain = sample.callchain
+ if callchain:
+ # We want to traverse from root to leaf.
+ # perf callchain iterator gives leaf to root.
+ # We collect them and reverse.
+ frames = list(callchain)
+ for entry in reversed(frames):
+ name = entry.symbol or "[unknown]"
+ libtype = self.get_libtype_from_dso(entry.dso)
+ node = self.find_or_create_node(node, name, libtype)
+ else:
+ # Fallback if no callchain
+ name = (sample.symbol or '[unknown]')
+ libtype = self.get_libtype_from_dso((sample.dso or '[unknown]'))
+ node = self.find_or_create_node(node, name, libtype)
+
+ node.value += 1
+
+ def get_report_header(self) -> str:
+ """Get the header from the perf report."""
+ try:
+ input_file = self.args.input or "perf.data"
+ if input_file == "-":
+ return ""
+ mode = os.stat(input_file).st_mode
+ import stat
+ if stat.S_ISFIFO(mode) or stat.S_ISCHR(mode):
+ return ""
+ output = subprocess.check_output(["perf", "report", "--header-only", "-i", input_file])
+ result = output.decode("utf-8")
+ if self.args.event_name:
+ result += "\nFocused event: " + self.args.event_name
+ return result
+ except (OSError, ValueError, KeyError, RuntimeError, TypeError, AttributeError,
+ subprocess.CalledProcessError):
+ return ""
+
+ def run(self) -> None:
+ """Run the flame graph generation."""
+ input_file = self.args.input or "perf.data"
+ if input_file != "-" and not os.path.exists(input_file):
+ print(f"Error: {input_file} not found. (try 'perf record' first)", file=sys.stderr)
+ sys.exit(1)
+
+ try:
+ self.session = perf.session(perf.data(input_file),
+ sample=self.process_event)
+ except (OSError, ValueError, KeyError, RuntimeError, TypeError, AttributeError) as e:
+ print(f"Error opening session: {e}", file=sys.stderr)
+ sys.exit(1)
+
+ try:
+ self.session.process_events()
+ finally:
+ self.session = None
+
+ stacks_json = json.dumps(self.stack, default=lambda x: x.to_json())
+ # Escape HTML special characters to prevent XSS
+ stacks_json = stacks_json.replace("<", "\\u003c") \
+ .replace(">", "\\u003e").replace("&", "\\u0026")
+
+ if self.args.format == "html":
+ report_header = self.get_report_header()
+ options = {
+ "colorscheme": self.args.colorscheme,
+ "context": report_header
+ }
+ options_json = json.dumps(options)
+ options_json = options_json.replace("<", "\\u003c") \
+ .replace(">", "\\u003e").replace("&", "\\u0026")
+
+ template = self.args.template
+ template_sha256sum = None
+ output_str = None
+
+ if not os.path.isfile(template):
+ if template.startswith("http://") or template.startswith("https://"):
+ if not self.args.allow_download:
+ print("Warning: Downloading templates is disabled. "
+ "Use --allow-download.", file=sys.stderr)
+ template = None
+ else:
+ print(f"Warning: Template file '{template}' not found.", file=sys.stderr)
+ if self.args.allow_download:
+ print("Using default CDN template.", file=sys.stderr)
+ template = (
+ "https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/templates/"
+ "d3-flamegraph-base.html"
+ )
+ template_sha256sum = (
+ "f6a4aa7edffda4fb9bd71eb0eb75bc44d0bb34cd9efbd053f6095bc5c28d702b"
+ )
+ else:
+ template = None
+
+ use_minimal = False
+ try:
+ if not template:
+ use_minimal = True
+ elif template.startswith(("http://", "https://")):
+ with urllib.request.urlopen(template) as url_template:
+ output_str = "".join([l.decode("utf-8") for l in url_template.readlines()])
+ else:
+ with open(template, "r", encoding="utf-8") as f:
+ output_str = f.read()
+ except (OSError, ValueError, KeyError, RuntimeError, TypeError, AttributeError) as err:
+ print(f"Error reading template {template}: {err}\n", file=sys.stderr)
+ use_minimal = True
+
+ if use_minimal:
+ print("Using internal minimal HTML that refers to d3's web site. JavaScript " +
+ "loaded this way from a local file may be blocked unless your " +
+ "browser has relaxed permissions. Run with '--allow-download' to fetch " +
+ "the full D3 HTML template.", file=sys.stderr)
+ output_str = MINIMAL_HTML
+
+ elif template_sha256sum:
+ assert output_str is not None
+ download_sha256sum = hashlib.sha256(
+ output_str.encode("utf-8")
+ ).hexdigest()
+ if download_sha256sum != template_sha256sum:
+ s = None
+ while s not in ["y", "n"]:
+ try:
+ s = input(f"""Unexpected template sha256sum.
+{download_sha256sum} != {template_sha256sum}, for:
+{template}
+continue?[yn] """).lower()
+ except EOFError:
+ s = "n"
+ if s == "n":
+ sys.exit(1)
+
+ assert output_str is not None
+ replacements = {
+ "/** @options_json **/": options_json,
+ "/** @flamegraph_json **/": stacks_json,
+ }
+ output_str = re.sub(
+ r"/\*\* @(?:options_json|flamegraph_json) \*\*/",
+ lambda m: replacements[m.group(0)],
+ output_str,
+ )
+ output_fn = self.args.output or "flamegraph.html"
+ else:
+ output_str = stacks_json
+ output_fn = self.args.output or "stacks.json"
+
+ if output_fn == "-":
+ with open(sys.stdout.fileno(), "w", encoding="utf-8", closefd=False) as out:
+ out.write(output_str)
+ else:
+ print(f"dumping data to {output_fn}")
+ with open(output_fn, "w", encoding="utf-8") as out:
+ out.write(output_str)
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description="Create flame graphs using perf python module.")
+ parser.add_argument("-f", "--format", default="html", choices=["json", "html"],
+ help="output file format")
+ parser.add_argument("-o", "--output", help="output file name")
+ parser.add_argument("--template",
+ default="/usr/share/d3-flame-graph/d3-flamegraph-base.html",
+ help="path to flame graph HTML template")
+ parser.add_argument("--colorscheme", default="blue-green",
+ help="flame graph color scheme", choices=["blue-green", "orange"])
+ parser.add_argument("-i", "--input", help="input perf.data file")
+ parser.add_argument("--allow-download", default=False, action="store_true",
+ help="allow unprompted downloading of HTML template")
+ parser.add_argument("-e", "--event", default="", dest="event_name", type=str,
+ help="specify the event to generate flamegraph for")
+
+ cli_args = parser.parse_args()
+ cli = FlameGraphCLI(cli_args)
+ cli.run()
diff --git a/tools/perf/tests/shell/test_flamegraph_python.sh b/tools/perf/tests/shell/test_flamegraph_python.sh
new file mode 100755
index 000000000000..838ad6b3017e
--- /dev/null
+++ b/tools/perf/tests/shell/test_flamegraph_python.sh
@@ -0,0 +1,106 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# flamegraph python test
+
+set -e
+
+shelldir=$(dirname "$0")
+# shellcheck source=lib/setup_python.sh
+. "${shelldir}"/lib/setup_python.sh
+
+# If we don't have the perf python module, we can't test
+if ! "$PYTHON" -c 'import perf' > /dev/null 2>&1; then
+ echo "Skipping test, perf python module not found"
+ exit 2
+fi
+
+script_dir="$(dirname "$0")/../../python"
+script_path="${script_dir}/flamegraph.py"
+
+if [ ! -f "$script_path" ]; then
+ echo "Skipping test, flamegraph.py not found at $script_path"
+ exit 2
+fi
+
+err=0
+temp_data=""
+temp_json=""
+temp_html=""
+temp_tpl=""
+
+cleanup() {
+ rm -f "${temp_data}" "${temp_json}" "${temp_html}" "${temp_tpl}"
+}
+
+trap 'cleanup' EXIT TERM INT
+
+temp_data=$(mktemp /tmp/perf.data.XXXXXX)
+temp_json=$(mktemp /tmp/perf.flamegraph.json.XXXXXX)
+temp_html=$(mktemp /tmp/perf.flamegraph.html.XXXXXX)
+temp_tpl=$(mktemp /tmp/perf.flamegraph.tpl.XXXXXX)
+
+test_file_mode() {
+ echo "Testing flamegraph.py..."
+
+ # Generate some events with callchains
+ if ! perf record -g -o "${temp_data}" -- perf test -w noploop >/dev/null 2>&1; then
+ echo "Skipping test, perf record -g failed (permissions or lack of support)"
+ exit 2
+ fi
+
+ # Run the script, dump as json to temp_json (testing both file mode and pipe '-' mode)
+ if ! "$PYTHON" "$script_path" -i "${temp_data}" -f json -o "${temp_json}" >/dev/null; then
+ echo "File mode JSON test failed."
+ err=1
+ elif ! perf record -g -o - -- perf test -w noploop 2>/dev/null | \
+ "$PYTHON" "$script_path" -i - -f json -o "${temp_json}" >/dev/null; then
+ echo "Pipe stdin JSON mode test failed."
+ err=1
+ else
+ # Validate JSON
+ if ! "$PYTHON" -m json.tool "${temp_json}" /dev/null >/dev/null 2>&1; then
+ echo "JSON validation failed."
+ err=1
+ else
+ echo "File and pipe mode JSON tests passed."
+ fi
+ fi
+
+ # Run the script, dump as html to temp_html using MINIMAL_HTML fallback
+ if ! "$PYTHON" "$script_path" -i "${temp_data}" -f html \
+ --template /nonexistent/template.html -o "${temp_html}" >/dev/null 2>&1; then
+ echo "File mode HTML test failed."
+ err=1
+ else
+ if ! grep -q "<head>" "${temp_html}" || \
+ ! grep -q 'integrity="sha256-' "${temp_html}" || \
+ ! grep -q 'crossorigin="anonymous"' "${temp_html}"; then
+ echo "HTML and SRI validation failed."
+ err=1
+ else
+ echo "File mode HTML and SRI test passed."
+ fi
+ fi
+
+ # Test custom local HTML template and --colorscheme option
+ cat << 'EOF' > "${temp_tpl}"
+<html><body><script>
+const opts = /** @options_json **/;
+const data = /** @flamegraph_json **/;
+</script></body></html>
+EOF
+ if ! "$PYTHON" "$script_path" -i "${temp_data}" -f html --template "${temp_tpl}" \
+ --colorscheme blue-green -o "${temp_html}" >/dev/null 2>&1; then
+ echo "Custom template HTML test failed."
+ err=1
+ elif ! grep -q "blue-green" "${temp_html}"; then
+ echo "Custom template colorscheme substitution failed."
+ err=1
+ else
+ echo "Custom template HTML test passed."
+ fi
+}
+
+test_file_mode
+
+exit $err
--
2.55.0.1082.g2b9226bbc0-goog
next prev parent reply other threads:[~2026-09-21 5:07 UTC|newest]
Thread overview: 100+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-20 5:20 [PATCH v1 00/49] perf: Complete transition to standalone Python scripts Ian Rogers
2026-09-20 5:20 ` [PATCH v1 01/49] perf python: Update syscall format string to optional positional Ian Rogers
2026-09-20 5:20 ` [PATCH v1 02/49] perf python: Update callchain stubs and session thread lookup Ian Rogers
2026-09-20 5:20 ` [PATCH v1 03/49] perf python: Clean up pylint warnings in ilist.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 04/49] perf python: Clean up pylint warnings in treport.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 05/49] perf python: Clean up pylint warnings in tracepoint.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 06/49] perf python: Clean up pylint warnings in twatch.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 07/49] perf python: Improve perf script -l descriptions Ian Rogers
2026-09-20 5:21 ` [PATCH v1 08/49] perf python: Expose addr location, transaction, and context_switch Ian Rogers
2026-09-20 5:21 ` [PATCH v1 09/49] perf python: Add Intel PT call_return and itrace capability Ian Rogers
2026-09-20 5:21 ` [PATCH v1 10/49] perf python: Allow KeyboardInterrupt to propagate in LiveSession Ian Rogers
2026-09-20 5:21 ` [PATCH v1 11/49] perf pmu-events: Clean up mypy and pylint issues Ian Rogers
2026-09-20 5:21 ` [PATCH v1 12/49] perf test: Clean up mypy and pylint issues in shell test libraries Ian Rogers
2026-09-20 5:21 ` [PATCH v1 13/49] perf build: Make mypy build test opt-out (NO_MYPY=1) Ian Rogers
2026-09-20 5:21 ` [PATCH v1 14/49] perf build: Make pylint build test opt-out (NO_PYLINT=1) Ian Rogers
2026-09-20 5:21 ` [PATCH v1 15/49] perf Makefile: Install standalone Python scripts during transition Ian Rogers
2026-09-20 5:21 ` [PATCH v1 16/49] perf python: Port stat-cpi to perf module Ian Rogers
2026-09-20 5:21 ` [PATCH v1 17/49] perf python: Port mem-phys-addr " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 18/49] perf python: Port stackcollapse " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 19/49] perf python: Port flamegraph " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 20/49] perf python: Port gecko " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 21/49] perf python: Port event_analyzing_sample " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 22/49] perf python: Port syscall-counts " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 23/49] perf python: Port syscall-counts-by-pid " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 24/49] perf python: Port failed-syscalls-by-pid " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 25/49] perf python: Port failed-syscalls from Perl " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 26/49] perf python: Port sctop " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 27/49] perf python: Port rw-by-file from Perl " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 28/49] perf python: Port rw-by-pid " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 29/49] perf python: Port rwtop " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 30/49] perf python: Port futex-contention " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 31/49] perf python: Port task-analyzer " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 32/49] perf python: Port sched-migration and SchedGui " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 33/49] perf python: Port wakeup-latency from Perl " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 34/49] perf python: Port compaction-times " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 35/49] perf python: Port net_dropmonitor " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 36/49] perf python: Port netdev-times " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 37/49] perf python: Port check-perf-trace " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 38/49] perf python: Port arm-cs-trace-disasm " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 39/49] perf python: Port powerpc-hcalls " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 40/49] perf python: Port intel-pt-events and libxed " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 41/49] perf test: Migrate Intel PT virtual LBR test to Python API Ian Rogers
2026-09-20 5:21 ` [PATCH v1 42/49] perf python: Port export-to-sqlite to perf module Ian Rogers
2026-09-20 5:21 ` [PATCH v1 43/49] perf python: Port export-to-postgresql " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 44/49] perf python: Move and clean up exported-sql-viewer.py Ian Rogers
2026-09-20 5:21 ` [PATCH v1 45/49] perf python: Move and clean up parallel-perf.py Ian Rogers
2026-09-20 5:21 ` [PATCH v1 46/49] perf: Remove libpython support and legacy Python scripts Ian Rogers
2026-09-20 5:21 ` [PATCH v1 47/49] perf Makefile: Update Python script installation path Ian Rogers
2026-09-20 5:21 ` [PATCH v1 48/49] perf script: Support standalone scripts and remove embedded scripting Ian Rogers
2026-09-20 5:21 ` [PATCH v1 49/49] perf Documentation: Update for standalone Python scripts Ian Rogers
2026-09-21 5:06 ` [PATCH v2 00/49] perf: Complete transition to " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 01/49] perf python: Update syscall format string to optional positional Ian Rogers
2026-09-21 5:06 ` [PATCH v2 02/49] perf python: Update callchain stubs and session thread lookup Ian Rogers
2026-09-21 5:06 ` [PATCH v2 03/49] perf python: Clean up pylint warnings in ilist.py Ian Rogers
2026-09-21 5:06 ` [PATCH v2 04/49] perf python: Clean up pylint warnings in treport.py Ian Rogers
2026-09-21 5:06 ` [PATCH v2 05/49] perf python: Clean up pylint warnings in tracepoint.py Ian Rogers
2026-09-21 5:06 ` [PATCH v2 06/49] perf python: Clean up pylint warnings in twatch.py Ian Rogers
2026-09-21 5:06 ` [PATCH v2 07/49] perf python: Improve perf script -l descriptions Ian Rogers
2026-09-21 5:06 ` [PATCH v2 08/49] perf python: Expose addr location, transaction, and context_switch Ian Rogers
2026-09-21 5:06 ` [PATCH v2 09/49] perf python: Add Intel PT call_return and itrace capability Ian Rogers
2026-09-21 5:06 ` [PATCH v2 10/49] perf python: Allow KeyboardInterrupt to propagate in LiveSession Ian Rogers
2026-09-21 5:06 ` [PATCH v2 11/49] perf pmu-events: Clean up mypy and pylint issues Ian Rogers
2026-09-21 5:06 ` [PATCH v2 12/49] perf test: Clean up mypy and pylint issues in shell test libraries Ian Rogers
2026-09-21 5:06 ` [PATCH v2 13/49] perf build: Make mypy build test opt-out (NO_MYPY=1) Ian Rogers
2026-09-21 5:06 ` [PATCH v2 14/49] perf build: Make pylint build test opt-out (NO_PYLINT=1) Ian Rogers
2026-09-21 5:06 ` [PATCH v2 15/49] perf Makefile: Install standalone Python scripts during transition Ian Rogers
2026-09-21 5:06 ` [PATCH v2 16/49] perf python: Port stat-cpi to perf module Ian Rogers
2026-09-21 5:06 ` [PATCH v2 17/49] perf python: Port mem-phys-addr " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 18/49] perf python: Port stackcollapse " Ian Rogers
2026-09-21 5:06 ` Ian Rogers [this message]
2026-09-21 5:06 ` [PATCH v2 20/49] perf python: Port gecko " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 21/49] perf python: Port event_analyzing_sample " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 22/49] perf python: Port syscall-counts " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 23/49] perf python: Port syscall-counts-by-pid " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 24/49] perf python: Port failed-syscalls-by-pid " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 25/49] perf python: Port failed-syscalls from Perl " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 26/49] perf python: Port sctop " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 27/49] perf python: Port rw-by-file from Perl " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 28/49] perf python: Port rw-by-pid " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 29/49] perf python: Port rwtop " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 30/49] perf python: Port futex-contention " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 31/49] perf python: Port task-analyzer " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 32/49] perf python: Port sched-migration and SchedGui " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 33/49] perf python: Port wakeup-latency from Perl " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 34/49] perf python: Port compaction-times " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 35/49] perf python: Port net_dropmonitor " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 36/49] perf python: Port netdev-times " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 37/49] perf python: Port check-perf-trace " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 38/49] perf python: Port arm-cs-trace-disasm " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 39/49] perf python: Port powerpc-hcalls " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 40/49] perf python: Port intel-pt-events and libxed " Ian Rogers
2026-09-21 5:06 ` [PATCH v2 41/49] perf test: Migrate Intel PT virtual LBR test to Python API Ian Rogers
2026-09-21 5:07 ` [PATCH v2 42/49] perf python: Port export-to-sqlite to perf module Ian Rogers
2026-09-21 5:07 ` [PATCH v2 43/49] perf python: Port export-to-postgresql " Ian Rogers
2026-09-21 5:07 ` [PATCH v2 44/49] perf python: Move and clean up exported-sql-viewer.py Ian Rogers
2026-09-21 5:07 ` [PATCH v2 45/49] perf python: Move and clean up parallel-perf.py Ian Rogers
2026-09-21 5:07 ` [PATCH v2 46/49] perf: Remove libpython support and legacy Python scripts Ian Rogers
2026-09-21 5:07 ` [PATCH v2 47/49] perf Makefile: Update Python script installation path Ian Rogers
2026-09-21 5:07 ` [PATCH v2 48/49] perf script: Support standalone scripts and remove embedded scripting Ian Rogers
2026-09-21 5:07 ` [PATCH v2 49/49] perf Documentation: Update for standalone Python scripts Ian Rogers
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=6a93df199d357d7dab2e6e061341dcea76ab6f25.1789966896.git.irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alice.mei.rogers@gmail.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=james.clark@linaro.org \
--cc=leo.yan@linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=tmricht@linux.ibm.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
all inboxes | Powered by JetHome®