Thursday, July 9th, 2009

Lessons from Gmail: Using Timers Effectively

Category: JavaScript

Neil Thomas of the Gmail for Mobile team keeps coming with great information on lessons learned. The latest discusses timers, and how to use them effectively (setTimeout/setInterval).

There are old questions here…. should you use lots of timers, or use one uber-timer that coordinates life? Here are some thoughts from Neil:

When I first started working on the new version of Gmail for mobile, the application used only a couple of timers. As we continued adding more and more features, the number of timers grew. We were curious about the performance implications: would 10 concurrent timers make the app feel slow? How about 100? How would the performance of many low-frequency timers compare to a single high-frequency timer?

To answer these questions, we conducted a few experiments. We injected some extra code into a development build of Gmail that created a lot of different timers, each of which just performed some simple calculations. Then we fired up the app on an iPhone 3G and Android G1 (both running the latest version of their respective firmware) and observed the performance. Note that although we could have just created a separate test page for this, we chose to inject the code right into our app so we could see how fast it would be to read and process mail with all those timers running.

Here’s what we learned. With low-frequency timers — timers with a delay of one second or more — we could create many timers without significantly degrading performance on either device. Even with 100 timers scheduled, our app was not noticeably less responsive. With high-frequency timers, however, the story was exactly the opposite. A few timers firing every 100-200 ms was sufficient to make our UI feel sluggish.

This led us to take a mixed approach with the timers we use in our application. For timers that have a reasonably long delay, we just freely create new timers wherever they are needed. However, for timers that need to execute many times each second, we consolidate all of the work into a single global high-frequency timer.

He then goes on to discuss the nice trick to tell if an application has come back from a sleeping state (and thus, maybe you want to call home and sync):

One neat application of a high-frequency timer is to detect when the device has been woken from sleep. When your application is put to sleep — either because the device is put into sleep mode or because the user has navigated away from the browser to another application — time, as perceived by your app, pauses. No timers fire until the user navigates back to your app and it wakes up. By keeping a close eye on the actual time that elapses between high-frequency timer ticks, you can detect when the app wakes from sleep.

First, create a high-frequency timer, as described above. In your timer, call a function that keeps track of the time between ticks:

javascript

  1. // The time, in ms, that must be "missed" before we
  2. // assume the app was put to sleep.
  3. var THRESHOLD = 10000;
  4.  
  5. var lastTick_;
  6. detectWakeFromSleep_ = function() {
  7.  var now = new Date().getTime();
  8.  var delta = now - this.lastTick_;
  9.  if (delta > THRESHOLD) {
  10.    // The app probably just woke up after being asleep.
  11.    fetchUpdatedData();
  12.  }
  13.  lastTick_ = now;
  14. };

Now your users will always have the latest data available when they return to your app without having to manually perform a refresh!

We recently ran into timer fun, as Ben mentioned on his directory post. He put together a nice little timing framework that is DOM agnostic that lets you have some fun with setting frameworks. There are other frameworks out there of course, especially when you get into the DOM (dojo.Animation can be used in the abstract, and there are then DOM specific impls on top).

Robert O’Callahan has been playing around with the idea of a framework in the browser too, with mozRequestAnimationFrame. Fun :)

Posted by Dion Almaer at 6:13 am
1 Comment

++++-
4.2 rating from 38 votes

1 Comment »

Comments feed TrackBack URI

this is a very interesting read for anyone doing continuous updates in the browser, and i recommend reading both http://googlecode.blogspot.com/2009/07/gmail-for-mobile-html5-series-using.html and http://ejohn.org/blog/how-javascript-timers-work/ .

i’ve found the single most important piece of advice in this field is, “when you can not be very sure that the code called by setInterval(f,dt0) will finish in clearly less than dt0 milliseconds, consider to use setTimeout(f,dt1) instead (from within f itself to keep the process running)”. this will give at least dt1 milliseconds to your other browser processes to execute so a freeze becomes less likely. you may want to check elapsed time before calling setTimeout from within f so you can add more delay in case execution was swift.

Comment by loveencounterflow — July 14, 2009

Leave a comment

You must be logged in to post a comment.