What are some solid techniques to account for the gap between processing time and frame update ticks? In other words, the game/render loop looks like this:

game/render loop

Some important points:

  1. Tick timings are determined by the web api (roughly 16ms consistently)
  2. Workers could either be triggered at the start of each tick (first checking if the previous one finished) or run continuously in their own loop. I think running continuously is better if we can account for the gap, so as to not waste time being idle which could lead to skipped frames.
  3. Either way - the size of the gap will vary between updates. It's not constant

note this article is a good reference: https://gafferongames.com/post/fix_your_timestep/ ... I haven't really tried applying it yet and I'm not sure if it fits the web constraints exactly.


1 Answer 1


I'm not sure if this is much of an answer, but...

Roughly speaking, if you are finished the work and want to render it, then that happens on a set schedule. Your graphics (WebGL) calls buffer things to be done; on next vsync (typically, in a browser environment), those commands should all have reached the GPU so they can be effected.

You really want to ensure that gap is always reasonably sized, because if you are still buffering commands when the next vsync comes around, your display may show odd results (depends very much on your implementation specifics). Other than that, you don't have to worry about the gap as such since your buffered commands that have been sent to the GPU will simply be put into practice at the next scheduled vsync.

If you want to be very sure you are not still making commands across the system bus when the threshold (~16.7ms @ 60fps) is reached, just make sure your ticks always take way less than 16.7 milliseconds (depending how close you want to cut it). You could have a cut-off at say 15ms in. If you're doing this on e.g. RequestAnimationFrame, then you have that much time to get all your work done, and a 1.7ms safety buffer (but you need to test to be sure of what works for you). If the job doesn't look complete by that point, just don't schedule draw calls for it till next frame (or later frames, even). You should only be doing draw calls for data that is in a ready state.

TL;DR Ensure your processing and resultant draw calls complete well before the render period does, and you will be fine. Profiling your code is the best way to determine if that is the case.

  • \$\begingroup\$ Thanks :) Javascript is super slow - simply piping things through some transformations and doing bounds checking (i.e. pong) takes around ~7ms. If I'm understanding you correctly - even if it does go beyond that and drops a frame here or there, it shouldn't be that big of a deal since fluctuations of what should be constant speed within the frame range shouldn't be too noticeable? Maybe the visual oddity I'm seeing is less about that gap and more around some other mistake I made... will see if I can fix! Your insight is very much appreciated - marking it as the answer ;) \$\endgroup\$
    – davidkomer
    Commented Sep 12, 2017 at 17:15
  • \$\begingroup\$ @davidkomer I would definitely avoid having any main / render thread processing (such as collecting work from worker threads, or making WebGL calls) exceed the threshold. Sure, you can overshoot that, but it's not recommended. As for worker threads... obviously it makes no difference if they take 1ms or 1000ms. You should leave a gap, and it is normal for the gap duration to fluctuate from frame to frame. It could be about something else, yes... maybe start from a minimal test case and work back to where you are? Best of luck :) \$\endgroup\$
    – Engineer
    Commented Sep 12, 2017 at 17:58
  • \$\begingroup\$ Yes - I'm isolating the main/render thread to only be rendering (and sampling inputs) now. Experimentally it's using React which of course I'd never do for a real game ;) hehe but I'd be surprised if a simple setState()+view update takes a whole frame \$\endgroup\$
    – davidkomer
    Commented Sep 12, 2017 at 18:36
  • 1
    \$\begingroup\$ By the way - my numbers were totally off, I had a bug which was adding like 6ms. The actually round processing is far less than 1ms :) \$\endgroup\$
    – davidkomer
    Commented Sep 19, 2017 at 20:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .