Trying to get my head around refresh rate

My game does not push high framerates, and that's OK: there's heavy calculation every frame, and it's not an action game.

But I'm trying to get my head around two weird phenomena:

1. Changing .setRefreshRate has a HUGE impact even though I never come NEAR the target refresh rate:

At setRefreshRate 20, I get ~ 10 fps
At setRefreshRate 30, I get ~ 14 fps
At setRefreshRate 40, I get ~ 16 fps
At setRefreshRate 50, I get ~ 18 fps... AND the fps is more steady AND less effected by adding/removing/optimizing various effects

2. Those are the numbers reported by .showfps and Device Info... but are visibly WAY higher than reality:

When it says ~14fps I'm visibly only getting 4 or 5 fps
When it says ! 18fps... it's much closer, too fast for me to count reliably, but I don't think 18.

After a day messing with removing effects to boost smoothness... and then putting them all back and just cranking up setRefreshRate... I'm already happy with the outcome... just confused about the causes. I'm doing next to nothing in coroutines FWIW—all the real work is in update().

Any insights?

One factor could be: how does Playdate deal with a "missed" refresh deadline?

Say I'm targeting 10 fps, but the work to generate the next frame takes more than 1/10 second. Say it takes 25% extra. When the work is done, what happens?

A) It immediately refreshes. You get frames lasting .125 seconds instead of the targeted .1.


B) It WAITS for the NEXT frame, adding even MORE delay. (So every frame is always a multiple of 1/10.) You get frames lasting .2 seconds even though .125 should be possible.

If (B) then I can see how using a refreshRate of 50 is the way to get best performance even when you know you'll never achieve close to that. (Battery aside.)

#2 still puzzles me.



I don’t have my playdate yet (hopefully sometime this month) so I can’t say if this still applies on OS2.0 but,
According to Matt Sephton (daily driver) the best refresh rate is no refresh rate limiter… see his blog post about that: Playdate hi frame rates

1 Like

I think perhaps the behaviour of the fps readout is unreliable if you're constantly exceeding the frame time. Ideally you should be targeting a frame rate of equal to higher than your game is running.

To echo the above comment, I would try running with setRefreshRate(0) and see what your actual frame rate is.

If you use that you'll get variable frame timings, which is sometimes not as bad as it sounds depending on your game.

1 Like

Agreed with Matt and above, a good thing to do in conjunction with setting it to unlocked framerate, would be to capture and log the frame time (from the beginning of your update function to the end) in milliseconds, and plot that. That should give you a real look at the execution time of your code, and whether it is fitting under a certain FPS envelope (e.g. 60fps = 1/60 = 16.667ms, 50fps = 1/50 ~ 20ms, 30fps = 1/33 ~ 33ms). In general its much better to think in terms of frame time, rather than FPS, as FPS scales somewhat un-intuitively, and frame time (or I call loop time) will give you vital information about the consistency of your performance, which in turn will help understand things like stuttering and other issues which come from inconsistent timings.

1 Like

Ooh! I'd overlooked that it could be set to 0! Definitely doing that in my case.

Nothing actually happens in my update loop itself, everything is running on a zillion timers, or triggered by input handlers. But when something happens, the quicker the better—and 0 insures that :+1:

1 Like

Fyi there is a function to stop the update loop altogether. It might be playdate.stop(). But I'm not sure whether timers will get triggered

1 Like

I think I still need to run timer.updateTimers() every update.

Framerate analysis tip: export a GIF from Simulator, and open it in Preview (on Mac) or some viewer that can step through frames.

This revealed multiple NEARLY identical frames in a row for each one I thought was a single frame.

THAT was the apparent inaccuracy in the FPS counter. I really was getting more refreshes than I could see without slow-mo. Not necessarily a problem, but important for understanding the reported values.

1 Like