After a capture, presentmon hands you a CSV file with one row per frame and a stack of columns with names like MsUntilRenderComplete. It looks like a wall of numbers, but it is really a complete diary of how your game performed, frame by frame. Once you know what each column means and which few actually matter, you can read a presentmon CSV the way a reviewer does: average performance, worst moments, bottlenecks and all.
Open the file in a spreadsheet like Excel, Google Sheets or LibreOffice Calc, and work through this guide with your own capture in front of you.
The Columns, Translated
The classic format starts with identity columns, then gets into timing. Here is the plain-language version:
- Application and ProcessID: which program the frame came from, and its Windows process ID. Useful when a file holds more than one app.
- SwapChainAddress: an ID for the game’s rendering chain. Mostly ignore it unless you are comparing multiple windows of the same app.
- Runtime: the graphics API, shown as DX11, DX12, GL or VK. Confirms what your game actually ran on.
- SyncInterval, PresentFlags, AllowsTearing, PresentMode: details about how frames were presented, tied to VSync and display behavior. Handy for diagnosing tearing or odd pacing.
- Dropped: a flag for frames that were rendered but never reached the screen. Count these; they are stutter made visible.
- TimeInSeconds: when the frame happened, in seconds from the capture start. Your x-axis for any graph.
Then come the timing columns, all measured in milliseconds. These are the heart of the file, covered next.
The Timing Columns That Matter Most
MsBetweenPresents is the star. It is the time between this frame appearing and the previous one, in other words the frame time. Everything about smoothness derives from it. Keep the conversion table in your head: 16.7 ms is 60 FPS, 8.3 ms is 120 FPS, 6.9 ms is 144 FPS. A row with 33 ms was a frame that displayed at an effective 30 FPS, and if it sits among 8 ms rows, that is a spike you felt.
The supporting cast explains why frame times look the way they do:
- MsBetweenDisplayChange: time between changes on the display itself, close cousin of the frame time from the screen’s point of view.
- MsInPresentAPI: how long the frame spent inside the present call, the final hand-off step. Unusually high values can hint at blocking behavior.
- MsUntilRenderComplete: how long after the frame started until the GPU finished rendering it.
- MsUntilDisplayed: how long from the frame’s start until it actually showed on screen. Together with render time, it sketches your latency picture.
Newer captures and summaries also surface CPU busy, GPU busy and percentile figures, but in the raw CSV, MsBetweenPresents plus Dropped will answer most questions you bring to the data.
Turning Rows into Answers
Start simple. Average the MsBetweenPresents column and invert it (1000 divided by the average) to get your mean FPS. Then sort the column from largest to smallest and look at the top one percent of rows. Those worst frames are your 1% lows territory, and their average tells you how bad the bad moments were. Count the rows where Dropped is flagged to see how many frames never displayed.
Three quick checks reveal most stories:
- The spike hunt: scan the largest frame times. A handful of huge values in an otherwise tight file means occasional hitches, often shader compilation or asset loading.
- The drift check: compare average frame time in the first ten seconds against the last ten. A steady climb suggests thermals, memory pressure or a scene that gets heavier.
- The consistency check: if frame times alternate between two values (8 ms, 16 ms, 8 ms, 16 ms), the game is pacing unevenly, a classic judder pattern that averages hide completely.
Graph It: The Frame Time Plot
The single most useful thing you can do with the data is a line chart: TimeInSeconds on the x-axis, MsBetweenPresents on the y-axis. In a spreadsheet, select both columns and insert a line graph. A flat, low line means smooth. Spikes are stutters. A sawtooth pattern means unstable pacing.
This graph is the format you see in professional reviews, and it settles arguments instantly. Two systems with identical average FPS produce visibly different lines, and the calmer line is the one that felt better to play on. Save a graph image next to each important capture and you build a visual history of your PC’s performance.
Working with Big Files
A 60-second capture at high frame rates holds thousands of rows, and a long session can reach hundreds of thousands. Spreadsheets handle this fine for averages and sorting, but keep two habits. First, filter the Application column if your file caught more than the game. Second, never edit the original; save an analysis copy so your raw data stays untouched for future comparisons. If you used the -simple flag when capturing, your file already carries a trimmed column set that is easier to handle.
Percentiles, Explained with Your Own Data
Percentiles sound statistical, but the idea is simple and you can compute one by hand from your own file. Sort all your frame times from fastest to slowest. The value at the halfway point is the 50th percentile, the typical frame. The value that 99 percent of frames beat is the 99th percentile, the boundary of the worst one percent. Reviewers quote that worst slice because it describes the moments that break immersion: the hitches during a fight, the stutters in a busy city.
Converted back to FPS language, the worst one percent is your “1% low”. If your average frame time is 10 ms (100 FPS) but the 99th percentile is 25 ms, then one frame in a hundred took as long as a 40 FPS frame, and clusters of those are exactly what you perceive as stutter. Some analysts go further to the 99.9th percentile, the “0.1% low”, which catches the rarest, nastiest hitches.
In a spreadsheet, the practical route is a percentile function over the MsBetweenPresents column, or sorting the column in descending order and averaging the top one percent of rows. Either approach lands you in the same place. Compare this number across two captures before you compare averages; it changes more, it matters more, and it explains the feel of the game far better.
Pair it with the Dropped count and the frame time graph, and a CSV stops being raw data. It becomes a verdict: how fast, how smooth, and where it hurt.
A tiny worked example makes this concrete. Imagine ten consecutive frame times in milliseconds: 8, 8, 9, 8, 8, 31, 8, 9, 8, 8. The average is about 10.5 ms, which converts to roughly 95 FPS and sounds perfectly healthy. But look at the sixth frame: 31 ms is a 32 FPS moment, and in a real capture it would sit inside a stream of hundreds of frames just like it, a single hitch surrounded by smoothness. Your eyes catch that one frame because it breaks the rhythm. The average forgives it; the percentile and the graph do not. Multiply that pattern across a sixty-second file and you understand why experienced readers always sort the column and check the top rows before they believe any summary.
Conclusion
A presentmon CSV stops being intimidating once you anchor on three things: MsBetweenPresents for frame time, Dropped for missed frames, and TimeInSeconds to place events on a timeline. Average for the headline, the worst one percent for the truth, and a line graph for the story. With those reads, every capture becomes a clear answer about how smooth a game really was, and why.
Read next:
