summaryrefslogtreecommitdiff
path: root/tools/perf/python
AgeCommit message (Collapse)Author
7 daysperf timechart: Add an interactive --tui modeAlice Rogers
Add ttimechart.py, a textual based interactive timechart, and a --tui option to perf timechart that launches it through perf script. Rather than writing an SVG file, per-CPU (busy, frequency and idle state), per-task (running, runnable and blocked) and I/O timelines are shown in the terminal along with a summary table. The timelines can be zoomed, panned and the state of the selected row at the cursor is described, including the task that woke it. The -i, -P, -T and -p options are passed to the script. The data is loaded in a background thread and the timelines are shown and updated as it loads. A --dump option prints a text summary without the UI. Committer testing: Fist record a short session with: root@x2:/home/acme/git/perf-tools-next# perf timechart record ^C[ perf record: Woken up 9 times to write data ] [ perf record: Captured and wrote 4.489 MB perf.data (29719 samples) ] root@x2:/home/acme/git/perf-tools-next# Then try the TUI with: root@x2:/home/acme/git/perf-tools-next# tools/perf/python/ttimechart.py or: root@x2:/home/acme/git/perf-tools-next# perf timechart --tui Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Alice Rogers <alice.mei.rogers@gmail.com> Co-developed-by: Ian Rogers <irogers@google.com> Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
7 daysperf treport: Show the profile while it loadsAlice Rogers
Reading a large perf.data file caused a long stall before the treport app started. Start the app immediately and build the profile in a background thread, showing the report tree and flame graph as they are built with the progress in the header. The time between updates grows with the load time as updating the views costs more as the profile grows. A lock guards the profile shared between the threads. Quitting while loading cancels the load. Tree nodes are now created lazily as they are expanded, expanded nodes and the cursor are kept across updates, and events are kept in the order they are first seen as their values aren't comparable. Node names are escaped so they aren't interpreted as markup. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Alice Rogers <alice.mei.rogers@gmail.com> Co-developed-by: Ian Rogers <irogers@google.com> Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
10 daysperf python: Avoid shadowing exception name in PostgreSQL exporterLeo Yan
During the perf build, pylint reports: ************* Module export-to-postgresql python/export-to-postgresql.py:319:8: W0621: Redefining name 'e' from outer scope (line 100) (redefined-outer-name) Rename 'e' to 'db_error' to clear the warning. Fixes: b1f968c9656a8a87 ("perf python: Port export-to-postgresql to perf module") Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Codex:gpt-6 Signed-off-by: Leo Yan <leo.yan@arm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
11 daysperf python event_analyzing_sample: Default to in-memory SQLite databaseIan Rogers
When -d/--db is not specified, event_analyzing_sample.py created a temporary file in /tmp via tempfile.mkstemp() and deleted it in trace_end(). As noted during review, creating the database in a shared /tmp directory does not reserve SQLite's auxiliary sidecar filenames (-journal or -wal), and a temporary on-disk file is unnecessary when the caller did not ask to persist the database. Default to sqlite3.connect(":memory:") when db_path is not provided, removing the temporary file creation and cleanup logic, and test both the default in-memory mode and explicit -d file mode in test_event_analyzing_sample_python.sh. Fixes: eeb70645a8097437 ("perf python: Port event_analyzing_sample to perf module") Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
11 daysperf python stat-cpi: Fix live mode signal races and test flakinessIan Rogers
In test_stat_cpi_python.sh, 'perf test -w noploop &' defaults to a 1-second duration and can exit under heavy parallel load before 'perf stat -p' and 'perf script stat-cpi' finish starting up. In addition, the fixed 'sleep 0.5' before sending SIGINT can fire before Python finishes importing the perf module, opening the live evlist, and flushing the first interval. In stat-cpi.py, register SIGINT and SIGTERM handlers before calling _open_live_evlist() and pass flush=True when printing live output so redirected stdout is flushed immediately after each interval. In test_stat_cpi_python.sh, run 'perf test -w noploop 60 &' so the target workload stays alive until killed, and poll the output file for 'cpi' (up to 5 seconds) before sending SIGINT. Fixes: 4425182d426b ("perf python: Port stat-cpi to perf module") Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
11 daysperf python sctop: Fix offline interval printing and test flakinessIan Rogers
In sctop.py: - If an earlier interval elapsed and printed an empty table before the target comm ('sleep') executed any syscalls, analyzer.printed became True and the final partial interval containing the target comm's syscalls was never flushed at EOF. Flush print_current_totals() in finally when analyzer.syscalls is non-empty as well as when nothing has been printed yet. - Initialize analyzer.e_machine after creating perf.session rather than when session is still None. In test_sctop_python.sh: - Use a private temporary directory via 'mktemp -d'. - Drop '-a' and pass '-B -N --no-bpf-event' to 'perf record', and sleep briefly in the subshell ('sh -c "sleep 0.1; sleep 0.05"') with a bounded retry loop so 'sleep's PERF_RECORD_COMM and sys_enter events are reliably captured under heavy load. Fixes: b83f0bacf5e4f936 ("perf python: Port sctop to perf module") Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
12 daysperf python: Fix arm-cs-trace-disasm type errorJames Clark
The perf sample dso_bid getter returns a string or None, matching its Optional[str] annotation. Attempting to decode it as bytes causes mypy to report union-attr errors, even though this was behind a conditional that checked for bytes type. Use the string directly, retaining the fallback for an unknown build ID. This fixes the following build error: python/arm-cs-trace-disasm.py:266: error: Item "None" of "str | None" has no attribute "decode" [union-attr] Fixes: 279b402e5143214c ("perf python: Port arm-cs-trace-disasm to perf module") Reviewed-by: Leo Yan <leo.yan@arm.com> Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Codex:GPT-6-Astra Signed-off-by: James Clark <james.clark@linaro.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Move and clean up parallel-perf.pyIan Rogers
Move parallel-perf.py from tools/perf/scripts/python/ to tools/perf/python/ as it is a standalone Python utility that invokes 'perf script' in parallel across time slices and CPUs. Update tools/perf/tests/shell/script.sh accordingly. Also fix bugs and clean up the script to pass mypy and pylint without suppression comments: - Fix Work.command() to return the shlex.quote()-escaped command string (previously sh_cmd was computed with shlex.quote() and discarded in favor of unquoted self.cmd). - Close self.popen.stdout in the parent process after spawning the consumer subprocess in Work.start() when --pipe-to is used, ensuring the producer receives SIGPIPE if the consumer exits early and avoiding leaking the pipe file descriptor. - Convert method and function names to snake_case, specify utf-8 file encodings, and add type annotations and docstrings. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Move and clean up exported-sql-viewer.pyIan Rogers
Move exported-sql-viewer.py from tools/perf/scripts/python/ to tools/perf/python/ as it is a standalone PySide/PyQt GUI application for viewing SQLite and PostgreSQL databases exported by perf script. Improvements and cleanups compared to the legacy script: - Add support for PySide6 (falling back to PySide2 and PySide) loaded dynamically via importlib, and provide stub base classes (_QtBase, _QtWidget) so static analysis (mypy and pylint) and --help-only execution succeed when Qt bindings are not installed. - Fix a Python 3 NameError crash in HBoxLayout where expanded_mark and not_expanded_mark called Python 2's removed unicode() builtin instead of chr(0x25BC) and chr(0x25B6). - Replace instance-level method monkey-patching (self.mousePressEvent = self.MousePressEvent) on SwitchGraphView with proper class methods gated by self.rb_enabled so Qt virtual method dispatch works cleanly across PySide2 and PySide6. - Remove Python 2 constructs (cPickle, xrange), wildcard imports, bare 'except:' clauses, and variable names shadowing Python builtins. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port export-to-postgresql to perf moduleIan Rogers
Port export-to-postgresql.py to a standalone script in tools/perf/python/ using the perf module and libpq via ctypes. Improvements compared to the legacy script: - Remove the dependency on PySide/QtSql for database creation and DDL execution by driving libpq directly via ctypes (PQconnectdb, PQexec, PQputCopyData, PQputCopyEnd) and streaming binary PostgreSQL COPY files in PostgresExporter, enabling export on headless servers without Qt installed. - Harden database connection and SQL identifier handling by rejecting URI ('://') and connection-parameter ('=') injection strings in setup_db() and connect(), escaping single quotes and backslashes in connection strings, and quoting SQL identifiers (quote_ident). - Support Intel PT and instruction trace export via perf.session(itrace=...) and perf.call_return callbacks, reconstructing relational call_paths and calls tables (including id=0 placeholder rows and callfk/returnfk foreign keys) and unpacking synthesized PT payloads (ptwrite, cbr, mwait, pwre, exstop, pwrx). - Use a dedicated context_switch ID counter so context-switch exports do not advance sample database IDs out of sync with call_return references. Update Documentation/db-export.txt and add a shell test (test_export_to_postgresql_python.sh) to verify the standalone exporter. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port export-to-sqlite to perf moduleIan Rogers
Port export-to-sqlite.py to a standalone script in tools/perf/python/ using the perf module and Python's standard library sqlite3 module. Improvements compared to the legacy script: - Remove the dependency on PySide/QtSql by using Python's built-in sqlite3 module in DatabaseExporter, allowing SQLite export on headless and minimal systems without Qt installed. - Support Intel PT and hardware instruction trace export via perf.session(itrace=...) and perf.call_return callbacks, reconstructing relational call_paths and calls tables and decoding synthesized PT payloads (ptwrite, cbr, mwait, pwre, exstop, pwrx). - Export context_switches via perf.session's context_switch callback and map thread and comm IDs to their relational database keys. - Manage temporary staging files inside an isolated tempfile.mkdtemp() directory with guaranteed cleanup in a finally block. Update Documentation/db-export.txt and add a shell test (test_export_to_sqlite_python.sh) to verify the standalone exporter. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port intel-pt-events and libxed to perf moduleIan Rogers
Port intel-pt-events.py and libxed.py from tools/perf/scripts/python/ to standalone modules in tools/perf/python/: - Refactor intel-pt-events.py into an IntelPTAnalyzer class with full type annotations to encapsulate trace state and stashed output. - Configure instruction trace decoding directly via perf.session's itrace option and context_switch callback. - Dynamically select 32-bit vs 64-bit disassembly mode in libxed.py using session.is_64_bit and annotate instructions with source lines via sample.srccode(). - Rename methods in libxed.py to snake_case (instruction, set_mode, disassemble_one) and remove Python 2 compatibility code. Add a shell test (test_intel_pt_events_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port powerpc-hcalls to perf moduleIan Rogers
Port powerpc-hcalls.py from tools/perf/scripts/python/ to a standalone script in tools/perf/python/: - Refactor the script into an HCallAnalyzer class with full type annotations to encapsulate per-CPU hypervisor call entry/exit state. - Use perf.session for event processing to track hypervisor call entry and exit timestamps and aggregate min/max/average duration statistics against HCALL_TABLE. - Add argparse CLI support (-i/--input) and remove Python 2 compatibility code. Add a shell test (test_powerpc_hcalls_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port arm-cs-trace-disasm to perf moduleIan Rogers
Port arm-cs-trace-disasm.py to a standalone script in tools/perf/python/ using the perf module directly. Improvements compared to the legacy script: - Encapsulate trace disassembly state in a TraceDisasm class. - Default to itrace="b" when creating perf.session() (overridable via --itrace or PERF_ITRACE) so all CoreSight branch samples are synthesized without requiring --itrace=b on the command line. - Automatically search standard kernel debug paths (find_vmlinux()) when -k/--vmlinux is not specified, and query perf.config_get("annotate.objdump") for the default objdump binary. - Bound DISASM_CACHE memory consumption by evicting the cache at 1024 entries and skipping caching of oversized (> 512 lines) objdump outputs. - Use sample.srccode() from the perf extension module to annotate disassembly output with source filenames, line numbers, and source lines. Update the ARM CoreSight disassembly shell test (test_arm_coresight_disasm.sh) to invoke the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Reviewed-by: James Clark <james.clark@linaro.org> Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port check-perf-trace to perf moduleIan Rogers
Port check-perf-trace.py to a standalone script in tools/perf/python/ using the perf module directly. Improvements compared to the legacy script: - Access tracepoint fields directly as attributes on perf.sample_event instead of per-event dictionaries and legacy Perf-Trace-Util helpers. - Decode symbolic flag and enum masks for irq:softirq_entry and kmem:kmalloc directly in Python and add -i/--input CLI support via argparse. - Add full type annotations and clean up Python 2 idioms. Add a shell test (test_check_perf_trace_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port netdev-times to perf moduleIan Rogers
Port netdev-times.py from tools/perf/scripts/python/ to a standalone script in tools/perf/python/: - Refactor the script into a NetDevTimesAnalyzer class with full type annotations to encapsulate state. - Collect events via perf.session and sort them in timestamp order before analysis so multi-CPU TX and RX packet timelines are reconstructed deterministically. - Replace custom argument parsing with argparse (-i/--input, --tx, --rx, --dev, --debug), extract tracepoint fields directly from sample attributes, and remove Python 2 compatibility artifacts. Add a shell test (test_netdev_times_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port net_dropmonitor to perf moduleIan Rogers
Port net_dropmonitor.py from tools/perf/scripts/python/ to a standalone script in tools/perf/python/: - Refactor the script into a DropMonitor class with full type annotations to encapsulate state. - Use perf.session for skb:kfree_skb event processing and add argparse CLI support (-i/--input and -k/--kallsyms). - Resolve kernel drop addresses via perf.session symbols/callchains and binary search over /proc/kallsyms, ignoring zeroed kptr_restrict addresses with graceful fallback when kallsyms is unavailable. - Remove Python 2 compatibility code. Add a shell test (test_net_dropmonitor_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port compaction-times to perf moduleIan Rogers
Port compaction-times.py to a standalone script in tools/perf/python/ using the perf module directly to analyze mm_compaction tracepoints. Improvements compared to the legacy script: - Replace Python 2 constructs (such as sys.maxint and raw integer bitmasks) with Python 3 enum.IntEnum (Popt) and enum.IntFlag (Topt) types. - Access tracepoint fields directly on perf.sample_event and add -i/--input CLI option support via argparse. - Add full type annotations passing mypy and pylint without suppression comments. Add a shell test (test_compaction_times_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port wakeup-latency from Perl to perf moduleIan Rogers
Replace the legacy Perl script wakeup-latency.pl with a standalone Python script in tools/perf/python/wakeup-latency.py using the perf Python module. Improvements compared to the legacy Perl script: - Remove the dependency on libperl and Perf::Trace::Util. - Track wakeup timestamps per-task (keyed by the wakee PID on sched:sched_wakeup and matched against next_pid on sched:sched_switch) rather than per-CPU, avoiding mixed latencies when multiple wakeups occur on a CPU before a context switch. - Guard print_totals() when total_wakeups == 0 (printing 'N/A' instead of dividing by zero when a trace contains no matched wakeup/switch pairs). - Add argparse CLI options (-i/--input) and full type annotations. Add a shell test (test_wakeup_latency_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port sched-migration and SchedGui to perf moduleIan Rogers
Port sched-migration.py and SchedGui.py from tools/perf/scripts/python/ to standalone modules in tools/perf/python/: - Refactor sched-migration.py into a SchedMigrationAnalyzer class using perf.session for event processing and add argparse CLI support (-i/--input, -v/--verbose, --gui, --no-gui). - Port SchedGui.py to tools/perf/python/ as a local module dependency. - Load wxPython dynamically via importlib only when GUI mode (--gui) is requested so text-mode analysis, testing on headless systems, and static analysis (mypy/pylint) succeed without wx installed. - Remove Python 2 compatibility code. Add a shell test (test_sched_migration_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port task-analyzer to perf moduleIan Rogers
Port task-analyzer.py from tools/perf/scripts/python/ to a standalone script in tools/perf/python/ refactored into a class-based architecture. Improvements compared to the legacy script: - Support both offline perf.data file analysis (using perf.session) and live trace capture (using evlist.read_on_cpu), accessing sched:sched_switch tracepoint fields directly from sample objects. - Automatically disable ANSI terminal color escape sequences when --csv or --csv-summary is enabled so CSV column headers ('Comm,', 'Time Out-Out,', etc.) are never polluted by color codes when running interactively on a TTY (e.g. as root). - Sanitize non-printable characters and leading CSV formula characters (=, +, -, @) in task comm strings. - Emit a one-time warning to stderr if sched:sched_switch samples are missing tracepoint fields (such as when recorded without libtraceevent support). Update test_task_analyzer.sh to invoke the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port futex-contention to perf moduleIan Rogers
Port tools/perf/scripts/python/futex-contention.py to a standalone script in tools/perf/python/ using the perf module. Avoiding the embedded interpreter overhead improves execution speed by ~3.2x: ``` $ perf record -e syscalls:sys_*_futex -a sleep 1 ... $ time perf script tools/perf/scripts/python/futex-contention.py ... real 0m1.007s user 0m0.935s sys 0m0.072s $ time python3 tools/perf/python/futex-contention.py ... real 0m0.314s user 0m0.259s sys 0m0.056s ``` Additional improvements compared to the legacy script: - Consolidate per-(tid, uaddr) contention count, total_time, min_time, and max_time into a single LockStats class instead of maintaining three separate dictionaries. - Validate that uaddr and op tracepoint attributes are present on syscalls:sys_enter_futex samples rather than silently attributing missing fields to uaddr=0, op=0 (FUTEX_WAIT). - Add -i/--input CLI option support via argparse and full type annotations. Add a shell test (test_futex_contention_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port rwtop from Perl to perf moduleIan Rogers
Replace the legacy Perl script rwtop.pl with a standalone Python script in tools/perf/python/rwtop.py using the perf Python module. Improvements compared to the legacy Perl script: - Remove the dependency on libperl and Perf::Trace::Util. - Support both offline perf.data files (via perf.session) and live recording (via LiveSession with --live), driving periodic interval summaries from event timestamps rather than wall-clock SIGALRM timers so both live and offline runs produce deterministic output. - Convert unsigned 32-bit and 64-bit error return values (0xfffff000..0xffffffff and >= 0x8000000000000000) to negative errnos so failed read/write syscalls are recorded in the error table rather than inflating bytes_read / bytes_written. - Sanitize non-printable characters in /proc/<pid>/comm to prevent terminal control sequence injection. Add a shell test (test_rwtop_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port rw-by-pid from Perl to perf moduleIan Rogers
Replace the legacy Perl script rw-by-pid.pl with a standalone Python script in tools/perf/python/rw-by-pid.py using the perf Python module. Improvements compared to the legacy Perl script: - Remove the dependency on libperl and Perf::Trace::Util. - Convert unsigned 32-bit and 64-bit error return values (0xfffff000..0xffffffff and >= 0x8000000000000000) to negative errnos so failed read/write syscalls are recorded in the error table rather than inflating bytes_read / bytes_written. - Add argparse CLI support (-i/--input) and full type annotations. Add a shell test (test_rw_by_pid_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port rw-by-file from Perl to perf moduleIan Rogers
Replace the legacy Perl script rw-by-file.pl with a standalone Python script in tools/perf/python/rw-by-file.py using the perf Python module. Improvements compared to the legacy Perl script: - Remove the dependency on libperl and Perf::Trace::Util. - Encapsulate per-file-descriptor read/write byte and call count aggregation in an RwByFile class using perf.session and resolve thread command names via session.find_thread(pid, sample_tid). - Add argparse CLI support (-i/--input and target program filter) and full type annotations. Add a shell test (test_rw_by_file_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port sctop to perf moduleIan Rogers
Port sctop.py from tools/perf/scripts/python/ to a standalone script in tools/perf/python/ using an SCTopAnalyzer class structure. Improvements compared to the legacy script: - Support both offline perf.data analysis (via perf.session, advancing display intervals deterministically using event timestamps) and live monitoring (via LiveSession with automatic tracepoint fallback from raw_syscalls:sys_enter to syscalls:sys_enter_*). - Resolve architecture-aware syscall names via perf.syscall_name(id, session.e_machine) without requiring python-audit. - Replace unsafe signal.SIGALRM dictionary mutation and os.popen("clear") subshell spawning with a synchronized threading.Lock / threading.Event timer and direct ANSI terminal escape sequences ('\x1b[2J\x1b[H'). Add a shell test (test_sctop_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port failed-syscalls from Perl to perf moduleIan Rogers
Replace the legacy Perl script failed-syscalls.pl with a standalone Python script in tools/perf/python/failed-syscalls.py using the perf Python module. Improvements compared to the legacy Perl script: - Remove the dependency on libperl and Perf::Trace::Util. - Support both syscalls:sys_exit_* and raw_syscalls:sys_exit events (the legacy script only handled raw_syscalls::sys_exit). - Use session.is_64_bit to distinguish 32-bit vs 64-bit unsigned error return ranges (0xfffff000..0xffffffff vs >= 0xfffffffffffff000) so valid 64-bit syscalls returning ~4GB values are not misclassified as 32-bit negative errors. - Add argparse CLI support (-i/--input and optional comm filter) and full type annotations. Add a shell test (test_failed_syscalls_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port failed-syscalls-by-pid to perf moduleIan Rogers
Port failed-syscalls-by-pid.py to a standalone script in tools/perf/python/ using the perf module: - Resolve architecture-aware syscall names using perf.syscall_name(id, session.e_machine) instead of host python-audit tables, supporting cross-architecture perf.data files without external dependencies. - Translate negative syscall return values into symbolic E* error names using perf.arch_strerrno(ret, session.e_machine), leveraging the auto-generated trace beauty architecture errno tables. - Encapsulate aggregation in a SyscallAnalyzer class using collections.defaultdict and add argparse filtering by comm, PID, and -i/--input. Add a shell test (test_failed_syscalls_by_pid_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port syscall-counts-by-pid to perf moduleIan Rogers
Port tools/perf/scripts/python/syscall-counts-by-pid.py to a standalone script in tools/perf/python/ using the perf module. Avoiding the embedded interpreter and per-event dictionary overhead improves execution speed by ~3.8x: ``` $ perf record -e raw_syscalls:sys_enter -a sleep 1 ... $ time perf script tools/perf/scripts/python/syscall-counts-by-pid.py perf ... real 0m3.852s user 0m3.512s sys 0m0.336s $ time python3 tools/perf/python/syscall-counts-by-pid.py perf ... real 0m1.011s user 0m0.963s sys 0m0.048s ``` Additional improvements compared to the legacy script: - Resolve architecture-specific syscall names via perf.syscall_name(id, session.e_machine) instead of host python-audit tables. - Support both raw_syscalls:sys_enter and individual syscalls:sys_enter_* tracepoints, and filter out invalid (> 0xffff or negative) syscall IDs. - Support filtering by numeric PID as well as command name (comm), and resolve process command names via session.find_thread(pid). Add a shell test (test_syscall_counts_by_pid_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port syscall-counts to perf moduleIan Rogers
Port tools/perf/scripts/python/syscall-counts.py to a standalone script in tools/perf/python/ using the perf module. Avoiding the embedded interpreter and per-event dictionary allocation overhead improves execution speed by ~4x: ``` $ perf record -e raw_syscalls:sys_enter -a sleep 1 ... $ time perf script tools/perf/scripts/python/syscall-counts.py perf ... real 0m3.887s user 0m3.578s sys 0m0.308s $ time python3 tools/perf/python/syscall-counts.py perf ... real 0m0.953s user 0m0.905s sys 0m0.048s ``` Additional improvements compared to the legacy script: - Resolve syscall names using perf.syscall_name(id, session.e_machine) instead of host python-audit / Util.py tables, enabling accurate cross-architecture perf.data analysis without external dependencies. - Support both raw_syscalls:sys_enter (sample.id) and individual syscalls:sys_enter_* tracepoints (sample.__syscall_nr / sample.nr), filtering out invalid/corrupt (> 0xffff or negative) syscall numbers. - Add argparse CLI options (-i/--input and optional comm filter). Add a shell test (test_syscall_counts_python.sh) to verify the standalone script. The legacy script and its bin wrapper are retained temporarily during the transition to maintain bisectability and are removed once all scripts are migrated. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port event_analyzing_sample to perf moduleIan Rogers
Port event_analyzing_sample.py to a standalone script in tools/perf/python/ using the perf module and standard library sqlite3 module. Improvements compared to the legacy script: - Encapsulate database state in a _DB container instead of mutating module-level globals, and ensure temporary SQLite database files are cleaned up on exit. - Add argparse CLI options (-i/--input and -d/--db) while preserving PerfEvent, PebsEvent, and PebsNHM binary raw_buf unpacking and symbol/DSO histogram reporting. - Remove Python 2 compatibility code and add type annotations. Add a shell test (test_event_analyzing_sample_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port gecko to perf moduleIan Rogers
Port gecko.py to a standalone script in tools/perf/python/ that uses the perf module directly to convert perf.data profiles into Firefox Gecko profile format. Improvements compared to the legacy script: - Encapsulate profiler state in GeckoCLI and CategoryData classes with full type annotations, removing global variables. - Harden the local HTTP server in _write_and_launch(): write the temporary profile to an isolated tempfile.TemporaryDirectory() with a randomized UUID filename instead of the current working directory, bind HTTPServer exclusively to 127.0.0.1 on an OS-assigned ephemeral port (0), restrict CORS Access-Control-Allow-Origin to 'https://profiler.firefox.com' instead of '*', and restrict HTTP GET requests exclusively to the randomized profile filename (returning HTTP 403 for directory listings and any other path). - Add -i/--input and -e/--event CLI options via argparse. Add a shell test (test_gecko_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port flamegraph to perf moduleIan Rogers
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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port stackcollapse to perf moduleIan Rogers
Port stackcollapse.py from tools/perf/scripts/python/ to a standalone script in tools/perf/python/ refactored into a StackCollapseAnalyzer class. Improvements compared to the legacy script: - Traverse sample.callchain directly from perf.session without allocating per-event dictionaries, and fall back to sample.symbol when a sample has no callchain. - Replace deprecated optparse with argparse, adding -i/--input alongside --include-tid, --include-pid, --no-comm, --tidy-java, and --kernel. - Handle BrokenPipeError cleanly when output is piped into downstream tools (such as head or flamegraph.pl). Add a shell test (test_stackcollapse_python.sh) using a CPU workload (perf test -w noploop) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port mem-phys-addr to perf moduleIan Rogers
Port mem-phys-addr.py to a standalone script in tools/perf/python/ using the perf.session API to read perf.data files and profile physical memory access types against /proc/iomem. Improvements compared to the legacy script: - Parse the full indentation hierarchy of /proc/iomem into a parent-child tree of frozen IomemEntry dataclasses (instead of only top-level indent-0 ranges), resolving physical addresses to the most specific sub-range (such as Kernel code/data/bss inside System RAM) and rolling child counts up into parent totals. - Support profiling multiple memory events in a single perf.data session (keyed by evsel name) instead of assuming a single global event. - Add argparse CLI options (-i/--input and --iomem to allow supplying an offline /proc/iomem snapshot from a target system). Add a shell test (test_mem_phys_addr_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Port stat-cpi to perf moduleIan Rogers
Port stat-cpi.py from the legacy embedded scripting framework to a standalone Python script in tools/perf/python/ to calculate Cycles Per Instruction (CPI) per interval per CPU or thread. Improvements compared to the legacy script: - Support both perf.data file mode (via perf.session stat callbacks) and live counter collection mode (using perf.parse_events, evlist.open, and evsel.read across intervals), with automatic fallback to user-space (:u) and self-process monitoring when perf_event_paranoid restricts system-wide events (EACCES). - Compute per-interval counter deltas (val, ena, run) keyed by raw event name so cumulative PERF_RECORD_STAT snapshots and hybrid PMU events (e.g. cpu_core/cycles/, cpu_atom/cycles/) are accumulated accurately, and scale counts by time_enabled / time_running when multiplexed. - Replace hard-coded CPU ([0, 1]) and thread ([0]) arrays with dynamic CPU and thread discovery so arbitrary system topologies work automatically. - Add CLI option handling (-i, -I, -p) via argparse and type annotations passing mypy and pylint. Add a shell test (test_stat_cpi_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Allow KeyboardInterrupt to propagate in LiveSessionIan Rogers
LiveSession.run() synchronously blocks while polling evlist for events. When running interactive tools or scripts from the terminal, KeyboardInterrupt exceptions raised via Ctrl-C must propagate so the caller can break out of the polling loop. Previously, LiveSession caught KeyboardInterrupt with an empty pass statement, swallowing the exception and preventing calling scripts from detecting the interrupt cleanly. Remove the empty handler so calling scripts receive KeyboardInterrupt and can perform clean teardown. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Add Intel PT call_return and itrace capabilityIan Rogers
Add support for Intel PT call_return events and itrace options to the perf Python extension so standalone Python scripts can decode and inspect low-level instruction traces. Specifically: - Add a call_return callback parameter and itrace option string to perf.session, treating explicit None (Py_None) callbacks as omitted. - Expose the perf.call_return object with db_id, parent_id, insn_count, cyc_count, comm, pid, tid, call_time, return_time, branch_count, call_ref, return_ref, flags, and call_path (resolved as a perf.callchain ordered from outermost caller to callee, populating frame->map and frame->sym so call_path entries expose resolved symbol and DSO names). - Export perf.CALL_RETURN_NO_CALL, perf.CALL_RETURN_NO_RETURN, and perf.CALL_RETURN_NON_CALL flag constants. - Expose session.e_machine and session.is_64_bit properties, preferring recorded thread ELF machines (perf_session__e_machine) over perf_env so pipe-mode traces do not prematurely cache host bitness. - Support optional vmlinux, kallsyms, and symfs symbol configuration parameters (and PERF_SYMBOL_VMLINUX, PERF_SYMBOL_KALLSYMS, PERF_SYMBOL_SYMFS environment fallbacks) in perf.session, resetting symbol_conf pointers and freeing vm_tm_corr_args, cpu_bitmap, and ptime_range in pyrf_session__delete(). Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Expose addr location, transaction, and context_switchIan Rogers
Expose destination address location components (addr_dso, addr_symbol, addr_sym_offset), branch/transaction metrics (branch_type, in_tx, flags, transaction), machine_pid, vcpu, sym_offset, and context_switch callbacks directly to the Python extension. Also include supporting fixes and infrastructure updates in util/python.c and perf.pyi: - Support fetching sym_offset on resolved sample symbols. - Populate sample machine_pid and vcpu from evlist__id2sid() when perf_guest is enabled, and resolve samples against the matching guest or host machine. - Expose next_prev_pid and next_prev_tid on switch_event only for PERF_RECORD_SWITCH_CPU_WIDE records (returning None otherwise). - Wire up tracing_data in pyrf_session__new() and update perf.pyi type stubs (including srccode() and insn() return types). Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Improve perf script -l descriptionsIan Rogers
Add module docstrings to counting.py, tracepoint.py, and twatch.py. This satisfies pylint's missing-module-docstring check and prepares these existing standalone scripts in tools/perf/python/ for the later commit in this series ("perf script: Support standalone scripts and remove embedded scripting"), which updates 'perf script -l' to scan tools/perf/python/ and display each script's module docstring: ``` $ perf script -l List of available scripts: ... counting Example for counting perf events. ... tracepoint Example showing how to enable a tracepoint and access its fields. twatch Example to show how to enable a software event and track context switches. ... ``` Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Clean up pylint warnings in twatch.pyIan Rogers
Clean up pylint warnings in twatch.py so that it passes pylint without warning suppression comments: - Convert tab indentation to 4 spaces (W0311: bad-indentation). - Remove unnecessary trailing semicolon (W0301: unnecessary-semicolon) after evsel.open(). - Convert floating multi-line string comments to '#' comments (W0105: pointless-string-statement). Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Clean up pylint warnings in tracepoint.pyIan Rogers
Clean up pylint warnings in tracepoint.py so that it passes pylint without warning suppression comments: - Catch ImportError instead of bare 'except:' (W0702: bare-except) when importing setproctitle. - Remove unnecessary trailing semicolon (W0301: unnecessary-semicolon) after evlist.enable(). Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Clean up pylint warnings in treport.pyIan Rogers
Clean up pylint warnings in treport.py so that it passes pylint without warning suppression comments: - Replace broad 'except Exception:' clauses (W0718: broad-exception-caught) with specific exception tuples. - Pass both pid and sample_tid to session.find_thread() so guest and process threads are resolved accurately. - Rename parameter 'args' to 'pos_args' in FlameGraph.__init__() to avoid shadowing the outer scope variable 'args' (W0621: redefined-outer-name). - Clear session = None in a finally block after session.process_events() to break the C perf_session reference cycle before launching the TUI. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Clean up pylint warnings in ilist.pyIan Rogers
Replace bare 'except:' clauses (pylint W0702: bare-except) in ilist.py with specific exception tuples (OSError, ValueError, RuntimeError, TypeError, KeyError) and use a safe '.get("name", "")' sort key in IListApp.compose() so that ilist.py passes pylint without warning suppression comments and handles unnamed PMU events gracefully. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Update callchain stubs and session thread lookupIan Rogers
Update pyrf_session__find_thread() in util/python.c to accept an optional tid parameter (defaulting to pid) and return None instead of raising TypeError when a thread is not found in the session machines. Update perf.pyi to match: - Set session.find_thread() signature to (pid: int, tid: int = -1) -> Optional[thread]. - Update callchain_node.symbol and callchain_node.dso to str (the C getters return "[unknown]" fallback strings rather than None) and add __iter__() to callchain. Also update treport.py to handle Optional[thread] returned by session.find_thread(). Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf python: Update syscall helpers and expose arch_strerrnoIan Rogers
Update the PyArg_ParseTupleAndKeywords format string for pyrf__syscall_name() and pyrf__syscall_id() from "i|$i" to "i|i" (and "s|$i" to "s|i"), allowing elf_machine to be passed as an optional positional argument as well as a keyword argument. Update syscall_id() and syscall_name() in perf.pyi to match, and set the return type of syscall_name() to Optional[str] as unknown syscall numbers return None. Also expose perf_env__arch_strerrno() as perf.arch_strerrno(err, elf_machine=None) so standalone Python scripts can resolve architecture-specific errno names directly from the auto-generated trace beauty tables instead of maintaining duplicate errno dictionaries in Python. Tighten the macro pattern in arch_errno_names.sh to E[A-Z0-9]+ so compiler -D flags containing underscores (such as LLVM's -DEXPERIMENTAL_KEY_INSTRUCTIONS=1) do not shadow EPERM (1), and add EM_SPARC32PLUS alongside EM_SPARC and EM_SPARCV9. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-09-13perf python: Fix ilist TreeNode string type driftIan Rogers
Updates Tree type hints to correctly use TreeNode[TreeValue] across all assignments preventing mypy strictness mismatches. Address some other minor stylistic issues reported by mypy, pylint and Sashiko. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-09-09perf python: Add flamegraph support to treportAlice Rogers
Implement a flamegraph widget that recursively walks down a tree splitting line segments based on their value (summed up periods across call chains). A visitor pattern is used so that the same logic can both draw the line segments and locate which segment had a mouse click. Add a tab for the flame graph widget. Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Co-developed-by: Ian Rogers <irogers@google.com> Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Alice Rogers <alice.mei.rogers@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-09-09perf python: New treport scriptAlice Rogers
A textual app that displays the results of processing samples similar to perf report. The app displays a tree of first processes and then functions which drop down to show more detail on the functions they call. The functions with the largest number of samples are sorted first, after each function the percentage of time spent within it is highlighted. If more than one event is recorded then each event appears first, with the processes and functions sorted for that event beneath it. The app is written in python and requires the textual framework. Using the textual framework means that in most modern terminals the mouse is supported, the color scheme can be configured, and screenshots made. With perf report: ``` $ perf record -e cycles:u -g perf test -w brstack [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.008 MB perf.data (57 samples) ] $ perf report ... Samples: 57 of event 'cycles:u', Event count (approx.): 15907831 Children Self Command Shared Object Symbol - 88.86% 0.00% perf libc.so.6 [.] 0x000079b17df69ca8 0x79b17df69ca8 main handle_internal_command cmd_test - brstack - 84.27% brstack_bench - 40.69% brstack_foo brstack_bar 3.32% brstack_bar 3.31% brstack_bar 1.27% brstack_foo + 88.86% 0.00% perf perf [.] main + 88.86% 0.00% perf perf [.] handle_internal_command + 88.86% 0.00% perf perf [.] cmd_test + 88.86% 0.00% perf perf [.] brstack + 84.27% 40.26% perf perf [.] brstack_bench + 41.96% 30.71% perf perf [.] brstack_foo + 17.89% 17.89% perf perf [.] brstack_bar ``` With the treport script: ``` $ perf record -e cycles:u -g perf test -w brstack [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.008 MB perf.data (57 samples) ] $ tools/perf/python/treport.py O ReportApp Report ╸━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ▼ Profile └── ▼ cycles:u 100% └── ▼ perf (32963) 100% ├── ▼ /usr/lib/x86_64-linux-gnu/libc.so.6 0x79b17df6 │ └── ▼ main 56.1% │ └── ▼ handle_internal_command 56.1% │ └── ▼ cmd_test 56.1% │ └── ▼ brstack 56.1% ▁▁ │ ├── ▼ brstack_bench 52.6% │ │ ├── ▶ brstack_foo 24.6% │ │ └── brstack_bar 1.75% │ ├── brstack_foo 1.75% │ └── brstack_bar 1.75% ├── ▶ /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ▌ ^q Quit ▏^p palette ``` Committer testing: One needs to install 'python-textual' to have this working. Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Co-developed-by: Ian Rogers <irogers@google.com> Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Alice Rogers <alice.mei.rogers@gmail.com> Link: https://lore.kernel.org/r/20260809051820.2436530-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-08-09perf python: Fix MetricGroup return type in perf.pyiIan Rogers
The metrics() function can return a dictionary where the value is either a string or a list of strings, so the type signature in the stub file should be Union[str, List[str]]. Fixes: 430da3cd03b4 ("perf python: Add perf.pyi stubs file") Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>