Fennec Alpha 2 is now available for download! Desktop versions are available too (Windows, OS X, Linux). While we added some good features in this alpha, the primary focus was performance. Faster startup. Faster page loading. Faster panning and UI interactions.
Faster, faster, faster!
Madhava made a nice video showing off Alpha 2. Even from the video, anyone who tried Alpha 1 can see that Alpha 2 is noticeably faster.
I thought I’d focus a bit on what we did to squeeze more speed out of Fennec, and the Mozilla platform in general. First, a big shout out to Taras Glek for finding slow spots and filing bugs to get them fixed. Taras worked tirelessly to find as many problem areas as he could.
Alpha 1 used a two layer system to implement panning. One layer panned the UI chrome – the URLbar, the tab sidebar and the browser control sidebar. Another layer, implemented in a XBL component, panned the web content. Both layers were children of a XUL
<stack>, which allowed us to position and float elements relative to each other. The “hand-off” between the two systems – when UI panning transitioned to content panning – was sloppy and chrome panning was not very smooth.
Alpha 2 combines the panning layers into a single system, still contained in a
<stack>. We removed the XBL component and now chrome and content pan together as a single unit. The result is much smoother panning. Also, the chrome UI parts are now located relative to the web content much better – in Alpha 1, the sidebars panned into view sooner than they should have.
I plan to cover more details of the Fennec architecture soon.
URL Autocomplete (Awesomebar)
We found that using
<panel> elements to float chrome UI over the main window was a performance problem. In fact, any XUL element that creates a native OS window under the covers slows things down. The awesomebar autocomplete list uses a
<panel>. We re-wrote the autocomplete list such that it was a
<vbox> in the main
<stack> and the results were dramatic. The list displays much faster.
We started with XUL similar to Firefox for our URLbar. We used a
<description> for the static caption and a
<textbox> to allow the user to type in a new URL. The elements occupied the same space, but only one was visible at a time. We used some JS code to hide/show the appropriate element.
We found that the process of showing/hiding the elements was taking a noticeable amount of time, affecting the perceived page loading time. We ended up removing the
<description> and we just toggle
readOnly on the
A similar situation occurred with the favicon indicator. We initially used the same
<stack> holding two
<image> elements – one for the throbber and another for the website’s favicon. Again, we were showing and hiding the images depending on situation. This time it was the
<stack> that was the slow down – creates a native OS window. So we removed it and page loading appeared to complete a little faster. We kept the two image elements because the load time for the swapping the favicon image with the throbber image eclipsed any benefits of removing the show/hide code.
We also restructured the way we handled
<link rel=""/> favicons to wait until the page fully loaded before updating the favicon indicator. Updating the indicator immediately, while the page was still loading, just caused the page load to take longer.
Canvas and Thumbnails
For panning and zooming performance, Fennec uses a
canvas element as the main display surface – not a
browser element. We copy the contents of the browser to the canvas. Updating the contents of a browser to a canvas is not cheap on mobile devices. Each
drawWindow call can take ~300-400ms. On the other hand,
drawImage is much faster – ~100ms. In Alpha 2, we switched to use
drawImage as much as we could when updating the tab thumbnails.
Alpha 2 also uses the new MozAfterPaint event to optimize all DHTML updates to the the main canvas display surface. Whenever the contents of the web page changes, for whatever reason, we only update the areas that actually changed. We don’t repaint the entire canvas.
Any work that occurs after the page loads is potentially bad for performance. Users like to start interacting with page content as soon as possible. We had some slow code that transformed phone numbers into
<a href="tel:555-123-4567"> links. The
tel: links can allow devices to auto-dial telephone numbers. The code was optimized quite a bit in Alpha 2 (see bug).
Various places in the platform code we found spots where file I/O was slowing Fennec down, usually on startup. As Taras said on IRC – “File I/O on the n810 is measured in milliseconds” – probably not just limited to the n810. So we tried to avoid useless I/O whenever we could. Startup improved from taking around 30 seconds (yes) for a first-time, cold start in Alpha 1 to around 7-10 seconds in Alpha 2. A warm start improved from taking around 13 seconds down to 4-5 seconds.
One spot in the Extension Manager code was checking for the existence of a file, which was never created unless you had extensions installed. That fix alone saved ~300ms during startup. XBL loading was also improved – saved 100-200ms during startup.
We still have more work to do – we are shooting for a ~3 second startup. Yes, we have already found several more changes we plan to make for the next release.
We made some significant improvements startup, panning and page loading. Take Fennec Alpha 2 for a spin, especially if you tried Alpha 1 and found it too slow.
The downside of the many changes we made, especially in the UI, will be extension breakage. Giorgio Maone, author of NoScript already discovered some breakage, but plans to have an updated version ready soon. Unfortunately, we will likely cause more breakage with the next release too. However, my hopes are that by soliciting feedback from the add-on developer community, we can get a stable XUL structure and JS API in place for the next release.