Frametime: Why a 60 FPS Average Can Feel Worse Than a Flat 55
By Indie Kings | October 19, 2026
Updated October 19, 2026: Average frames per second is a rate measured over a window, while the number that decides whether a game feels smooth is the duration of its worst frame inside that window. A 60 FPS average assembled from a handful of long frames can feel rougher than a flat 55, and PresentMon-style capture exists to record the individual frames that an average throws away.
Image credit: GameTechDev/GitHub
Frametime is the unit, FPS is the summary
A frame is not an instant. It is a delivery that takes time, and the length of that time is the frametime, usually written in milliseconds. Frames per second is just the reciprocal of the average frametime, converted to a rate: 60 FPS means an average of 16.67 milliseconds per frame, and 30 FPS means 33.33 milliseconds.
That reciprocal relationship is why the two numbers carry different information. An average frametime preserves the cost of each frame before it is collapsed into a rate. An average FPS figure divides a frame count by an elapsed time, so a small number of very expensive frames can disappear into the total. Both describe the same window, but only one keeps the shape of the delivery.
Refresh rate supplies the deadline. A display running at 60 Hz asks for a new image every 16.67 milliseconds, so a frame that takes longer than that arrives late even if the average rate for the second looks healthy.
| Refresh rate | Frame budget | What one missed deadline costs |
|---|---|---|
| 60 Hz | 16.67 ms | 33.33 ms between presented frames, a 60 FPS cadence cut to 30 |
| 120 Hz | 8.33 ms | 16.67 ms, a 120 FPS cadence cut to 60 |
| 144 Hz | 6.94 ms | 13.89 ms, a 144 FPS cadence cut to 72 |
| 240 Hz | 4.17 ms | 8.33 ms, a 240 FPS cadence cut to 120 |
The table is arithmetic, not a measurement. It shows why the same absolute hitch reads differently on different displays: a 20 millisecond frame is a missed deadline at every rate listed, but it costs more refresh intervals at 240 Hz than at 60 Hz, and the visible jump in spacing is larger.
What 1% and 0.1% lows actually describe
A 1% low starts with the frametimes in a capture window, sorts them from slowest to fastest, and looks at the slowest one percent of frames by count. A 0.1% low does the same at a tighter cutoff. The result is a description of the tail, the frames that arrive late enough to be felt, rather than the middle of the distribution where the average lives.
Implementation details vary between tools, and the variation matters when comparing numbers. Some report the average duration of the worst one percent of frames. Some report the boundary value that separates that worst one percent from the rest. Some express the tail as an equivalent FPS by taking the reciprocal. All of those describe the same slow tail, but they are not interchangeable figures, so two 1% low numbers are only comparable when they come from the same method and a similar window length.
Window length changes what the percentile means. In a capture of 600 frames, one percent is six frames, which is enough to smooth over a single outlier. One tenth of a percent is 0.6 frames, so a 0.1% low over a short capture collapses toward the single worst frame in the sample. A longer capture gives the 0.1% figure more frames to work with, which is why a 0.1% low from a 30 second run and one from a 10 minute run should not be treated as the same statistic.
Percentiles also count frames, not seconds. Ten frames out of 600 is 1.7 percent of the frame count, but if each of those frames takes 75 milliseconds, they occupy 7.5 percent of the elapsed time. The tail is a small share of the frames and a larger share of the experience, which is exactly the asymmetry an average erases.
Why a 60 average can lose to a 55 average
Consider two hypothetical ten second windows, chosen to make the arithmetic visible rather than to describe any particular game. Window A delivers 550 frames at a steady 18.18 milliseconds each. That is 55.0 FPS, and the spacing never changes.
Window B delivers 600 frames in just under ten seconds, for about 60.6 FPS. Of those frames, 590 take 15.5 milliseconds and 10 take 75 milliseconds. The ten long frames are only 1.7 percent of the frame count, but they are 7.5 percent of the elapsed time, and each one is roughly four and a half refresh intervals at 60 Hz.
The average rate favors Window B. The tail does not. The worst one percent of Window B is six frames, all of them 75 milliseconds, so its 1% low is 75 milliseconds against 18.2 milliseconds for Window A. That is the whole argument in one comparison: the spikier window wins on the summary and loses on the part a player notices. The measure that matches the complaint is the worst frame in the window, not the rate across it.
This is also why an average FPS benchmark can be honest and still misleading. If the capture really did record 60.6 frames per second, the number is true. The failure is one of scope: the number answers how much work was completed per second, while the player is asking how long they waited between frames. Those questions have different answers whenever the frametimes are uneven.
How PresentMon-style capture sees a frame
PresentMon is a set of Windows tools for capturing and analyzing the high level performance characteristics of graphics applications, per its repository README. The project describes tracing CPU, GPU and display frame durations and latencies across DirectX, OpenGL and Vulkan, on different hardware, for both desktop and UWP applications.
The measurement starts below the game. Per the README, the PresentData library performs the lowest level collection and analysis of ETW events, the operating system's event tracing mechanism. The frame presentation process emits those events, so the capture can build a per frame timeline from what the system already records rather than from a counter the game chooses to expose. That timeline is made of individual frame events with durations and latencies attached, which is the raw material a percentile needs.
Three front ends sit on top of that collection layer. The console application collects CSV data from target applications. The service combines the ETW frame event analysis with hardware telemetry such as GPU power, temperature and utilization gathered from vendor APIs such as NVAPI, and exposes it through an API. The capture application provides a GUI overlay with realtime graphs and per frame CSV capture. The console and capture applications write per frame CSV data, and the service exposes the frame event analysis through an API, so a capture leaves behind a record of individual frames rather than a single summary number.
The timings inside a capture
The README names the metrics directly, and the names are worth knowing because they separate work done by the CPU, work done by the GPU, and time spent waiting for the display. A single frametime can therefore be decomposed instead of guessed at.
| Metric named in the README | What it times | Why it matters for stutter |
|---|---|---|
| CPUFrameTime | CPU time attributed to a frame | Shows CPU side cost, with a stated accuracy caveat on OpenGL and Vulkan |
| CPUFramePacingStall | Stall in CPU frame pacing | Reports as zero on OpenGL and Vulkan applications, per the README |
| msUntilRenderStart | Time until rendering starts | GPU execution metric, less accurate with hardware accelerated GPU scheduling enabled |
| msUntilRenderComplete | Time until rendering completes | Same scheduling caveat as above |
| msGPUActive | GPU active interval | Same caveat, and may read larger than true GPU work under that scheduling mode |
| DisplayLatency | Latency through to display | A different quantity from frame duration, and one an average FPS figure never shows |
| InputLatency | Latency from input | Listed by the README as not affected by the OpenGL and Vulkan CPU timing caveat |
The README is explicit about two accuracy limits, and both belong in any honest reading of a capture. Applications that report a runtime of Other, typical of OpenGL and Vulkan, have less instrumentation in the presentation path, so CPUFramePacingStall always reports zero and CPUFrameTime may be slightly less accurate. That inaccuracy carries into latency figures calculated from CPUFrameTime, including GPUBeginLatency, GPUEndLatency and DisplayLatency, but not InputLatency.
The second limit concerns hardware accelerated GPU scheduling. With that mode enabled, msUntilRenderStart, msUntilRenderComplete, msGPUActive and msGPUVideoActive may be later or larger than they should be. The README gives an example in which a GPU bound frame's msGPUActive reads about half a millisecond larger than the true GPU work duration, notes that the amount depends on the workload and GPU, and describes an improved solution as work in progress.
There is also a permissions requirement. PresentMon must run under a user in the Performance Log Users group, otherwise the trace session fails with access denied. Without administrator privilege the tool lacks complete process information for processes on other accounts or short lived processes, which appear as unknown and cannot be targeted by name.
Reading a capture without fooling yourself
Start with the window. A percentage is only as stable as the sample it is drawn from, and a 0.1% low from a short run is close to a single worst frame. Compare captures of similar length, from the same scene, with the same settings. A busy benchmark scene and an empty corridor produce different tails for reasons that have nothing to do with the hardware.
Compute the average rate from counts and elapsed time, not by averaging instantaneous FPS values. Averaging rates gives every sample equal weight regardless of how long it lasted, and it overstates the result when frame durations vary. Frame count divided by elapsed seconds is the average the rate is supposed to represent, and the per frame CSV makes that calculation straightforward.
Then read the tail next to the middle. An average frametime with a 1% low close to it describes a steady cadence. A wide gap between the two describes a window with hitches, even when the average looks strong. Adding the 0.1% low shows whether the worst moment was a single event or a recurring pattern.
Keep frame duration and latency separate in your head. A frame duration says how long one frame took. DisplayLatency says how long the path from the frame to the display took. A capture can show short frames and still show high display latency, and fixing one does not automatically fix the other.
Finally, respect the caveats above when comparing across APIs or scheduling modes. An OpenGL capture and a DirectX capture are not measuring CPU frame pacing the same way, and a hardware scheduled GPU changes the accuracy of the GPU execution metrics. Differences that fall inside those stated limits are not findings.
Our take
The industry habit of quoting a single average is less a lie than a bad summary, and the fix is not to abandon averages but to publish the tail beside them. A 1% low and a 0.1% low cost nothing extra once the per frame data exists, and they answer the question players actually ask. When a benchmark reports only an average, I read it as a claim about throughput, not about smoothness, and I wait for the frame data before forming an opinion about how the game feels.
FAQ
What is a 1% low in gaming?
It is a statistic built from the slowest one percent of frames in a capture window, sorted by frametime. It describes the tail of the distribution, the frames that arrive late enough to be felt, rather than the average frame.
Why can 60 FPS feel worse than 55 FPS?
Because the average hides the spacing. A 60 FPS window with a handful of 75 millisecond frames can have a far worse 1% low than a steady 55 FPS window, and the long gaps are what a player perceives as stutter.
Does PresentMon calculate 1% lows itself?
The README describes per frame CSV capture and overlay graphs of exposed metrics. Percentile lows are a calculation performed on those per frame durations, which is why the method and window length behind a published low matter.
What is the difference between frametime and FPS?
Frametime is how long one frame took, in milliseconds. FPS is a rate over a window, equal to the frame count divided by elapsed seconds, so it is the reciprocal of the average frametime rather than a record of any individual frame.
Why does PresentMon need Performance Log Users membership?
Per the README, the tool starts an ETW trace session, and that requires membership in the Performance Log Users group. Without it the session fails with access denied.
Are PresentMon's GPU timings exact?
No. The README states that GPU execution metrics are less accurate with hardware accelerated GPU scheduling enabled, and that CPU timing is slightly less accurate for OpenGL and Vulkan applications, which also affects latency figures derived from CPUFrameTime.
Bottom Line
The number that decides whether a game feels smooth is not frames per second but the worst frame in the window. Average FPS is a throughput figure, and it can be perfectly accurate while saying nothing useful about the long frame that interrupts an otherwise fast run. Frametime preserves what the average discards, 1% and 0.1% lows summarize the slow tail, and PresentMon-style capture records the per frame CPU, GPU and display timings those statistics are built from. A stable 55 can beat a spiky 60 because the eye notices the gap, not the total.
Sources
- GameTechDev, PresentMon repository and README (github.com/GameTechDev/PresentMon), accessed October 19, 2026
Related: CPU Performance Engineering Reading List: 16 Sections in Order [2026] | Valve Hands Deck Performance Data To Developers | Ls Addon Manager Brings DLSS 5 To Lossless Scaling