Skip to content

Debugging Tool WPA

Mainkill1 edited this page Sep 21, 2026 · 1 revision

Windows Performance Analyzer (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.

When to use it

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.

What to inspect first

For a lag/stutter interval:

  1. restrict the timeline to the known measurement window;
  2. identify the xemu PID;
  3. identify the target thread by name or independent identity proof;
  4. compare sampled CPU with scheduled/off-CPU time;
  5. inspect GPU intervals over the same window;
  6. resolve hot xemu addresses separately using the exact executable/symbol artifact.

Sampled CPU is not scheduled CPU time

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.

Running, waiting, and ready are different states

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

Interpret carefully

  • 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.

GPU overlap is correlation, not dependency

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.

Wait-reason trap

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.


Reading common profiling numbers correctly

This section is intentionally repetitive because these mistakes have already cost investigation time.

Sample percentage

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.

Scheduled-running time

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 time

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 time

Ready means runnable but unscheduled. This can point toward host scheduling/CPU contention rather than an emulator wait.

GPU execution overlap

Temporal overlap is useful evidence for a hypothesis but does not prove causation.

Call counts

A function called 100,000 times may still be cheap. Combine counts with cost or use the count only to justify a targeted experiment.

p95 / p99

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.

Display-write cadence

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.


Boundaries and common mistakes

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.

Evidence to retain

  • 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.

Official references

Related xemu guides

Clone this wiki locally