Skip to content

FPS and jank

“Sixty FPS average” and “smooth” are different claims. A capture that averages 58 can contain a dropped frame every second, and users feel every one of them.

iOS presents frames on a fixed cadence — 16.7 ms on a 60 Hz screen, 8.3 ms on a 120 Hz ProMotion display. A frame is dropped when the work for it is not finished when the cadence comes round. The counter reports frames actually presented per second.

So on a 120 Hz device, a steady 60 is not a failure; it is ProMotion sitting at half rate, which is normal for static content. What is a failure is 120 falling to 40 for a moment while the user is dragging.

In a KeyMob capture, do this in order:

  1. Find the dips. Anywhere the line drops sharply and comes back.
  2. Note when they happen. During launch? On the first scroll? Every time an image loads?
  3. Read the other counters at that same moment. This is the diagnosis.
At the dip Likely cause
CPU spikes Work on the main thread — layout, JSON parsing, image decoding, a synchronous file read
GPU spikes, CPU flat Render-bound — overdraw, blurs, shadows, offscreen passes, too many layers
Memory jumps A large allocation, often decoding a full-resolution image to display a thumbnail
Network active Waiting on a request on the wrong thread
Nothing moves Something blocking outside your process, or thermal throttling
  • Image decoding on the main thread. Loading a 4000-pixel photo into a 200-pixel cell decodes the whole thing. Downsample before display.
  • Cell reuse that is not reuse. A list rebuilding views instead of recycling them shows as CPU that scales with scroll speed.
  • Blur and shadow. Both are cheap on a desktop GPU and expensive on a phone. Shadows on a moving view are the classic case: give them an explicit path.
  • Synchronous work in a scroll callback. Anything touching disk or the network during a drag will be visible.
  • Autolayout in deep hierarchies. Constraint solving grows faster than the view count.
  • Use the oldest device you support. A frame budget is a fixed 16.7 ms; a fast chip hides sloppy work that an old one will not.
  • Let the device cool. A throttled phone produces a stutter that no code change will fix.
  • Reproduce the same interaction each run. Same list, same distance, same speed.
  • Capture over the cable. Wi-Fi sampling introduces a jitter of its own, which is indistinguishable from the jitter you are hunting.

Some stutter never shows in FPS: a tap that takes 300 ms to respond, an animation that starts late. Watch the CPU trace and the live log around the interaction; a long gap in log output during a drag is often the clearest evidence you will get.

Performance monitoring · Live logs · Energy