metal-gpu-trace
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PERF_ENV | No | `NAME=VALUE` pairs, separated by spaces, set for the recorded program. | |
| KEEP_RUNS | No | Keeps only the newest N recordings. | |
| KEEP_TRACE | No | `1` keeps each recording's `.trace`, for `trace_tables`, `trace_query` or Instruments. | |
| WINEPREFIX | No | The Wine prefix used when the call names none; `~/.wine` otherwise. | |
| METAL_TRACE_LOG | No | `off` silences the one-line stderr log per call. | |
| METAL_TRACE_OUT | No | Where recordings go. Give an absolute path: the default, `./perf-runs`, depends on the client's working directory. | |
| METAL_TRACE_READ | No | More directories the tools may read, separated by `:`. | |
| METAL_TRACE_WINE | No | The Wine directory (holding `bin/wine`) that `perf_record` uses when the call names none. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Records GPU use on Apple silicon with Metal System Trace. One recording runs at a time; keep other GPU work off the Mac while it records. Under Wine record 30 s or more: Wine's start-up takes part of the recording. A recording needs about 0.8 GB of free disk per second for Instruments' temporary files (26 GB for 30 s, 50 GB for 60 s); perf_record refuses to start without it. Reading a recording back takes 1 to 14 s per recorded second. Compare only recordings with 100 frames or more, and repeat a run before calling a change real. perf_baseline (or perf_baseline_record, which records them) saves several equal runs as a named reference and perf_check says whether a new run regressed against their range. perf_diagnose says whether a run splits its GPU work into too many short encoders, as translation layers do; perf_compare says how much two runs differ; skip_s on perf_compare, perf_gate and perf_panel leaves out the first seconds (start-up) of each run; perf_history follows FPS, hitches and memory across runs with one name prefix, oldest first; perf_gate says whether a run meets budgets you set (FPS floor, hitch or memory ceiling); perf_panel writes an HTML page to look at one or two runs in a browser.trace_tables and trace_query need the .trace, kept only with KEEP_TRACE=1. When perf_record ends it stops every program of its Wine prefix, or every process named like a native program. To compare native Metal with a translation layer without a game of one's own: workload_list, workload_fetch, then perf_record with workload and api (and example, for a workload that lists examples), or the compare-layer prompt. perf_sweep records one run per value of dim, example, api or an environment variable and fits GPU ms per frame on the value. memory_free_pct holds the whole Mac short of memory while recording (keep other work off it) and background throttles the program: repeat a run that uses either.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
| prompts | {} |
| resources | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| perf_recordA | Records |
| perf_baseline_recordA | Records the same program |
| perf_sweepA | Records the same program once per value of one variable (dim, example, api, size, or env:NAME for an environment
variable) and returns, per value, the median of FPS, 1 % low, GPU ms per frame and stutter, and with 3 or more
numeric values the straight line GPU ms per frame follows (fixed ms plus ms per draw for dim, per unit otherwise)
with its r2. With rounds above 1 the values run in opposite order every other round, so drift hits all alike.
Runs are named |
| perf_abA | Records the same program with two environments in the order A B B A (repeated |
| perf_attachA | Records a program that is already running, by pid or by a name in its command line (Game.exe under Wine),
for |
| perf_runsA | Lists the saved recordings, newest first, with frames, FPS, GPU ms per frame, memory peaks and the translation layer each ran on (fingerprint and Wine, or native). |
| perf_compareA | Compares two saved recordings (names from perf_runs), a the reference and b the run after a change: the
headline numbers (FPS, GPU ms, frame pacing, memory), then what changed in the GPU work and where: encoders and
command buffers per frame, the share of encoders under short_us, the GPU's idle time, and each encoder label's
count and GPU ms per frame, largest change first. layer says whether both ran on the same translation layer:
with different layers it compares layers, not one change. A Windows run against a Metal run has |
| perf_baselineA | Names a reference for perf_check, or lists them. With name and runs (names from perf_runs, several runs of the
same program recorded with no change between them), it saves copies of their summaries as the reference |
| perf_checkA | Judges a recording against a reference saved with perf_baseline: regressed when FPS falls under the
reference's lowest FPS by more than margin_pct, GPU ms per frame rises over its highest by more than margin_pct,
or encoders or command buffers per frame exceed its highest; improved when a number leaves the range the other
way and none regressed; same otherwise. Frame pacing, short encoders and GPU idle time are reported by the
comparison but do not decide: they vary too much between equal runs. A run from Windows against a Metal
reference (or the reverse) is judged on FPS alone. A reference saved with skip_s judges the run without its first
skip_s seconds too ( |
| perf_export_traceA | Writes a recording's GPU frames as a Chrome trace file, |
| perf_gateA | Checks a recording against budgets and says pass or fail: a floor for FPS and the 1% low, a ceiling for the stutter rate, the p95 GPU ms per frame, the hitch count and the peak Metal MiB. Give at least one. A number the recording lacks fails its budget (value null): a gate must not pass on missing data. Returns each budget with its limit, the value and whether it held. Use it as a bar a change must clear, where perf_check judges against equal runs. skip_s leaves out the first seconds of the recording (the start-up), as perf_compare does. |
| perf_historyA | Lists the recordings whose name starts with |
| perf_panelA | Writes one HTML file, |
| perf_diagnoseA | Says whether a saved recording splits its GPU work into too many short encoders, the pattern of translation layers such as DXMT, Mullion or MoltenVK, with the numbers behind it: encoders and command buffers per frame, the share of short encoders, the labels with the most GPU time and the GPU's idle time. Read the idle time together with the FPS: a program waiting for vsync idles too. Defaults come from bgfx 17-drawstress on an M1 Pro: 7 encoders per frame and 50% under 25 us under Mullion, 2 and 2% in native Metal. |
| trace_tablesA | Lists the data tables (schemas) a .trace recording holds; recordings keep their .trace only with KEEP_TRACE=1. |
| trace_countA | Counts the rows of several tables of a kept .trace, in all and per process, so a recording's useful tables show before reading them: a table with 0 rows needs another instrument or Xcode, not a bigger page. |
| trace_queryA | Returns one page of rows of one table of a .trace as {column: value}, optionally only one process's rows. |
| capture_summaryB | Reads a Metal .gputrace capture without Xcode: command buffers, encoders, draws, debug groups, and the 100 most frequent call ids out of calls_total. |
| capture_recordsA | Returns one page of the records of a .gputrace command stream, with their Metal call names when known. |
| gpu_familyA | Apple's published facts for one GPU family, by family ("Apple7") or chip ("M1 Pro"): its chips, what it adds, its limits, plus the limits shared by all families and the footnotes. Source URLs are in the result. |
| workload_listA | Lists the test programs workload_fetch can download, such as bgfx's drawstress: what each measures, its size, license and APIs, and whether it is already downloaded. |
| workload_fetchA | Downloads a test program from this project's GitHub releases once, checks its SHA-256 against the one this package pins, and keeps it in ~/Library/Caches/metal-gpu-trace; later calls reuse it. The programs are built from source by the project's workloads workflow. |
| presentmon_installA | Windows only: downloads Intel's PresentMon console application (MIT) from its GitHub release, checks its SHA-256 against the one this package pins, and keeps it in %LOCALAPPDATA%\metal-gpu-trace, where perf_record and perf_attach find it; later calls reuse it. It needs administrator rights or the Performance Log Users group to run. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| compare-layer | Records a test program in native Metal and under a translation layer, then diagnoses and compares both runs |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| Apple GPU families | Apple silicon GPU families Apple7 to Apple10: chips, first family with each feature, and limits that differ. Facts restated from Apple's public documents, not Apple's text. Check a device with MTLDevice.supportsFamily; families nest, so an Apple9 GPU also supports Apple7 and Apple8. |
| Apple7 GPU family | Apple's published facts for Apple7 |
| Apple8 GPU family | Apple's published facts for Apple8 |
| Apple9 GPU family | Apple's published facts for Apple9 |
| Apple10 GPU family | Apple's published facts for Apple10 |
TDQS
Scored across 23 tools
Despite many perf_* tools, each has a clearly distinct role: record, attach, sweep, A/B compare, baseline, check, gate, history, diagnose, panel, export, and run listing. Similar-sounding pairs like perf_baseline versus perf_baseline_record are differentiated by whether they consume existing runs or record new ones. The trace and capture tools are also cleanly separated by operation and artifact type.
The set follows a consistent snake_case convention with useful domain prefixes such as perf_, trace_, capture_, workload_, and gpu_. Names are not strictly verb_noun throughout—there are noun-style names like perf_runs, perf_history, and perf_panel—but the grouping is readable and predictable. Minor deviations do not impede tool selection.
At 23 tools the surface is large, but this is a broad GPU profiling suite covering recording, comparison, baselines, gates, traces, captures, workload setup, and environment inspection. Each tool appears to earn its place, though the count is slightly heavy and could be streamlined. It is not an extreme mismatch for the stated scope.
The tool set covers the main lifecycle: fetching workloads, recording or attaching, saving baselines, comparing, checking, gating, diagnosing, visualizing, exporting traces, and inspecting raw trace/capture data. The main noticeable gap is management of saved artifacts, such as deleting or renaming recordings and baselines. That is a minor omission rather than a blocker for core profiling workflows.