本文へ移動
cccskills
無料GitHub で公開

linux-perf

Use when collecting sampling profiles with perf record, reading perf report or perf annotate, measuring PMU counters with perf stat -e, or using PAPI instrumentation to interpret IPC, miss rates, MPKI, or memory bandwidth on Linux. Not for SVG rendering: use flamegraphs.

インストール方法を見る

含まれるファイル(3)

  • SKILL.md13.8 KB
  • agents/openai.yaml295 B
  • references/events.md4.1 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Linux perf and PMU counters

perf ships in the kernel source tree under tools/perf, so its feature set follows the running kernel line (mainline 7.2, LTS 6.18). This skill covers the three jobs perf does for a CPU-bound program: count hardware events with perf stat, sample where cycles go with perf record and perf report, and attribute samples to instructions with perf annotate. It also covers PAPI region instrumentation, counter-derived metrics, memory-bandwidth counters, and raw PMU event lookup.

Contract

FieldBound contract
TriggerA Linux program is slow or CPU-bound and the user wants hot functions, counter totals, or instruction-level attribution from perf, or asks for PAPI instrumentation, IPC, miss rates, MPKI, or counter-based memory bandwidth. Also fires on [unknown] frames, Permission denied from perf, or a request to feed perf data to a flamegraph pipeline.
AuthorityReversible local: writes only perf.data files (or the -o target), compiled or PAPI-instrumented test binaries, and PMU tool checkouts in the working directory; rollback is deleting those files. sysctl and MSR module changes are proposed to the user, never applied. No remote mutation.
Side effectProfile and counter data on disk. Counting mode (perf stat) adds negligible overhead; PAPI adds instrumentation overhead around the measured region; sampling mode slows the program by a small factor that depends on sample frequency and call-graph mode.
DoneThe report names the hot symbols with their sample share, every counter metric carries its formula, raw counts, workload, microarchitecture, and comparison it supports, and any unresolved frame is explained with its fix.

Inputs

  • Target program and a representative workload (required). Short programs need a longer input or a higher -F.
  • Debug symbols (required for symbol names and source lines): build with -g. For frame-pointer call graphs add -fno-omit-frame-pointer; otherwise use --call-graph dwarf.
  • CPU model (lscpu) and whether the host is virtualized: a VM often exposes no hardware events.
  • Value of /proc/sys/kernel/perf_event_paranoid (gathered by the skill). Meaning: 2 allows user-space measurement of the caller's own processes only, 1 adds kernel measurement, 0 adds CPU-wide events, -1 removes all restrictions. Values above 2 block unprivileged perf entirely.
  • A question: which function is hot, which counter or derived metric is high, which source line causes misses, or which instruction stalls. The question picks the subcommand or counter mode.
  • For PAPI: libpapi headers and library (-lpapi), PAPI 7.3.0 at grounding.

