PHOBOSLAB

Blog Home

Measuring Input Lag in Browsers

For games, the time between a key-press and the appropriate action happening on the screen can often decide over virtual life or death.

It is no surprise that game developers go to great length to reduce input lag as much as possible. Guitar Hero for instance even has an option to compensate for lag. One of the biggest time hogs these days seem to be displays, but a poorly written application or game can introduce a lot of lag as well.

The typical path a key-press travels – Keyboard » USB Driver » OS » Application – is bad enough as each of these layer can introduce some lag. Yet, JavaScript games have to go through an additional layer they have no control over: the browser – which in itself may have several layers that introduce lag until a JavaScript callback for a keydown event can be called.

I decided to try and measure this lag for different browsers to see if there's room for improvement. The good news: most browsers do a good job delivering input to JavaScript events as fast as possible. The bad news: Chrome does not.

I build a simple website that draws to a canvas element at 60 frames per second, counts the number of frames and captures input events. I used my camera (a Samsung NX200) to record video at 120 frames per second, then slowed the video down even further to have a close look at the results.

The response time from the command prompt was used as a baseline (I measured the same lag with Quake 3 and other native games): 5 frames or about ~83ms. This is pretty awful to begin with. I'm not really sure where all this lag comes from, but I blame the display. Since I measured all (Windows) browsers with the same setup, results are still comparable.

Firefox 14 had the fastest response time of only 5 frames, followed by IE9, Opera 12 and Safari 5.1.5 (Mac) with 6 frames. The real surprise here is Chrome's response time of 8 frames or 133ms – 50ms more than Firefox. This doesn't sound like much, but if you directly compare a real JavaScript game in Chrome and Firefox, you can definitely feel the difference.

The input lag for Mobile Safari on iOS6 is around the 5 frame, ~83ms mark as well. I also tried to measure the Android's "Browser" and the Chrome Beta on my Galaxy Nexus, but couldn't get accurate results.

Chrome on Android refused to render at more than 20 frames per second and the "Browser", while proclaiming to render at 60 frames per second, only really presented every fourth frame. This is clearly visible in the slow motion video – 4 boxes appear at the same time, instead of one after the other. This is also why HTML5 games in the "Browser" (damn, I hate that "name") still seem to stutter, even though they are "rendered" at 60 frames per second.

Android has a lot of catching up to do.

I build another simple website that behaves like Guitar Hero's lag calibration. As humans, we try to compensate for the lag ourselves by pressing a bit earlier, so the results from this aren't as accurate as measured with a camera, but you can clearly see and feel the difference between Chrome and about any other desktop browser.

Try it here: phoboslab.org/inputlag/

Update June 26th 2012

As suggested by Filip Svendsen in the comments, I made another video to show mouse input lag in Firefox 14 and Chrome 22. To make the lag easier to spot, I wrote a Python script to move the mouse cursor at constant speeds.

From the video, it's quite obvious that the mouse lag in Chrome is much higher than in Firefox. However, the movement looks much smoother in Chrome. I guess you can't have everything - at least not yet.

Tuesday, June 19th 2012

8 Comments:

#1 – NinjaWarrior1976 – Tuesday, June 19th 2012, 21:23

Nice video. The latency of Chrome's Canvas is a critical problem. I'm a big fun of shmups but I can't make them with Chrome!

We mush attack this issue with 1000 stars.
code.google.com/p/chromium/issues/detail?id=99171

#2Justin Dolske – Tuesday, June 19th 2012, 21:34

I'd be curious to see how the new Firefox for Android beta fares (www.mozilla.org/en-US/mobile/).

FWIW, I did a little hack a couple years ago to get some similar measurements with Firefox -- see blog.mozilla.org/dolske/2010/05/26/a-little-mouse-hack/. I don't think it resulted in any direct fixes, but there's some data and video floating around somewhere from making latency measurements with it.

#3 – Filip Svendsen – Saturday, June 23rd 2012, 14:14

Have you tried testing the lag between mousemove events and the movement of the cursor? For example, if you draw a cursor on a canvas with the position from mousemove events, and compare it to the position of the normal mouse cursor.

There is a HUGE delay in chrome, but basically none in firefox and IE9. This is a problem for some types of games.

It feels like a significantly larger delay than for keyboard events, even though you are actually removing some of the delay by comparing two things on screen (removes usb and other i/o latency). I don't have any hard numbers though.

Could you try measuring this jsfiddle with your camera? I'm afraid that getting good numbers for something like this will be harder.

jsfiddle.net/filipncs/fptur/1/embedded/result/

#4 – Filip Svendsen – Saturday, June 23rd 2012, 14:34

(New version that doesn't draw in the event handler. I'm still seeing the giant difference between chrome and other browsers though)

jsfiddle.net/filipncs/F6x8z/embedded/result/

#5 – fizzd – Monday, December 3rd 2012, 02:40

Thank you for this - I'll be linking to this page from my music game as a way of explaining why Chrome isn't suitable to be used when playing it. Thanks!

#6 – maurice smith – Saturday, February 23rd 2013, 17:24

Nice post! I'm a little confused though, so maybe you can clarify. You say that you recorded 120fps video (8.3ms/frame) but the lag non-browser games is "5 frames or about ~83ms". 5*8.3=41.5ms. By "frames" do you mean monitor rather than camera frames, where your monitor's refresh rate is 60Hz (16.7ms refresh interval)? Thanks in advance!

#7David Drew – Saturday, August 17th 2013, 02:02

I think I might have fixed this. What you need to do is hijack the game loop by turning the touch event into the driver for the game loop. Things like touchmove and mousemove are plenty fast, but they run out of sync with the game loop.

It works like this:

The game loop is set to an interval of 0 (so it's literally running as fast as it can).

Time is tracked between the last draw and the current draw. You use this to throttle the draw() call.

When you listen for mouse movement, you allow the mousemove listener to call draw() (instead of tick()).

When the input stops moving (not sure yet how to check for this... maybe check for two consecutive x,y that match?) you flip the loop back to the game.

Github: github.com/dclowd9901/NoLagCanvasInputPoC

#8 – Maxim – Sunday, August 18th 2013, 19:32

Another version that draws directly from the mouse event without "waiting" for the game loop:

jsfiddle.net/xQyKd/

On Ubuntu, Chrome seems to marginally beat Firefox both on lag and smoothness. Is this the case on other systems now, too?

David, I don't think this lag issue has anything to do with the game loop on my system: I see no difference between the tests that draw directly from the event and those that draw from the loop.

A video test of a native implementation would help sort things out. Is there as great of a delay when there's no browser between the mouse and the screen?

Post a Comment:

Comment: (Required)

(use <code> tags for preformatted text; URLs are recognized automatically)

Name: (Required)

URL:

Please type phoboslab into the following input field or enable Javascript. This is an anti-spam measure. Sorry for the inconvenience.