From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A16D32D0CC for ; Mon, 20 Apr 2026 00:00:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776643214; cv=none; b=kwFBwd2Oypswx+M7Yr8AU7rM/2iHrDyohPfMwTwAUqwrOImNhhvSa0AzvpMQQ8V1hawU48NMmQoWGtx5sUSbKup1BSoeG8iXSTYmNAK/K+CYcEaeMhkSYjrYVJAQtzFAbhVGUVBbge3Hxq3Jx6BXA4eDnldFKMBGYu9vovWfmV0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776643214; c=relaxed/simple; bh=AKzqfaXC7AzBydNPDcmXo6my7/IuRA/xRJ4/jXI6MeA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=FaOBPSnuVJKOmh3tfTFT40P7LbXZNBg0rtQzIelUanFkx3nXt6F1sCQfKqtBOMB3q4BIqb7CpOCylGOPWux/ZeOVEp/eJxtqh/BpRz9qNsLrn98fN/H+oNfHxbQgZQkE8bfA2SE9fHeiY4g0PWIu8+4zv/w5nSSIdcbDM2eTI4Y= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=IFcmEs01; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="IFcmEs01" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2bdf6fe90a9so3059304eec.1 for ; Sun, 19 Apr 2026 17:00:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1776643212; x=1777248012; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=3Cj4qbUaeOYcHHiNYTmNzwTP1zmQKfbRNYQSzHORVpg=; b=IFcmEs0171DpW8N9O2CovTyMI3fxKvIj3NMYbo2vEK+FC+o/gmMyniudcOmiW9FzJb lkenD3aNc712FvH4eoeim6w7CgKw9FaJX50DkD8Yn2tj2RuxrYVZEDO+V+0In8NxdJBn bUPE5eKPZe8YI/K90jO3hwygU1rvB4j00vBKbB12FMdpfF8m7xxSMNOJstzSfEV+6te+ ZFpHryZRJa8JFLoTY3nu6M17RFKIlYX2wJRrblYOucHUAoXrXFQhRGjiV5+OZUWVwCWI Up31TnZNkwqAJx/NHt01mrJE1QFd00mNEJ4rOmOb6EtfD5X0eDHwe2AoIRVQq1eqDDq4 8r3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776643212; x=1777248012; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3Cj4qbUaeOYcHHiNYTmNzwTP1zmQKfbRNYQSzHORVpg=; b=OVKNOxCAVJstvGWLiblsEuNdHtX68e7FlTA3z4z/Psp1AeLcZKSPY+lbu0sFI7k1po H6zsGUs1szOD00P6hfH00N5qTKg3x9ocgRKDKV6lXZWZDyCR7FOnPjcQgfbBfD01K79x EnI6O722toMZi3c39WXmz+g+tFHIgcbNgEH+Ob/Q9lnBOV7CTQ2ljUHXMRVqJqi77eeA slZgqbC0vbpeZ2UIwtKiMiYL7SeWVCLw5XK+KmTeXp1pxqqpVB1ssLcBvH/Alh19f+F/ ALiuYDOKx5Szp4BlGQXgZKBskjO4b05KrL1Fdz/Ne6cAOVKmKgggPDjvJnxxtRUDmocA SkRQ== X-Forwarded-Encrypted: i=1; AFNElJ8tnMp19ZuXubwlYB1qBwmFz0z7WVMpjZPRYGbzJ73OGvwL7NOp+/iqfW05K7CaNXKyQZecRH6dP7jctlvekudI@vger.kernel.org X-Gm-Message-State: AOJu0YxhuPcExrYhaz4FfQSPd/VgUYU0AA5IX5OJr75N5MftWHYt9OZL d/gAWFKKiZcdcbkEcph1gqFhjGCzpoTud3pHGbBdZAFQNGf1zPqQcIoHdc4jg0J6TmyBN093bJd WdntDpoBy4A== X-Received: from dyjh29.prod.google.com ([2002:a05:7300:561d:b0:2e0:f299:f616]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:d704:b0:2d8:b814:29af with SMTP id 5a478bee46e88-2e464dafab3mr5101956eec.3.1776643211416; Sun, 19 Apr 2026 17:00:11 -0700 (PDT) Date: Sun, 19 Apr 2026 16:58:34 -0700 In-Reply-To: <20260419235911.2186050-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-perf-users@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260419235911.2186050-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.rc1.513.gad8abe7a5a-goog Message-ID: <20260419235911.2186050-23-irogers@google.com> Subject: [PATCH v1 22/58] perf python: Add perf.pyi stubs file From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Jiri Olsa , Adrian Hunter , James Clark , Alice Rogers , Suzuki K Poulose , Mike Leach , John Garry , Leo Yan , Yicong Yang , Jonathan Cameron , Nick Terrell , David Sterba , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Alexandre Chartre , Dmitrii Dolgov <9erthalion6@gmail.com>, Yuzhuo Jing , Blake Jones , Changbin Du , Gautam Menghani , Wangyang Guo , Pan Deng , Zhiguo Zhou , Tianyou Li , Thomas Falcon , Athira Rajeev , Collin Funk , Dapeng Mi , Ravi Bangoria , Zecheng Li , tanze , Thomas Richter , Ankur Arora , "Tycho Andersen (AMD)" , Howard Chu , Sun Jian , Derek Foreman , Swapnil Sapkal , Anubhav Shelat , Ricky Ringler , Qinxin Xia , Aditya Bodkhe , Chun-Tse Shao , Stephen Brennan , Yang Li , Chuck Lever , Chen Ni , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org Cc: Ian Rogers Content-Type: text/plain; charset="UTF-8" Add Python type stubs for the perf module to improve IDE support and static analysis. Includes docstrings for classes, methods, and constants derived from C source and JSON definitions. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers --- tools/perf/python/perf.pyi | 481 +++++++++++++++++++++++++++++++++++++ 1 file changed, 481 insertions(+) create mode 100644 tools/perf/python/perf.pyi diff --git a/tools/perf/python/perf.pyi b/tools/perf/python/perf.pyi new file mode 100644 index 000000000000..0aa897f45315 --- /dev/null +++ b/tools/perf/python/perf.pyi @@ -0,0 +1,481 @@ +"""Type stubs for the perf Python module.""" +from typing import Callable, Dict, List, Optional, Any, Iterator + +def config_get(name: str) -> Optional[str]: + """Get a configuration value from perf config. + + Args: + name: The configuration variable name (e.g., 'colors.top'). + + Returns: + The configuration value as a string, or None if not set. + """ + ... + +def metrics() -> List[Dict[str, str]]: + """Get a list of available metrics. + + Returns: + A list of dictionaries, each describing a metric. + """ + ... + +def syscall_name(sc_id: int) -> str: + """Convert a syscall number to its name. + + Args: + sc_id: The syscall number. + + Returns: + The name of the syscall. + """ + ... + +def syscall_id(name: str) -> int: + """Convert a syscall name to its number. + + Args: + name: The syscall name. + + Returns: + The number of the syscall. + """ + ... + +def parse_events( + event_string: str, + cpus: Optional[cpu_map] = None, + threads: Optional[Any] = None +) -> 'evlist': + """Parse an event string and return an evlist. + + Args: + event_string: The event string (e.g., 'cycles,instructions'). + cpus: Optional CPU map to bind events to. + threads: Optional thread map to bind events to. + + Returns: + An evlist containing the parsed events. + """ + ... + +class data: + """Represents a perf data file.""" + def __init__(self, path: str) -> None: ... + +class thread: + """Represents a thread in the system.""" + def comm(self) -> str: + """Get the command name of the thread.""" + ... + +class counts_values: + """Raw counter values.""" + val: int + ena: int + run: int + +class thread_map: + """Map of threads being monitored.""" + def __init__(self, pid: int = -1, tid: int = -1) -> None: + """Initialize a thread map. + + Args: + pid: Process ID to monitor (-1 for all). + tid: Thread ID to monitor (-1 for all). + """ + ... + def __len__(self) -> int: ... + def __getitem__(self, index: int) -> int: ... + def __iter__(self) -> Iterator[int]: ... + +class evsel: + """Event selector, represents a single event being monitored.""" + def __str__(self) -> str: + """Return string representation of the event.""" + ... + def open(self) -> None: + """Open the event selector file descriptor table.""" + ... + def read(self, cpu: int, thread: int) -> counts_values: + """Read counter values for a specific CPU and thread.""" + ... + ids: List[int] + def cpus(self) -> cpu_map: + """Get CPU map for this event.""" + ... + def threads(self) -> thread_map: + """Get thread map for this event.""" + ... + + +class sample_event: + """Represents a sample event from perf.""" + evsel: evsel + sample_cpu: int + sample_time: int + sample_pid: int + sample_comm: str + type: int + brstack: Optional['branch_stack'] + def __getattr__(self, name: str) -> Any: ... + +class branch_entry: + """Represents a branch entry in the branch stack. + + Attributes: + from_: Source address of the branch (corresponds to 'from' keyword). + to: Destination address of the branch. + mispred: True if the branch was mispredicted. + predicted: True if the branch was predicted. + in_tx: True if the branch was in a transaction. + abort: True if the branch was an abort. + cycles: Number of cycles since the last branch. + type: Type of branch. + """ + from_: int + to: int + mispred: bool + predicted: bool + in_tx: bool + abort: bool + cycles: int + type: int + +class branch_stack: + """Iterator over branch entries in the branch stack.""" + def __iter__(self) -> Iterator[branch_entry]: ... + def __next__(self) -> branch_entry: ... + +class stat_event: + """Represents a stat event from perf.""" + type: int + id: int + cpu: int + thread: int + val: int + ena: int + run: int + +class stat_round_event: + """Represents a stat round event from perf.""" + type: int + time: int + +class cpu_map: + """Map of CPUs being monitored.""" + def __init__(self, cpustr: Optional[str] = None) -> None: ... + def __len__(self) -> int: ... + def __getitem__(self, index: int) -> int: ... + def __iter__(self) -> Iterator[int]: ... + + +class evlist: + def open(self) -> None: + """Open the events in the list.""" + ... + def close(self) -> None: + """Close the events in the list.""" + ... + def mmap(self) -> None: + """Memory map the event buffers.""" + ... + def poll(self, timeout: int) -> int: + """Poll for events. + + Args: + timeout: Timeout in milliseconds. + + Returns: + Number of events ready. + """ + ... + def read_on_cpu(self, cpu: int) -> Optional[sample_event]: + """Read a sample event from a specific CPU. + + Args: + cpu: The CPU number. + + Returns: + A sample_event if available, or None. + """ + ... + def all_cpus(self) -> cpu_map: + """Get a cpu_map of all CPUs in the system.""" + ... + def metrics(self) -> List[str]: + """Get a list of metric names within the evlist.""" + ... + def compute_metric(self, metric: str, cpu: int, thread: int) -> float: + """Compute metric for given name, cpu and thread. + + Args: + metric: The metric name. + cpu: The CPU number. + thread: The thread ID. + + Returns: + The computed metric value. + """ + ... + def config(self) -> None: + """Configure the events in the list.""" + ... + def disable(self) -> None: + """Disable all events in the list.""" + ... + def enable(self) -> None: + """Enable all events in the list.""" + ... + def __iter__(self) -> Iterator[evsel]: + """Iterate over the events (evsel) in the list.""" + ... + + +class session: + def __init__( + self, + data: data, + sample: Optional[Callable[[sample_event], None]] = None, + stat: Optional[Callable[[Any, Optional[str]], None]] = None + ) -> None: + """Initialize a perf session. + + Args: + data: The perf data file to read. + sample: Callback for sample events. + stat: Callback for stat events. + """ + ... + def process_events(self) -> None: + """Process all events in the session.""" + ... + def process(self, pid: int) -> thread: + """Process events for a specific process.""" + ... + +# Event Types +TYPE_HARDWARE: int +"""Hardware event.""" + +TYPE_SOFTWARE: int +"""Software event.""" + +TYPE_TRACEPOINT: int +"""Tracepoint event.""" + +TYPE_HW_CACHE: int +"""Hardware cache event.""" + +TYPE_RAW: int +"""Raw hardware event.""" + +TYPE_BREAKPOINT: int +"""Breakpoint event.""" + + +# Hardware Counters +COUNT_HW_CPU_CYCLES: int +"""Total cycles. Be wary of what happens during CPU frequency scaling.""" + +COUNT_HW_INSTRUCTIONS: int +"""Retired instructions. Be careful, these can be affected by various issues, +most notably hardware interrupt counts.""" + +COUNT_HW_CACHE_REFERENCES: int +"""Cache accesses. Usually this indicates Last Level Cache accesses but this +may vary depending on your CPU.""" + +COUNT_HW_CACHE_MISSES: int +"""Cache misses. Usually this indicates Last Level Cache misses.""" + +COUNT_HW_BRANCH_INSTRUCTIONS: int +"""Retired branch instructions.""" + +COUNT_HW_BRANCH_MISSES: int +"""Mispredicted branch instructions.""" + +COUNT_HW_BUS_CYCLES: int +"""Bus cycles, which can be different from total cycles.""" + +COUNT_HW_STALLED_CYCLES_FRONTEND: int +"""Stalled cycles during issue [This event is an alias of idle-cycles-frontend].""" + +COUNT_HW_STALLED_CYCLES_BACKEND: int +"""Stalled cycles during retirement [This event is an alias of idle-cycles-backend].""" + +COUNT_HW_REF_CPU_CYCLES: int +"""Total cycles; not affected by CPU frequency scaling.""" + + +# Cache Counters +COUNT_HW_CACHE_L1D: int +"""Level 1 data cache.""" + +COUNT_HW_CACHE_L1I: int +"""Level 1 instruction cache.""" + +COUNT_HW_CACHE_LL: int +"""Last Level Cache.""" + +COUNT_HW_CACHE_DTLB: int +"""Data TLB.""" + +COUNT_HW_CACHE_ITLB: int +"""Instruction TLB.""" + +COUNT_HW_CACHE_BPU: int +"""Branch Processing Unit.""" + +COUNT_HW_CACHE_OP_READ: int +"""Read accesses.""" + +COUNT_HW_CACHE_OP_WRITE: int +"""Write accesses.""" + +COUNT_HW_CACHE_OP_PREFETCH: int +"""Prefetch accesses.""" + +COUNT_HW_CACHE_RESULT_ACCESS: int +"""Accesses.""" + +COUNT_HW_CACHE_RESULT_MISS: int +"""Misses.""" + + +# Software Counters +COUNT_SW_CPU_CLOCK: int +"""CPU clock event.""" + +COUNT_SW_TASK_CLOCK: int +"""Task clock event.""" + +COUNT_SW_PAGE_FAULTS: int +"""Page faults.""" + +COUNT_SW_CONTEXT_SWITCHES: int +"""Context switches.""" + +COUNT_SW_CPU_MIGRATIONS: int +"""CPU migrations.""" + +COUNT_SW_PAGE_FAULTS_MIN: int +"""Minor page faults.""" + +COUNT_SW_PAGE_FAULTS_MAJ: int +"""Major page faults.""" + +COUNT_SW_ALIGNMENT_FAULTS: int +"""Alignment faults.""" + +COUNT_SW_EMULATION_FAULTS: int +"""Emulation faults.""" + +COUNT_SW_DUMMY: int +"""Dummy event.""" + + +# Sample Fields +SAMPLE_IP: int +"""Instruction pointer.""" + +SAMPLE_TID: int +"""Process and thread ID.""" + +SAMPLE_TIME: int +"""Timestamp.""" + +SAMPLE_ADDR: int +"""Sampled address.""" + +SAMPLE_READ: int +"""Read barcode.""" + +SAMPLE_CALLCHAIN: int +"""Call chain.""" + +SAMPLE_ID: int +"""Unique ID.""" + +SAMPLE_CPU: int +"""CPU number.""" + +SAMPLE_PERIOD: int +"""Sample period.""" + +SAMPLE_STREAM_ID: int +"""Stream ID.""" + +SAMPLE_RAW: int +"""Raw sample.""" + + +# Format Fields +FORMAT_TOTAL_TIME_ENABLED: int +"""Total time enabled.""" + +FORMAT_TOTAL_TIME_RUNNING: int +"""Total time running.""" + +FORMAT_ID: int +"""Event ID.""" + +FORMAT_GROUP: int +"""Event group.""" + + +# Record Types +RECORD_MMAP: int +"""MMAP record. Contains header, pid, tid, addr, len, pgoff, filename, and sample_id.""" + +RECORD_LOST: int +"""Lost events record. Contains header, id, lost count, and sample_id.""" + +RECORD_COMM: int +"""COMM record. Contains header, pid, tid, comm, and sample_id.""" + +RECORD_EXIT: int +"""EXIT record. Contains header, pid, ppid, tid, ptid, time, and sample_id.""" + +RECORD_THROTTLE: int +"""THROTTLE record. Contains header, time, id, stream_id, and sample_id.""" + +RECORD_UNTHROTTLE: int +"""UNTHROTTLE record. Contains header, time, id, stream_id, and sample_id.""" + +RECORD_FORK: int +"""FORK record. Contains header, pid, ppid, tid, ptid, time, and sample_id.""" + +RECORD_READ: int +"""READ record. Contains header, and read values.""" + +RECORD_SAMPLE: int +"""SAMPLE record. Contains header, and sample data requested by sample_type.""" + +RECORD_MMAP2: int +"""MMAP2 record. Contains header, pid, tid, addr, len, pgoff, maj, min, ino, +ino_generation, prot, flags, filename, and sample_id.""" + +RECORD_AUX: int +"""AUX record. Contains header, aux_offset, aux_size, flags, and sample_id.""" + +RECORD_ITRACE_START: int +"""ITRACE_START record. Contains header, pid, tid, and sample_id.""" + +RECORD_LOST_SAMPLES: int +"""LOST_SAMPLES record. Contains header, lost count, and sample_id.""" + +RECORD_SWITCH: int +"""SWITCH record. Contains header, and sample_id.""" + +RECORD_SWITCH_CPU_WIDE: int +"""SWITCH_CPU_WIDE record. Contains header, and sample_id.""" + +RECORD_STAT: int +"""STAT record.""" + +RECORD_STAT_ROUND: int +"""STAT_ROUND record.""" + +RECORD_MISC_SWITCH_OUT: int +"""MISC_SWITCH_OUT record.""" -- 2.54.0.rc1.513.gad8abe7a5a-goog