Procedure

  1. Check permissions. Read cat /proc/sys/kernel/perf_event_paranoid. If the value blocks the intended measurement, propose sudo sysctl -w kernel.perf_event_paranoid=1 for the session, or the persistent form echo 'kernel.perf_event_paranoid=1' | sudo tee /etc/sysctl.d/99-perf.conf followed by sudo sysctl -p /etc/sysctl.d/99-perf.conf. Wait for the user to apply it. Done when: perf can open the events the plan needs, or the user has declined and the plan is narrowed to what the current level allows.

  2. Build with symbols: gcc -g -O2 -fno-omit-frame-pointer -o prog main.c. Keep the optimization level of the real build, because a -O0 profile points at code that does not exist in production. Done when: nm prog | head shows symbols and the binary runs the workload.

  3. Counter mode. Confirm what the CPU exposes with perf list hw, perf list cache, and perf list pmu; the first prints generic hardware events, the second cache events, and the third CPU-specific names. If perf list hw is empty, the host is virtualized or the PMU is locked and only software events remain. Run perf stat ./prog for the default set, then perf stat -e cycles,instructions,cache-references,cache-misses,branches,branch-misses ./prog for named events. For cache and TLB pairs, use perf stat -e L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses ./prog and perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses ./prog. Use perf stat -r 5 -e instructions,cycles ./prog to average five runs and print the spread; attach to a live process with perf stat -p <pid> sleep 10. Group events that must be measured together in one -e list; when more events are requested than counters exist, perf multiplexes and scales them, and prints the percentage of time each was counted. Done when: the events for the chosen metric appear in perf list (or software-only operation is recorded), and raw counts for every event are recorded with the run spread.

    Read derived metrics as conditional signals, not verdicts:

    MetricFormulaReading
    IPCinstructions / cyclesCeiling is the core's issue width. Compare two builds on the same core; a memory-bound or pointer-chasing loop has a low IPC by nature, and a lower IPC after a change is the signal, not the level
    L1 miss rateL1-dcache-load-misses / L1-dcache-loadsMeaningful with the absolute miss count beside it; streaming through a large array raises it by design
    LLC miss rateLLC-load-misses / LLC-loadsHigh rate plus high absolute count means DRAM traffic; check bandwidth below
    Branch miss ratebranch-misses / branchesData-dependent branches drive it; if sorting the input lowers it, the branches are the cost
    MPKImisses / (instructions / 1000)Normalizes misses to work done; use it to compare builds with different instruction counts

    Done when: each metric carries its formula, raw counts, workload, CPU model, and the build comparison it supports.

    When whole-program totals are too coarse, use the PAPI region mode. The low-level API (the old PAPI_start_counters and PAPI_stop_counters are gone from PAPI 7.x) is:

    #include <papi.h>
    #include <stdio.h>
    
    int main(void) {
        int events[] = { PAPI_TOT_INS, PAPI_TOT_CYC, PAPI_L2_TCM, PAPI_BR_MSP };
        long long values[4];
        int set = PAPI_NULL;
    
        if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT) return 1;
        if (PAPI_create_eventset(&set) != PAPI_OK) return 1;
        for (int i = 0; i < 4; i++)
            if (PAPI_add_event(set, events[i]) != PAPI_OK) return 1;
    
        PAPI_start(set);
        do_work();
        PAPI_stop(set, values);
    
        printf("IPC %.2f  L2 misses %lld  branch mispredicts %lld\n",
               (double)values[0] / values[1], values[2], values[3]);
        return 0;
    }
    

    Build with gcc -O2 -g -o prog prog.c -lpapi. The high-level API wraps the same region in PAPI_hl_region_begin("name") and PAPI_hl_region_end("name") with events chosen through PAPI_EVENTS. papi_avail -a lists the presets this CPU supports (PAPI_TOT_INS, PAPI_TOT_CYC, PAPI_L1_DCM, PAPI_L2_TCM, PAPI_L3_TCM, PAPI_BR_MSP, PAPI_TLB_DM, PAPI_FP_INS, PAPI_VEC_INS); papi_native_avail lists native events. A preset absent from papi_avail -a fails in PAPI_add_event. Done when: the region's counts print and the preset list confirms each event.

    When LLC misses are high, measure memory bandwidth. Uncore IMC events count DRAM transactions: perf stat -e uncore_imc/cas_count_read/,uncore_imc/cas_count_write/ -a ./prog on Intel hosts that expose the uncore_imc PMU in perf list pmu; system-wide -a needs paranoid level 0 or root. Intel PCM (https://github.com/intel/pcm, built with cmake, binaries in build/bin) reports socket bandwidth with pcm-memory 1 and core metrics with pcm 1, both with a -csv mode. PCM reads MSRs and needs root or CAP_SYS_RAWIO, or its daemon mode for unprivileged readers. Done when: achieved bandwidth is recorded next to the platform peak.

    When generic names do not cover the question, reach raw events: perf list pmu prints the CPU's named events, and the raw form is perf stat -e cpu/event=0x..,umask=0x../. pmu-tools (git clone https://github.com/andikleen/pmu-tools, run ./ocperf.py from the checkout) translates vendor event names to raw codes; showevtinfo from libpfm4 lists what the library knows. Done when: the raw event's name and code are recorded together.

  4. Sample with perf record. Use perf record -F 999 -g ./prog for a frame-pointer call graph at 999 Hz (an odd frequency avoids lock-step with periodic timers). Use perf record -F 999 --call-graph dwarf ./prog when the binary or its libraries lack frame pointers; cap the copied stack with --call-graph dwarf,4096 if the data file grows too fast. Sample a specific event with -e cache-misses; for miss attribution use -e LLC-load-misses and add the :p or :pp suffix when the PMU supports precise sampling. Attach with -p <pid> sleep 30, sample all CPUs with -a, and name the output with -o app.perf.data. Done when: perf record prints the sample count and the data file exists.

  5. Read the report. perf report opens the TUI on perf.data; perf report -i app.perf.data reads a named file; perf report --stdio prints text; perf report --no-children shows self time instead of inclusive time; perf report --sort comm,dso,sym groups by process, library, and symbol. In the TUI, Enter expands a symbol, a annotates it, d filters by DSO, t filters by thread, and ? lists keys. Done when: the top symbols by self time are listed with their percentages.

  6. Annotate the hot symbol. perf annotate -i perf.data --symbol=<name> --stdio prints the disassembly with per-instruction sample shares; s in the TUI toggles source when debug info is present. A high share on a load instruction (mov, vmovdqa) marks a stall on that load, usually a cache miss. For miss attribution, the percentage next to a source line is the share of miss samples landing there; a loop body with a strided access pattern shows the load instruction at the top. Done when: the hottest instructions and source lines (or, for miss attribution, the top source lines by miss samples) are named.

  7. Watch live when the workload is long-running: sudo perf top -g or sudo perf top -p <pid>. Done when: the live view confirms or refutes the recorded hotspot.

  8. Export for a flamegraph: perf script -i perf.data > out.perf, then hand out.perf to flamegraphs (stackcollapse-perf.pl and flamegraph.pl). Done when: out.perf exists.

  9. Resolve any bad frames or empty output using the failure table below before reporting. Done when: no [unknown] frame remains in the top entries, or its cause is stated.

Event names to reach for: hardware cycles, instructions, cache-references, cache-misses, branches, branch-misses, stalled-cycles-frontend, stalled-cycles-backend; cache L1-dcache-loads, L1-dcache-load-misses, LLC-loads, LLC-load-misses, dTLB-load-misses; software context-switches, cpu-migrations, page-faults, major-faults; tracepoints such as sched:sched_switch (need paranoid level 0 or root). perf list prints what this CPU exposes; perf list hw, perf list cache, perf list sw, and perf list tracepoint filter by class. Raw PMU codes are CPU-specific, and :u, :k, :p, and :pp modifiers restrict counting or request precise sampling. Full event notes live in references/events.md.

Failure and recovery

FailureCauseFix
Permission denied or Error: Access to performance monitoring and observability operations is not permittedperf_event_paranoid above the needed levelPropose the sysctl change from step 1, or run the measurement with sudo
[unknown] framesNo frame pointers or no debug infoRebuild with -g -fno-omit-frame-pointer, or record with --call-graph dwarf
Kernel frames show as addressesKernel symbols hiddenRecord with sudo; kptr_restrict at 0 (/proc/sys/kernel/kptr_restrict) exposes /proc/kallsyms; install the kernel debug symbols package for the running kernel
Empty report for a short programToo few samplesRaise -F toward the value in kernel.perf_event_max_sample_rate, or lengthen the workload
DWARF unwinding is slow or the data file is hugeWhole user stack copied per sample--call-graph dwarf,4096 or a smaller size, or add frame pointers and use -g
Counter shows <not supported>Event absent on this CPU or virtualizedPick a name from perf list; in a VM only software events may exist
Counter shows <not counted> or a low multiplex percentageMore events than countersSplit the events across runs, or group the ones that must be read together
Miss rate looks alarmingAbsolute count is smallReport the count beside the rate; a rate on few references is noise
PAPI_add_event failsPreset not available or counter conflictCheck papi_avail -a; reduce the event set
Uncore events are missingPMU not exposed or paranoid level too highPropose paranoid level 0 or root for -a; use PCM or the vendor profiler (intel-vtune-amd-uprof)
Numbers differ run to runFrequency scaling, SMT sibling, or cache stateUse -r, pin with taskset, and report the spread

A partial profile or counter report is reported as partial: the report states which steps ran and which measurement is missing.

Output

A profile report containing the counter table from step 3 with formulas, raw counts, run spread, workload, CPU model, and the comparison it supports; the top symbols by self time from step 5 with percentages; the hot instructions and source lines from step 6; the bandwidth figure and platform peak when measured; the PAPI region output when instrumented; the path of every data file written; and any unresolved frame with its cause and fix.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when configuring ADC sampling time, DMA-driven ADC, calibration, or DAC channel setup on bare-metal MCUs. Not for the DMA stream itself: use dma-baremetal.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

af-xdp

無料

Use when creating AF_XDP sockets, configuring UMEM and XSK rings, writing an XDP redirect program, or choosing copy versus zero-copy mode. Not for full kernel bypass: use dpdk.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when a redacted, trimmed agent transcript must be appended to a GitHub PR or issue body, with human approval and preview. Not for automated or model-initiated insertion.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

agents-md

無料

Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential, publish, deploy, or irreversible changes.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

OutlineDriven のスキルをすべて見る

このスキルの問題を報告する