Gmail for Mobile HTML5 Series: Suggestions for Better Performance
    
    
    
    
    On April 7th, Google launched a new version of Gmail for mobile
      for iPhone and Android-powered devices. We shared the behind-the-scenes story through this blog and decided to share more of our learnings
      in a brief series of follow-up blog posts. This week, I'll talk about a few small things you
      can do to improve performance of your HTML5-based applications. Our focus here will be on
      performance bottlenecks related to the database and AppCache.Optimizing Database PerformanceThere are
      hundreds of books written about optimizing SQL and database performance, so I won't bother to
      get into these details, but instead focus on things which are of particular interest for
      mobile HTML5 apps.
Problem: 
Creating and deleting tables is
      slow! It can take upwards of 200 ms to create or delete a table. This means a simple
      database schema with 10 tables can easily take 2-4 seconds (or more!) just to delete and
      recreate the tables. Since this often needs to be done at startup time, this really hurts your
      launch time.
Solution: 
Smart versioning and backwards
      compatible schema changes (whenever possible). A simple way of doing this is to have
      a VERSION table with a single row that includes the version number (e.g., 1.0). For
      backwards-compatible version changes, just update the number after the decimal (e.g., 1.1) and
      apply any updates to the schema. For changes that aren't backwards compatible, update the
      number before the decimal (e.g., 2.0) at which point you can drop all the tables and recreate
      them all. With a reasonable schema design to begin with, it should be very rare that a schema
      change is not backwards compatible and even if this happens every month or so, users should
      get to use your application 20, 30 even 100 times before they hit this startup delay again. If
      your schema changes very infrequently, a simple 1, 2, 3 versioning scheme will probably work
      fine; just make sure to only recreate the database when the version changes!
Problem: 
Queries are slow! Queries are faster than creates and
      updates, but they can still take 100ms-150ms to execute. It's not uncommon for traditional
      applications to execute dozens or even hundreds of queries at startup – on mobile this is not
      an option. 
Solution: 
Defer and/or combine queries.
      Any queries that can be deferred from startup (or at any other significant point in the
      application) should be deferred until the data is absolutely needed. Adding 2-3 more queries
      on a user-driven operation can turn an action from appearing instantaneous to feeling
      unresponsive. Any queries that are performed at startup should be optimized to require as few
      hits to the database as possible. For example, if you're storing data about books and
      magazines, you could use the following two queries to get all the authors along with the
      number of books and magazine articles they've writen:
SELECT Author, COUNT(*) as NumArticles
FROM Magazines
GROUP BY Author
ORDER BY NumArticles;
SELECT Author,
      COUNT(*) as NumBooks
FROM Books
GROUP BY Author
ORDER BY
      NumBooks;This will work fine, but the additional query
      will generally cost you about 100-200 ms over a different (albeit less pretty) query
      like:
SELECT Author, NumPublications,
      PubType
FROM (
 SELECT Author, COUNT(*) as NumPublications, 'Magazine'
      as PubType, 0 as SortIndex
 FROM Magazines
 GROUP BY Author
      UNION
 SELECT Author, COUNT(*) as NumPublications, 'Book' as PubType, 1 as
      SortIndex
 FROM Books
 GROUP BY Author
)
ORDER BY
      SortIndex, NumPublications;This will return all the
      entries we want, with the magazine entries first in increasing order of number of articles,
      followed by the book entries, in increasing order of the number of books. This is a toy
      example and there are clearly other ways of improving this, such as merging the Magazines and
      Books tables, but this type of scenario shows up all the time. There's always a trade-off
      between simplicity and speed when dealing with databases, but in the case of HTML5 on mobile,
      this trade-off is even more important.
Problem: 
Multiple
      updates is slow! Solution: 
Use Triggers whenever
      possible. When the result of a database update requires updating other rows in the
      database, try to do it via SQL triggers. For example, let's say you have a table called Books
      listing all the books you own and another called Authors storing the names of all the authors
      of books you own. If you give a book away, you'll want to remove it from the Books table.
      However, if this was the only book you owned by that author, you would also want to remove the
      author from the Authors table. This can be done with two UPDATE statements, but a "better" way
      is to write a trigger that automatically deletes the author from the Authors table when the
      last book by this author is removed. This will execute faster and because triggers happen
      asynchronously in the background, it will have less of an impact on the UI than executing two
      statements. Here's an example of a simple trigger for this case:
CREATE TRIGGER IF NOT EXISTS RemoveAuthor
AFTER DELETE
      ON Books
BEGIN
 DELETE FROM Authors
 WHERE Author NOT
      IN
 (SELECT Author
 FROM Books);
END;
We'll get into more detail on triggers and how to use them in
      another performance post to come.
Optimizing AppCache
      PerformanceProblem: 
Logging in is slow!
      Solution: Avoid redirects to the login page. App-Cache is great
      because it can launch the application without needing to hit the network, which makes it much
      faster and allows you to launch offline. One problem you might encounter though, is that the
      application will launch and then you'll need to hit the network to get some data for the
      current user. At this point you'll have to check that the user is authenticated and it might
      turn out that they're not (e.g., their cookies might have expired or have been deleted). One
      option is to redirect the user to a login page somewhere, allow him to authenticate and then
      redirect him back to the application. Regardless of whether or not the login page is listed in
      the manifest, when it redirects back to your application, the entire application will reload.
      A nicer approach is for the application itself to display an authentication interface which
      sends the credentials and does the authentication seamlessly in the background. This will
      avoid any additional reloads of the application and makes everything feel faster and better
      integrated.
Problem: 
AppCache reloading causes my app to be
      slow! Solution: 
List as few URLs in the manifest as
      possible. In a 
series of posts on code.google.com, we talked about the HTML5 AppCache
      manifest file. An important aspect of the manifest file is that when the version gets updated,
      all the URLs listed in the file are fetched again. This happens in the background while the
      user is using the application, but opening all these network connections and transferring all
      that data can cause the application to slow down considerably during this process. Try to
      setup your application so that all the resources can be fetched from as few URLs as possible
      to speed up the manifest download and minimize this effect. Of course you could also just
      never update your manifest version, but what's the point of having rapid development if you
      never make any changes?

That's a
      brief intro to some performance considerations when developing HTML5 applications. These are
      all issues that we ran into ourselves and have either fixed or are in the process of fixing in
      our application. I hope this helps you to avoid some of the issues we ran into and makes your
      application blazing fast!
We plan to write several more performance
      related posts in the future, but for now stay tuned for next post where we'll discuss the
      cache pattern for building offline capable web applications.
By Derek Phillips, Software Engineer,
      Google MobilePrevious posts from Gmail for
      Mobile HTML5 SeriesHTML5 and Webkit pave the way for mobile web applications
Using AppCache to launch offline - Part 1
Using AppCache to launch offline - Part 2
Using AppCache to launch offline - Part 3
A Common API for Web Storage