1. JavaScript speedups in Firefox 3.6

    This post was written by David Mandelin who works on Mozilla’s JavaScript team.

    Firefox 3.5 introduced TraceMonkey, our new JavaScript engine that traces loops and JIT compiles them to native (x86/ARM) code. Many JavaScript programs ran 3-4x faster in TraceMonkey compared to Firefox 3. (See our previous article for technical details.)

    For JavaScript performance in Firefox 3.6, we focused on the areas that we thought needed further improvement the most:

    • Some JavaScript code was not trace-compiled in Firefox 3.5. Tracing was disabled by default for Firefox UI JavaScript and add-on JavaScript, so those programs did not benefit from tracing. Also, many advanced JavaScript features were not trace-compiled. For Firefox 3.6, we wanted to trace more programs and more JS features.
    • Animations coded with JavaScript were often choppy because of garbage collection pauses. We wanted to improve GC performance to make pauses shorter and animations smoother.

    In this article, I’ll explain the most important JS performance improvements that come with Firefox 3.6. I’ll focus on listing what kinds of JS code get faster, including sample programs that show the improvements Fx3.6 makes over Fx3.5.

    JIT for Browser UI JavaScript

    Firefox runs JavaScript code in one of two contexts:content and chrome (no relation to Google Chrome). JavaScript that is part of web content runs in a content context. JavaScript that is part of the browser UI or browser add-ons runs in a chrome context and has extra privileges. For example, chrome JS can alter the main browser UI, but content JS is not allowed to.

    The TraceMonkey JIT can be enabled or disabled separately for content and chrome JS using about:config. Because bugs affecting chrome JS are a greater risk for security and reliability, in Firefox 3.5 we chose to disable the JIT for chrome JS by default. After extensive testing, we’ve decide to enable the JIT for chrome JS by default, something we did not have time to fully investigate for Fx3.5. Turning on the JIT for chrome should make the JS behind the Firefox UI and add-ons run faster. This difference is probably not very noticeable for general browser usage, because the UI was designed and coded to perform well with the older JS engines. The difference should be more noticeable for add-ons that do heavy JS computation.

    Option Fx3.5 Default Fx3.6 Default
    javascript.options.jit.chrome false true
    javascript.options.jit.content true true
    about:config options for the JIT

    Garbage Collector Performance

    JavaScript is a garbage-collected language, so periodically the JavaScript engine must reclaim unused memory. Our garbage collector (GC) pauses all JavaScript programs while it works. This is fine as long as the pauses are “short”. But if the pauses are even a little too long, they can make animations jerky. Animations need to run at 30-60 frames per second to look smooth, which means it should take no longer than 17-33 ms to render one frame. Thus, GC pauses longer than 40 ms cause jerkiness, while pauses under 10 ms should be almost unnoticeable. In Firefox 3.5, pause times were noticeably long, and JavaScript animations are increasingly common on the web, so reducing pause times was a major goal for JavaScript in Firefox 3.6.

    Demo: GC Pauses and Animation

    Demo.
    The spinning dial animation shown here illustrates pause times. Besides animating the dial, this demo creates one million 100-character strings per second, so it requires frequent GC. The frame delay meter gives the average time between frames in milliseconds. The estimated GC delay meter gives the average estimated GC delay, based on the assumption that if a frame has a delay of 1.7 times the average delay or more, then exactly one GC ran during that frame. (This procedure may not be valid for other browsers, so it is not valid for comparing different browsers. Note also that the GC time also depends on other live JavaScript sessions, so for a direct comparison of two browsers, have the same tabs open in each.) On my machine, I get an estimated GC delay of about 80 ms in Fx3.5, but only 30 ms in Fx3.6.

    But it’s a lot easier to see the difference by opening the demo in Fx3.5, watching it a bit, and then trying it in Fx3.6.
    In Fx3.5, I see frequent pauses and the animation looks noticeably jerky. In Fx3.6, it looks pretty smooth, and it’s hard for me even to tell exactly when the GC is running.

    How Fx3.6 does it better. We’ve made many improvements to the garbage collector and memory allocator. I want to give a little more technical details on the big two changes that really cut our pause times.

    First, we noticed that a large fraction of the pause time was spent calling free to reclaim the unused memory. We can’t do much to make freeing memory faster, but we realized we could do it on a separate thread. In Fx3.6, the main JS thread simply adds unused memory chunks to a queue, and another thread frees them during idle time or on a separate processor. This means machines with 2 or more cores will benefit more from this change. But even when one core, freeing might be delayed to an idle time when it will not affect scripts.

    Second, we knew that in Fx3.5 running GC clears out all the native code compiled by the JIT as well as some other caches that speed up JS. The reason is that the tracing JIT and GC did not know about each other, so if the GC ran, it might reclaim objects being used by a compiled trace. The result was that immediately after a GC, JS ran a bit slower as the caches and compiled traces were built back up. This would be experienced as either an extended GC pause or a brief hiccup of slow animation right after the GC pause. In Fx3.6, we taught the GC and the JIT to work together, and now the GC does not clear caches or wipe out native code, so it resumes running normally right after GC.

    Tracing More JavaScript Constructs

    In my article on TraceMonkey for the Fx3.5 release, I noted that certain code constructs, such as the arguments object, were not traced and did not get performance improvements from the JIT. A major goal for JS in Fx3.6 was to trace more stuff, so more programs can run faster. We do trace more stuff now, in particular:

    • DOM Properties. DOM objects are special and harder for the trace compiler to work with. For Fx3.5, we implemented tracing of DOM methods, but not DOM properties. Now we trace DOM properties (and other “native” C++ getters and setters) as well. We still do not trace scripted getters and setters.
    • Closures. Fx3.5 traced only a few operations involving closures (by which I mean functions that refer to variables defined in lexically enclosing functions). Fx3.6 can trace more programs that use closures. The main operation that is still not traced yet is creating an anonymous function that modifies closure variables. But calling such a function and actually writing to the closure variables are traced.
    • arguments. We now trace most common uses of the arguments keyword. “Exotic” uses, such as setting elements of arguments, are not traced.
    • switch. We have improved performance when tracing switch statements that use densely packed numeric case labels. These are particularly important for emulators and VMs.

    These improvements are particularly important for jQuery and Dromaeo, which heavily use arguments, closures, and the DOM. I suspect many other complex JavaScript applications will also benefit. For example, we recently heard from the author that this R-tree library performs much better in Fx3.6.

    Here is a pair of demos of new things we trace. The first sets a DOM property in a loop. The second calls a sum function implemented with arguments I get a speedup of about 2x for both of them in Fx3.6 vs. Fx3.5.

    Demo: Fx3.6 Tracing DOM properties and arguments


    DOM Property Set:

    Sum using arguments:

    String and RegExp Improvements

    Fx3.6 includes several improvements to string and regular expression performance. For example, the regexp JIT compiler now supports a larger class of regular expressions, including the ever-popular \w+. We also made some of our basic operations faster, like indexOf, match, and search. Finally, we made concatenating sequences of several strings inside a function (a common operation in building up HTML or other kinds of textual output) much faster.

    Technical aside on how we made string concatenation faster: The C++ function that concatenates two strings S1 and S2 does this: Allocate a buffer big enough to hold the result, then copy the characters of S1 and S2 into the buffer. To concatenate more than two strings, as in JS s + "foo" + t, Fx3.5 simply concatenates two at a time from left to right.

    Using the Fx3.5 algorithm, to concatenate N strings each of length K, we need to do N-1 memory allocations, and all but one of them are for temporary strings. Worse, the first two input strings are copied N-1 times, the next one is copied N-2 times, and so on. The total number of characters copied is K(N-1)(N+2)/2, which is O(N^2).

    Clearly, we can do a lot better. The minimum work we can do is to copy each input string exactly once to the output string, for a total of KN characters copied. Fx3.6 achieves this by detecting sequences of concatenation in JS programs and combining the entire sequence into one operation that uses the optimal algorithm.

    Here are a few string benchmarks you can try that are faster in Fx3.6:

    Demo: Fx3.6 String Operations


    /\w+/:

    indexOf('foo'):

    match('foo'):

    Build HTML:

    Final Thoughts and Next Steps

    We also made a lot of little improvements that don't fit into the big categories above. Most importantly, Adobe, Mozilla, Intel, Sun, and other contributors continue to improve nanojit, the compiler back-end used by TraceMonkey. We have improved its use of memory, made trace recording and compiling faster, and also improved the speed of the generated native code. A better nanojit gives a boost to all JS that runs in the JIT.

    There are two big items that didn't make the cut for Fx3.6, but will be in the next version of Firefox and are already available in nightly builds:

    • JITting recursion. Recursive code, like explicit looping code, is likely to be hot code, so it should be JITted. Nightly builds JIT directly recursive functions. Mutual recursion (g calls f calls g) is not traced yet.
    • AMD x64 nanojit backend. Nanojit now has a backend that generates AMD x64 code, which gives the possibility of better performance on that plaform.

    And if you try a nightly build, you'll find that many of these demos are already even faster than in Fx3.6!

  2. Firefox 3.6 is here!

    Firefox 3.6 has some cool consumer facing features like Personas and a better Plug-in Updater, but developers have a lot to be excited about too.  Developers will appreciate the increased stability, especially the work done to prevent crashes with third party software.  There are also enhancements like improved JavaScript performance and optimizations to speed up everyday Web tasks to make web applications snappier.  However, what developers will be most interested in are all the new features around CSS3 and HTML5 that bring the future of the Web to Firefox 3.6 today. 

    This is an exciting release because we have built on the progress we made with Firefox 3.5 just a few months ago and have implemented even more cutting-edge features that will make the Web experience more engaging and interactive than ever before.

    Today’s Firefox 3.6 release and the upcoming mobile release of Firefox for Maemo are both based on Gecko 1.9.2 and bring a number of big features including:

    For a more in-depth look at all the changes that developers will want to know about please check out Firefox 3.6 for Developers on MDC. And if you haven’t already, go get Firefox 3.6 now!

  3. offline web applications

    The network is a key component of any web application, whether it is used to download JavaScript, CSS, and HTML source files and accompanying resources (images, videos, …) or to reach web services (XMLHttpRequest and <forms>).

    Yet having offline support for web applications can be very useful to users. Imagine, for example, a webmail application that allows users to read emails already in their inbox and write new messages even when they are not connected.

    The mechanism used to support offline web applications can also be used to improve an application’s performance by storing data in the cache or to make data persistent between user sessions and when reloading and restoring pages.

    Demo: a To Do List Manager

    To see an offline web application in action, watch Vivien Nicolas’ demo, which shows a to do list manager working online and offline on an N900 running Firefox:

    You can also check out the live demo of the application.

    Creating your Own Offline Application

    For a web application to work offline, you need to consider three things:

    Let’s see how to use each of these components.

    Storage: Persistent Data

    DOM storage lets you store data between browser sessions, share data between tabs and prevent data loss (for example from page reloads or browser restarts). The data are stored as strings (for example a JSONified JavaScript object) in a Storage object.

    There are two kinds of storage global objects: sessionStorage and localStorage.

    • sessionStorage maintains a storage area that’s available for the duration of the page session. A page session lasts for as long as the browser is open and survives over page reloads and restores. Opening a page in a new tab or window causes a new session to be initiated.
    • localStorage maintains a storage area that can be used to hold data over a long period of time (e.g. over multiple pages and browser sessions). It’s not destroyed when the user closes the browser or switches off the computer.

    Both localStorage and sessionStorage use the following API:

    window.localStorage and window.sessionStorage {
      long length; // Number of items stored
      string key(long index); // Name of the key at index
      string getItem(string key); // Get value of the key
      void setItem(string key, string data); // Add a new key with value data
      void removeItem(string key); // Remove the item key
      void clear(); // Clear the storage
    };

    Here is an example showing how to store and how to read a string:

    // save the string
    function saveStatusLocally(txt) {
      window.localStorage.setItem("status", txt);
    }
     
    // read the string
    function readStatus() {
       return window.localStorage.getItem("status");
    }

    Note that the storage properties are limited to an HTML5 origin (scheme + hostname + non-standard port). This means that window.localStorage from http://foo.com is a different instance of window.localStorage from http://bar.com. For example, http://google.com can’t access the storage of http://yahoo.com.

    Are We Offline?

    Before storing data, you may want to know if the user is online or not. This can be useful, for example, to decide whether to store a value locally (client side) or to send it to the server.

    Check if the user is online with the navigator.onLine property.
    In addition, you can be notified of any connectivity changes by listening to the online and offline events of the window element.

    Here is a very simple piece of JavaScript code, which sends your status to a server (à la twitter).

    • If you set your status and you’re online, it sends the status.
    • If you set your status and you’re offline, it stores your status.
    • If you go online and have a stored status, it sends the stored status.
    • If you load the page, are online, and have a stored status, it sends the stored status.
    function whatIsYourCurrentStatus() {
      var status = window.prompt("What is your current status?");
      if (!status) return;
      if (navigator.onLine) {
        sendToServer(status);
      } else {
        saveStatusLocally(status);
      }
    }
     
    function sendLocalStatus() {
      var status = readStatus();
      if (status) {
        sendToServer(status);
        window.localStorage.removeItem("status");
      }
    }
     
     
    window.addEventListener("load", function() {
       if (navigator.onLine) {
         sendLocalStatus();
       }
    }, true);
     
    window.addEventListener("online", function() {
      sendLocalStatus();
    }, true);
     
    window.addEventListener("offline", function() {
      alert("You're now offline. If you update your status, it will be sent when you go back online");
    }, true);

    Offline Resources: the Cache Manifest

    When offline, a user’s browser can’t reach the server to get any files that might be needed. You can’t always count on the browser’s cache to include the needed resources because the user may have cleared the cache, for example. This is why you need to define explicitly which files must be stored so that all needed files and resources are available when the user goes offline: HTML, CSS, JavaScript files, and other resources like images and video.

    The manifest file is specified in the HTML and contains the explicit list of files that should be cached for offline use by the application.

    <html manifest="offline.manifest">

    Here is an example of the contents of a manifest file:

    CACHE MANIFEST
    fonts/MarketingScript.ttf
    css/main.css
    css/fonts.css
    img/face.gif
    js/main.js
    index.xhtml

    The MIME-Type type of the manifest file must be: text/cache-manifest.

    See the documentation for more details on the manifest file format and cache behavior.

    Summary

    The key components you should remember to think about when making your application work offline are to store the user inputs in localStorage, create a cache manifest file, and monitor connection changes.

    Visit the Mozilla Developer Center for the complete documentation.

  4. Hacks v2.0

    As you may have noticed, Hacks looks a bit different today.  That’s because we’ve completely redesigned the site. We wanted to make it easier for everyone to not only enjoy the new content we publish, but also to find past articles and demos. With Firefox 3.6 just around the corner, it’s the perfect time to rediscover Hacks!

    Thanks go out to Chris Howse for his design expertise, Craig Cook and Matt Harris for their development work, and everyone else that helped out.  What a difference a redesign like this can make:

    Hacks v1.0

    Chris Blizzard started the Hacks blog back in June 2009 as part of the “35 days of Firefox” campaign to give developers a look at the latest features and web technology upgrades that were coming in Firefox 3.5.  Since then, we have continued to reach out to web developers and collaborate with them to put together amazing posts.

    With a collection of helpful tutorials, updates on web standards, and technology demos, Hacks has become a popular destination for anyone interested in keeping up with innovation on the web.  We cover a wide range of topics, including everything from new possibilities with HTML5 to the latest version of Firebug. Developers get to see what is possible on the web today, while everyone gets a glimpse of what the future holds for Firefox and the open web.

    Hacks has ignited a renewed focus on web developer outreach and collaboration. In addition to the blog, you can follow us on Twitter, watch videos and demos on YouTube, and even subscribe to the about:hacks newsletter. Our goal is to inform and inspire web developers to help us establish a strong Mozilla Developer Network (MDN).

    We have big plans for MDN in 2010, and Hacks v2.0 is just the beginning!  Enjoy the new website and please share your thoughts and feedback with us…

    Happy New Year!

  5. Firebug 1.5 released!

    Editor’s note: today the Firebug team released Firebug 1.5. Check out Rob Campbell’s announcement reposted below.

    I am very happy to be able to announce the release of Firebug 1.5.0 on addons.mozilla.org. This release represents a significant effort by the Firebug Working Group which saw the addition of some new faces over the last few months.

    Here’s a quick run-down of some of the new features:

    • Enhanced Inspector
    • More accurate Net panel timings
    • Break on HTML mutation
    • MathML and SVG namespace support
    • Break on XHR
    • Improved HTML editing
    • Persist buttons on Console and Net panel
    • Separate Computed CSS and Style subpanels
    • Many many bugfixes and stability improvements

    This is a huge release and these are just some of the highlights you’ll see in this new version. Please feel free to read the Firebug 1.5 release notes and John Barton’s blog post for more details.

    As always, if you encounter any problems, don’t be shy about filing a bug! We’ll be following up with quick point-releases if and when you find issues.

    Special shout-outs and thanks to Mike Ratcliffe for the Inspector improvements, Steven Roussey for HTML editor improvements, SVG and MathML namespace patches, Honza for being awesome and John Barton for his tireless contributions.

    If you’re new to Firebug, you might want to check out my introduction to Firebug screencast.

  6. ClassList in Firefox 3.6

    This article was writt by Anthony Ricaud, French OpenWeb enthusiast.

    Why you need classList

    A dynamic web application usually needs visual feedback from its inner mechanism or needs to display different visual elements based on users’ actions.

    To change the user interface easily, you can add/remove/edit elements through the DOM API (document.createElement, div.removeChild, elt.style.color, …) but it’s easier to just update the elements’ class attribute to change how they are displayed and styled by CSS.

    Let’s take an example. Suppose you want to display a form with two modes: a basic mode, and an expert mode with extra options.

    This can be done with CSS rules: each mode has its own class and set of CSS code.

    #anexpertinput.basic {
      display: none;
    }
    #anexpertinput.expert {
      display: inline;
    }

    To dynamically change the classes of elements, you can use element.className. However, you may want to add, remove, or toggle just one class. There used to be two ways to do this, by using a library or by writing complex code with regular expressions. There is now another way with the new HTML5 API called classList, which is implemented in Firefox 3.6.

    Let’s see how it can simplify your code and improve performance at the same time.

    The classList API

    Here is an example to show you what the classList API looks like:

    // By default, start without a class in the div: <div class=""/>
     
    // Set "foo" as the class by adding it to the classList
    div.classList.add('foo'); // now <div class="foo"/>
     
    // Check that the classList contains the class "foo"
    div.classList.contains('foo'); // returns true
     
    // Remove the class "foo" from the list
    div.classList.remove('foo'); // now <div class=""/>
     
    // Check if classList contains the class "foo"
    div.classList.contains('foo'); // returns false: "foo" is gone
     
    // Check if class contains the class "foo",
    // If it does, "foo" is removed, if it doesn't, it's added
    div.classList.toggle('foo'); // class set to <div class="foo"/>
    div.classList.toggle('foo'); // class set to <div class=""/>

    Demo

    Let’s go back to our initial example of a form with both a basic and an expert mode – check out the live demo to see it in action.

    As you can see in the code below, you can switch between the two modes with one line of JavaScript.

    <button onclick="document.getElementById('box').classList.toggle('expert');">
      Toggle expert mode
    </button>
    <div id="box">
      <label for="nick">Name: <input type="text" id="nick" /></label>
      <label for="status">Status: <input type="text" id="status" /></label>
      <p id="help"> Blablablablabla...</p>
      <label for="postpone">Postpone: <input type="checkbox" id="postpone" /></label>
      <label for="lang">Lang: <input type="text" id="lang" /></label>
    </div>
    #box.expert > #help,
    #box.expert > label[for="postpone"],
    #box.expert > label[for="lang"] {
       display: none;
    }

    See the Mozilla documentation and the HTML5 specification for more details on classList.

    Performance

    Using the classList API is not only easier, it’s also more powerful. Take a look at what we observed using Firefox 3.6.

    benchmark classList

    Interoperability

    Since other browser vendors have not yet implemented the HTML5 classList API, you still need fallback code. You can use this sample code as fallback.

    To know more about the current implementation of classList in well-known JavaScript libraries, see:

  7. Firebug 1.5: a closer look

    Firebug 1.5 was released yesterday on addons.mozilla.org, where you can now download it. It’s compatible with the upcoming Firefox 3.6.

    If you’d like to take a more in-depth look at what’s new in Firebug 1.5, here’s a series of articles written by Firebug contributor Jan Odvarko (aka Honza):

    If you’ve had a chance to try the new Firebug, comment here or in the Firebug newsgroup and tell the team what you think!

  8. industry support for WOFF and Firefox 3.6

    Today we announced the release of Firefox 3.6 and users are starting to upgrade. One of the more important features we included for developers was support for a new font standard called WOFF.

    WOFF has received wide support from the type community and we’re starting to see the results of that. There are a couple of specific instances that we’d like to point out on day zero of our release:

    1. FontFont, one of the largest type foundries in the world, announced a free-as-in-beer demo font in the WOFF format called FF Nuvo Medium Demo. This is part of FontFont’s commitment to support the new format and to start to give people the tools to start to adopt it.

    2. Typekit, a commercial hosting provider for fonts, announced that they will start serving up WOFF fonts to Firefox 3.6 users.

    It’s great to see commercial support already ramping up to support the new format. It’s going to really improve the experience for users on the web.