Repository navigation
Debugging Tool WPA
← Debugging Tools and Commands
WPA is the interactive ETL analyzer used to discover the responsible process, thread, time interval, scheduling state, and GPU overlap before producing smaller scripted exports.
| Property | Details |
|---|---|
| Supported OS | Windows 8 or later. |
| Install | Install the Windows Performance Toolkit feature from the Windows ADK. |
| Verify | wpa.exe -help |
| Primary output | See the workflow below. |
WPA is the interactive analysis tool for ETL traces. It is useful when discovering which thread or interval deserves a narrower export.
The tables we have used most heavily are conceptually:
- CPU Usage (Sampled) / Samples by Thread Name;
- Thread Delays / scheduling transitions;
- GPU activity by process.
For a lag/stutter interval:
- restrict the timeline to the known measurement window;
- identify the xemu PID;
- identify the target thread by name or independent identity proof;
- compare sampled CPU with scheduled/off-CPU time;
- inspect GPU intervals over the same window;
- resolve hot xemu addresses separately using the exact executable/symbol artifact.
A sampled CPU table estimates where instruction-pointer samples landed.
Example from the retained PFIFO trace:
PFIFO sampled weight: 4,179.0205 ms
PFIFO precisely scheduled: 4,494.3294 ms
Those values answer different questions and should not be substituted for one another.
A useful thread partition is:
measurement window
= running
+ waiting
+ ready-for-scheduling
For the retained PFIFO interval:
running: 4.4943294 s
waiting: 15.4398723 s
ready: 0.0748441 s
- Running means the thread was scheduled on a CPU.
- Waiting means it was not runnable because it was blocked/waiting.
- Ready means it could run but the scheduler had not put it on a CPU yet.
A thread being off-CPU for 15 seconds does not mean Sleep() consumed 15 seconds of CPU, and it does not identify what dependency made it wait.
If GPU execution overlaps a PFIFO waiting interval, that does not prove PFIFO was waiting for that GPU execution.
The retained trace had substantial GPU/PFIFO-wait overlap. That was sufficient to justify deeper wait attribution, not sufficient to label every PFIFO wait a fence wait.
Do not automatically read an Old Wait Reason field at PFIFO switch-in as the reason PFIFO was waiting. In our exported scheduling data that field described the other outgoing thread at the switch-in boundary and was excluded from PFIFO cause attribution.
This section is intentionally repetitive because these mistakes have already cost investigation time.
Function X = 20% of samples on PFIFO
Means:
About 20% of the selected PFIFO sampled weight landed in Function X under the capture conditions.
It does not automatically mean:
- Function X consumes 20% of a frame;
- deleting Function X makes xemu 20% faster;
- Function X is the root cause;
- the same share exists on another renderer/game/hardware configuration.
PFIFO running = 4.49 s in a 20 s window
Means the thread was on-CPU for about 4.49 seconds in the selected interval.
It does not explain the remaining 15.5 seconds until waiting/ready states are separated.
Waiting means blocked/not runnable. Find the dependency before optimizing the wait mechanism.
A faster fence poll can make the polling loop cheaper without making the fence signal earlier.
Ready means runnable but unscheduled. This can point toward host scheduling/CPU contention rather than an emulator wait.
Temporal overlap is useful evidence for a hypothesis but does not prove causation.
A function called 100,000 times may still be cheap. Combine counts with cost or use the count only to justify a targeted experiment.
Tail metrics describe the slow end of the interval distribution. A higher average FPS with worse p99 can still feel more stuttery.
Always retain both central throughput and tail behavior for hitch-oriented work.
Our current runner's NV2A display-write cadence is a guest progress proxy, not rendered FPS or monitor-present FPS.
Label it as cadence, not FPS.
Always select the explicit measurement interval and exact xemu PID/TID. Process IDs and thread IDs are run-local. Save the analysis profile when its filters and columns become evidence.
Sampled CPU, scheduled running time, waiting time, ready time, and GPU execution answer different questions. Do not replace one with another or interpret temporal overlap as causation.
- Tool name and exact version.
- Source commit/tree and executable SHA-256.
- The complete command or saved profile used.
- Input artifact hashes and the explicitly selected time or address range.
- Raw output plus any derived report; do not retain only a screenshot or conclusion.
- Admission failures, warnings, dropped events, incomplete rows, or unsupported operations.
DSP tooling guide and navigation updated November 2, 2026 for experimental PR #384, source 8f51d237. Capture/replay usage and limits.
The earlier wiki-wide review was published November 1, 2026. Emulator source: b7140848. Reviewed wiki content: 1d2b671. Current status · Release availability · Publication process.
- Home
- Current status
- Stable versus main
- Implemented mechanisms
- Controls and defaults
- Measured results and limits
- Complete change register
- System
- CPU and vCPU
- Memory and DMA
- Graphics / NV2A
- APU and audio
- Timing and timers
- Platform and I/O
- Hardware observations
- Fidelity boundaries
- Methodology
- PGR2 routes
- Debugging lag / hot paths
- Tools and commands
- DSP capture, replay and fuzzing
- HLE readiness and public XISO proof
- Concurrent DSP shadow and OpenAL proof
- DSP HLE operation inventory
- DSP HLE fix examples and testing
- Development
- Upstream shortlist
- Wiki maintenance
- Research / retired work
- Optimization catalog
- Hot-path shortcuts
- Researched experiments
- Unproven proposal directory
- PR lessons
- September26 snapshot
Repository · PRs · Issues