My first attempt to find the cause of the performance regression was using method tracing from Dalvik Debug Monitor Server (DDMS). In particular, I started tracing when the onKeyDown() method is called, and ended tracing when the call finishes. However, the total time consumption and the time distribution of the trace result looked almost identical to the result of a version of our app before the regression.
It occurred to me that the computation that slows down the key handling must be "posted" in MessageQueue and run in separate message loops. But what do I mean by that?
An Android app by default runs in a single main thread called UI thread. The UI thread is managed by a MessageQueue and a Looper. The message queue is the data structure to contain various tasks (called message) the app needs to execute. An example of a message could be redrawing the UI, handling key event, etc. The Looper, on the other hand, is simply a infinite loop that dispatch each message from the MessageQueue to a suitable Handler. The simplest form of a message is a Runnable and one can post such a Runnable to the MessageQueue to be executed later, by calling Handler.post() or Handler.postDelayed().
Even though the key handling method is not slowing our app down, it was very likely that some Runnables are posted during key handling. Since those posted Runnables will executes immediately after the key handling, they will occupy the UI thread and prevent it from handling the next key event and freezes the UI. This is when the users experience lag.
In order to find out the culprit Runnables, I used the Looper.dump() method. This method will dump all the queued message currently in the MessageQueue. By comparing the dump before and after onKeyDown() is called, it's easy to tell what are the new messages (Runnables) posted by onKeyDown(), as in the following snippet:
From the dump, I finally found out the regression cause and solved the problem. As a side note, one can also use Looper.setMessageLogging() method to log when a message is dispatched and finished. This was less useful in my case since Android system post many messages to the UI thread and it's hard to tell which ones are related to key handling.
No comments:
Post a Comment