Android and JavaScript and Webkit, Oh My!

First off let me state that Webkit is not the problem. Secondly, let me state that JavaScript is also not the problem. The problem is Android.

Let us pretend that you are working on an application and making heavy use of embedded webkit views. On IOS, you know this means you don't get Nitro, but the 4.2 engine is plenty fast enough to draw a canvas at 30fps. Let's also assume you are using DOM touch events, and handle touchstart, touchmove, touchstop, and touchcancel (which I have yet to see anywhere in my logs BTW). You would like to process one touch event every 33ms, so as to maintain the fidelity of your interface. Not too much to ask as the hardware on the Xoom is firing off native Android events for move every 5ms. But wait, it is not that easy.

WebViews on Android are a very nasty business. Webkit runs in a separate process, not thread, and all communication to your WebKit engine is brokered by a dalvik thread running parallel to your main UI thread. This EventHub thread translates Android messages into a queue of events that are fed to Webkit via a native binding. What this means is your WebKit view receives all input on a delay. This delay when added into the fudge factor timings used for the browser, 50ms between motion events(vs 5 native), 1000ms long press (but apparently 200ms on the Xoom breaking touchmove with one finger most of the time), and a turn around time of 60-100ms for the draw event, means it is effectively impossible to draw a webkit app at better than 16fps on the latest tablets.

While you can override most of these input settings by subclassing WebView and adding your own gesture recognizers, the 60+ms turn around time, and short circuit logic which drops frames that take "too long" to draw, often means you are effectively rate limited to 10fps, whenever you start dropping frames (if I remember correctly long draws are >100ms, but I need to check the source again). This sorts of long draws happen any time you pull an asset from SD or over the network. This is also why many apps seem to go unresponsive, because they aren't being drawn.

Webkit in Android is a kind of third class citizen. Reading the source it is clear that the Google Maps team is the most active in driving it's performance. But due to the constraint of having to integrate a graphics, layout, event, and programming engine inside of a Java environment with it's own peculiar idiosyncratic behavior, it falls down when it comes to HTML5 gaming. IOS does slightly better in that the interface for calling JavaScript from Objective-C is both well defined and easy to use. Where as the Android version is essentially JavaScript URLs or build your own adventure with the JavaScript bridge, which also once again relies on the EventHub to synchronize, and effectively batch events.

If you read stackoverflow enough you will also come across plenty of postings where people will complain about move events being batched, this integration is exactly the reason. Even on dual core devices you will see JavaScript processes (which actually do follow the chrome model and run in other processes) end up with additional translation layers as they too must pass events to the Webkit engine. I am still looking for a good way to work with the EventHub to make it perform adequately, but I'm afraid it might be far too late in the game to fix HTML5 performance on Honeycomb.