Mozilla

JavaScript Articles

Sort by:

View:

  1. Fun With Fast JavaScript

    This post is by Vladimir Vukićević and is a re-post from his personal weblog.

    Fast JavaScript is a cornerstone of the modern web. In the past, application authors had to wait for browser developers to implement any complex functionality in the browser itself, so that they could access it from script code. Today, many of those functions can move straight into JavaScript itself. This has many advantages for application authors: there’s no need to wait for a new version of a browser before you can develop or ship your app, you can tailor the functionality to exactly what you need, and you can improve it directly (make it faster, higher quality, more precise, etc.).

    Here are two examples that show off what can be done with the improved JS engine and capabilities that will be present in Firefox 4. The first example shows a simple web-based Darkroom that allows you to perform color correction on an image. The HTML+JS is around 700 lines of code, not counting jQuery. This is based on a demo that’s included with Google’s Native Client (NaCl) SDK; in that demo, the color correction work is done inside native code going through NaCl. That demo (originally presented as “too slow to run in JavaScript”) is a few thousand lines of code, and involves downloading and installing platform-specific compilers, multiple steps to test/deploy code, and installing a plugin on the browser side.

    I get about 15-16 frames per second with the default zoomed out image (around 5 million pixels per second — that number won’t be affected by image size) on my MacBook Pro, which is definitely fast enough for live manipulation. The algorithm could be tightened up to make this faster still. Further optimizations to the JS engine could help here as well; for example, I noticed that we spend a lot of time doing floating point to integer conversions for writing the computed pixels back to the display canvas, due to how the canvas API specifies image data handling.

    The Web Darkroom tool also supports drag & drop, so you can take any image from your computer and drop it onto the canvas to load it. A long (long!) time ago, back in 2006, I wrote an addon called “Croppr!”. It was intended to be used with Flickr, allowing users to play around with custom crops of any image, and then leave crop suggestions in comments to be viewed using Croppr. It almost certainly doesn’t work any more, but it would be neat to update it: this time with both cropping and color correction. Someone with the addon (perhaps a Jetpack now!) could then visit a Flickr photo and experiment, and leave suggestions for the photographer.

    The second example is based on some work that Dave Humphrey and others have been doing to bring audio manipulation to the web platform. Originally, their spec included a pre-computed FFT with each audio frame delivered to the web app. I suggested that there’s no need for this — while a FFT is useful for some applications, for others it would be wasted work. Those apps that want a FFT could implement one in JS. Some benchmark numbers backed this up — using the typed arrays originally created for WebGL, computing an FFT in JS was approaching the speed of native code. Again, both could be sped up (perhaps using SSE2 or something like Mono.Simd on the JS side), but it’s fast enough to be useful already.

    The demo shows this in action. A numeric benchmark isn’t really all that interesting, so instead I take a video clip, and as it’s playing, I extract a portion of the green channel of each frame and compute its 2D FFT, which is then displayed. The original clip plays at 24 frames per second, so that’s the upper bound of this demo. Using Float32 typed arrays, the computation and playback proceeds at around 22-24fps for me.

    You can grab the video controls and scrub to a specific frame. (The frame rate calculation is only correct while the video is playing normally, not while you’re scrubbing.) The video source uses Theora, so you’ll need a browser that can play Theora content. (I didn’t have a similar clip that uses WebM, or I could have used that.)

    These examples are demonstrating the strength of the trace-based JIT technique that Firefox has used for accelerating JavaScript since Firefox 3.5. However, not all code can see such dramatic speedups from that type of acceleration. Because of that, we’ll be including a full method-based JIT for Firefox 4 (for more details, see David Anderson’s blog, as well as David Mandelin’s blog). This will provide significantly faster baseline JS performance, with the trace JIT becoming a turbocharger for code that it would naturally apply to.

    Combining fast JavaScript performance alongside new web platform technologies such as WebGL and Audio will make for some pretty exciting web apps, and I’m looking forward to seeing what developers do with them!

    Edit: Made some last-minute changes to the demos, which ended up pulling in a slightly broken version of jQuery UI that wasn’t all that happy with Safari. Should be fixed now!

  2. Firefox 4: easier JS form handling with FormData

    This feature has landed in Mozilla Central (trunk) and only available with a Firefox Nightly Build for the time being.

    XMLHttpRequest Level 2 (editor’s draft) adds support for the new FormData interface. FormData objects provide a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest send() method in “multipart/form-data” format.

    Why FormData?

    When you want to send complex data to a server from a web page (files, non-ASCII content), you must use the multipart/form-data content type. To set the content type in a <form>, you write:

    <form method="post" enctype="multipart/form-data" action="http://foo.bar/upload.php">
    <input type="file" name="media"/>
    <input name="nickname"/>
    <input name="website"/>
    <input type="submit" value="upload"/>
    </form>

    This is what you usually do to upload a file.

    Starting with Firefox 3.6, you can manipulate files with JavaScript (see File API), and maybe you want to send files using XMLHttpRequest. But if, for example, you want to reproduce this form, it’s really hard because you’ll have to create the multipart/form-data content yourself in JavaScript (see, for example, this code I wrote a while ago implementing a multipart/form-data: ugly and slow).

    This is where FormData is useful: to reproduce the <form> submission mechanism in JavaScript

    The FormData object

    The FormData object lets you compile a set of key/value pairs to send using XMLHttpRequest. This object has only one method:

    append(key, value);

    where key is the name of your value, and where value can be a string or a file.

    You can create a FormData object, append values and then send it through XMLHttpRequest. If you want to simulate the previous form, you write:

    // aFile could be from an input type="file" or from a Dragged'n Dropped file
    var formdata = new FormData();
    formdata.append("nickname", "Foooobar"); 
    formdata.append("website", "http://hacks.mozilla.org");
    formdata.append("media", aFile);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "http://foo.bar/upload.php");  
    xhr.send(formdata);

    FormData and the <form> element

    Firefox extends the HTML form element slightly, adding a getFormData() method that lets you fetch a form’s data as a FormData object. This is not yet part of the HTML standard, but is expected to be added to the specification at some point in the future (although possibly with a different name):

    var formElement = document.getElementById("myFormElement");
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "submitform.php");
    xhr.send(formElement.getFormData());

    You can also add data to the FormData object between retrieving it from a form and sending it, like this:

    var formElement = document.getElementById("myFormElement");
    formData = formElement.getFormData();
    formData.append("serialnumber", serialNumber++);
    xhr.send(formData);

    This lets you augment the form’s data before sending it along, to include additional information that’s not necessarily user editable on the form.

    Resources

  3. Beyond HTML5: experiments with interactive audio

    This is a re-post of an important post from David Humphrey who has been doing a lot of experiments on top of Mozilla’s extensible platform and doing experiments with multi-touch, sound, video, WebGL and all sorts of other goodies. It’s worth going through all of the demos below. You’ll find some stuff that will amaze and inspire you.

    David’s work is important because it’s showing where the web is going, and where Mozilla is helping to take it. It’s not enough that we’re working on HTML5, which we’re about finished with, but we’re trying to figure out what’s next. Mozilla’s platform, Gecko, is a huge part of why we’re able to experiment and learn as fast as we can. And that’s reflected with what’s possible here. It’s a web you can see, touch and interact with in new ways.

    David’s post follows:

    I’m working with an ever growing group of web, audio, and Mozilla developers on a project to expose audio spectrum data to JavaScript from Firefox’s audio and video elements. Today we show what we did at www2010.

    I’m in Raleigh, North Carolina, with Al MacDonald for the www2010 conference. We’re here to present our work on exposing audio data in the browser. Over the past month Corban, Charles, and a bunch of other friends have been working with us to refine the API and get new types of demos ready. We ended-up with 11 demos, some of which I’ve shown here before. Here are the others.

    The first was done by Jacob Seidelin, and shows many cool 2D visualizations of audio using our API. You can see the live version on his site, or check out this video:

    The second and third demos where done by Charles Cliffe, and show 3D visualizations using WebGL and his CubicVR engine. These also show off his JavaScript beat detection code. Is JavaScript fast enough to do real-time analysis of audio and synchronized 3D graphics? Yes, yes it is. The live versions are here and here, and here are some videos:

    The fourth demo was done by Corban Brook and shows how audio data can be mixed live using script. Here he mutes the main audio, plays it, passes the data through a low pass filter written in JavaScript, then dumps the modified frames into a second audio element to be played. It’s a technique we need to apply more widely, as it holds a lot of potential. Here’s the live version, and here’s a video (check out his updated JavaScript synthesizer, which we also presented):

    The fifth and sixth demos were done by Al (with the help of many). When I was last in Boston, for the Processing.js meetup at Bocoup, we met with Doug Schepers from the W3C. He loved our stuff, and was talking to us about ideas that would be cool to build. He pulled out his iPhone and showed us Brian Eno’s Bloom audio app. “It would be cool to do this in the browser.” Yeah, it is cool, and here it is, written in a few hundred lines of JavaScript and Processing.js (video 1, video 2):

    This demo also showcases the awesome work of Felipe Gomes, who has a patch to add multi-touch DOM events to Firefox. The method we’ve used here can be taken a lot further. Imagine being able to connect multiple browsers together for collaborative music creation, layering other audio underneath, mixing fragments vs. just oscillators, etc. We built this one in a week, and the web is capable of a lot more.

    One of the main points of our talk was to emphasize that what we’re talking about here isn’t just a concept, and it isn’t some far away future. This is real code, running in a real browser, and it’s all being done in HTML5 and JavaScript. The web is fast enough to do real-time audio processing now, powerful enough and expressive enough to create music. And the community of digital music and audio hackers, visualizers, etc. are hungry for it. So hungry that they are seeking us out, downloading our hacked builds and creating gorgeous web audio applications.

    We want to keep going, and we need help. We need help from those within Mozilla, the W3C, and other browsers to get this stuff into shipping browsers. We need the audio, digital music, accessibility, and web communities to come together in order to help us build js audio libraries and more sample applications. Yesterday Joe Hewitt was talking on twitter about how web browser vendors need to experiment more with non-standard APIs. I couldn’t agree more, and here’s a chance for people to put their money where their mouth is. Let’s make audio a scriptable part of the open web.

    I’m currently creating new builds of our updated patch for Firefox, and will post links to them here when I’m done. You can read more about the technical details of our work here, and get involved in the bug here. You can talk more with me on irc in the processing.js channel (I’m humph on moznet), or talk to me on twitter (@humphd) or by email. One way or another, get in touch so you can help us push this forward.

  4. Real-time server visualization with canvas and processing.js

    This is a guest blog post by Logan Welliver, Chief Creative at Cloudkick. He is a graphic designer by training and a web designer in practice.

    Cloud management company Cloudkick has released a real-time server monitoring visualization based on canvas and processing.js, that was co-developed with Alastair McDonald of processing.js fame. The product is designed to let users keep a finger on the pulse of their infrastructure, quickly identify problem nodes, and visualize aggregate performance with an easy-to-digest interface.

    The tool uses canvas and processing.js to plot servers as stylized circles in 3 dimensions, with axes mapped to one of three performance metrics: CPU usage, memory usage, and ping latency. Each server’s radius is determined by it’s relative prowess (i.e. an EC2 extra large is bigger than 256mb Slice), and colors are customizable via the Cloudkick dashboard. Each server sparkles when the monitoring system returns data, and servers with problems identify themselves by flashing an angry red.

    Canvas and processing.js take care of all the presentation, powered by a slew of back-end services that do everything from monitoring servers to pushing data in real-time back to the user.

    Here’s a brief overview of the back-end architecture: instances of the Cloudkick Agent (running on individual servers) report metrics to an endpoint, which talks to Reconnoiter, which then publishes messages to RabbitMQ. An internal service called Livedata consumes these messages, finds the ones applicable to an account, and publishes messages back to RabbitMQ. Orbited consumes these messages and sends them to the browser. From agent to browser, the round-trip time is less than a second.

    Cloudkick has partnered with Mozilla to provide the visualization for their addons.mozilla.org servers. You can see how they’re behaving in a live demo of the visualization here: addons.mozilla.org infrastructure in Cloudkick Viz.

    Get the visualization for your own servers. Cloudkick is offering 20% off for the first 100 Mozilla Hacks readers, using promo code “mozhacks01″.

  5. a quick note on JavaScript engine components

    There have been a bunch of posts about the JägerMonkey (JM) post that we made the other day, some of which get things subtly wrong about the pieces of technology that are being used as part of Mozilla’s JM work. So here’s the super-quick overview of what we’re using, what the various parts do and where they came from:

    1. SpiderMonkey.This is Mozilla’s core JavaScript Interpreter. This engine takes raw JavaScript and turns it into an intermediate bytecode. That bytecode is then interpreted. SpiderMonkey was responsible for all JavaScript handling in Firefox 3 and earlier. We continue to make improvements to this engine, as it’s still the basis for a lot of work that we did in Firefox 3.5, 3.6 and later releases as well.

    2. Tracing. Tracing was added before Firefox 3.5 and was responsible for much of the big jump that we made in performance. (Although some of that was because we also improved the underlying SpiderMonkey engine as well.)

    This is what we do to trace:

    1. Monitor interpreted JavaScript code during execution looking for code paths that are used more than once.
    2. When we find a piece of code that’s used more than once, optimize that code.
    3. Take that optimized representation and assemble it to machine code and execute it.

    What we’ve found since Firefox 3.5 is that when we’re in full tracing mode, we’re really really fast. We’re slow when we have to “fall back” to SpiderMonkey and interpret + record.

    One difficult part of tracing is generating code that runs fast. This is done by a piece of code called Nanojit. Nanojit is a piece of code that was originally part of the Tamarin project. Mozilla isn’t using most of Tamarin for two reasons: 1. we’re not shipping ECMAScript 4 and 2. the interpreted part of Tamarin was much slower than SpiderMonkey. For Firefox 3.5 we took the best part – Nanojit – and bolted it to the back of SpiderMonkey instead.

    Nanojit does two things: it takes a high-level representation of JavaScript and does optimization. It also includes an assembler to take that optimized representation and generate native code for machine-level execution.

    Mozilla and Adobe continue to collaborate on Nanojit. Adobe uses Nanojit as part of their ActionScript VM.

    3. Nitro Assembler. This is a piece of code that we’re taking from Apple’s version of webkit that generates native code for execution. The Nitro Assembler is very different than Nanojit. While Nanojit takes a high-level representation, does optimization and then generates code all the Nitro Assembler does is generate code. So it’s complex, low-level code, but it doesn’t do the same set of things that Nanojit does.

    We’re using the Nitro assembler (along with a lot of other new code) to basically build what everyone else has – compiled JavaScript – and then we’re going to do what we did with Firefox 3.5 – bolt tracing onto the back of that. So we’ll hopefully have the best of all worlds: SpiderMonkey generating native code to execute like the other VMs with the ability to go onto trace for tight inner loops for even more performance.

    I hope this helps to explain what bits of technology we’re using and how they fit into the overall picture of Firefox’s JS performance.

  6. improving JavaScript performance with JägerMonkey

    In August 2008, Mozilla introduced TraceMonkey. The new engine, which we shipped in Firefox 3.5, heralded a new era of performance to build the next generation of web browsers and web applications. Just after the introduction of our new engine Google introduced V8 with Chrome. Apple also introduced their own engine to use in Safari, and even Opera has a new engine that they’ve introduced with their latest browser beta.

    As a direct result of these new engines we’ve started to see new types of applications start to emerge. People experimenting with bringing Processing to the web, people experimenting with real-time audio manipulation, games and many other things. (For some good examples have a look at our list of Canvas demos.)

    We’ve learned two things at Mozilla about how our JavaScript engine interacts with these new applications:

    1. That the approach that we’ve taken with tracing tends to interact poorly with certain styles of code. (That NES game example above, for example, tends to perform very badly in our engine – it’s essentially a giant switch statement.)
    2. That when we’re able to “stay on trace” (more on this later) TraceMonkey wins against every other engine.

    Mozilla’s engine is fundamentally different than every other engine: everyone else uses what’s called a “method-based JIT”. That is, they take all incoming JS code, compile it to machine code and then execute it. Firefox uses a “tracing JIT.” We interpret all incoming JS code and record as we’re interpreting it. When we detect a hot path, we turn that into machine code and then execute that inner part. (For more background on tracing, see this post on hacks from last year.)

    The downside of the tracing JIT is that we have to switch back and forth between the interpreter and the machine code whenever we reach certain conditions. When we have to jump back from machine code to the interpreter this is what we call being “knocked off trace.” The interpreter is, of course, much slower than running native machine code. And it turns out that happens a lot – more than anyone expected.

    So what we’re doing in our 2nd generation engine is to combine the best elements of both approaches:

    1. We’re using some chunks of the WebKit JS engine and building a full-method JIT to execute JavaScript code. This should get us fast baseline JS performance like the other engines. And most important, it will be consistent – no more jumping on and off trace and spending a huge amount of time in interpreted code.
    2. We’ll be bolting our tracing engine into the back of that machine code to generate super-fast code for inner loops. This means that we’ll be able to still have the advantages of a tracing engine with the consistency of the method-based JIT.

    This work is still in the super-early stages, to the point where it’s not even worth demoing, but we thought it would be worth posting about so people understand the basics of what’s going on.

    You can find more information about this on David Mandelin‘s and David Anderson‘s weblogs as well as the project page for the the new engine.

  7. 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:

  8. 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!

  9. making waves with HTML5

    Thomas Saunders of modern-carpentry has a very nice HTML5 demo, making waves with html5, showcasing the power of Canvas as well as Processing.js.

    modern carpentry rides the html5 canvas wave

    Thomas says:

    I was challenged at work to create something that “floats naturally”. After a while of confusion in my pursuit of “natural floating” or whatever, I came up with the idea that I needed a tool to investigate my confusion. This project is a result of my trying to build that tool.

    It was initially built as a Flash/Flex application, which you can see here. Later on, however, I became interested in HTML5 and the Canvas tag and decided to port the application to JavaScript and HTML (with the help of jQuery, and also Processing.js, of course…). The transition went fairly well, and I ended up with a JS/HTML version of the application that I actually think is cooler than the original Flash version.

    In the end, I came up with both something that “floats naturally” and also a serendipitous encounter with the simplicity of working with only HTML and JavaScript, which has been very rewarding.