Great performance is one of many things being delivered in Internet Explorer?8 Beta 2, the latest version of the popular browser.

Beyond a much faster JScript engine, Internet Explorer?8 Beta 2 includes profound performance improvements and exciting new developer features that make it one of the most exciting browser releases in years.

Internet Explorer?8 Beta 2 streamlines the browsing experience and ensures that users and developers can be more productive than in any other browser. Find out why the community is buzzing as I highlight some of the most significant performance improvements and great new features being released as part of Internet Explorer?8 Beta 2.

Faster JScript

As Shreesh Dubey discusses in the article ?AJAX Performance Measurement Methodology?, the JScript engine is an important component affecting the speed of the AJAX pipeline used in many websites today. Internet Explorer?8 Beta 2 includes several enhancements that significantly improve those sites. We have worked hard in several broad areas to make sites faster and to reduce the amount of memory Internet Explorer?8 Beta 2 needs on your favorite sites. I describe a few of them below.

Circular Memory Leak Mitigation

A key factor influencing the performance of Web browsers today is their ability to minimize the amount of memory they require. We have made significant improvements to how the JScript engine manages memory in Internet Explorer?8 Beta 2.

Internet Explorer?8 Beta 2 streamlines the browsing experience and ensures that users and developers can be more productive than in any other browser.

The JScript garbage collector in previous versions of Internet Explorer manages the lifetime of JScript objects but not of DOM objects. As a result, the JScript garbage collector cannot break circular references between DOM objects and JScript objects, and memory leaks can result. In Internet Explorer 6, these circular references are broken when the Internet Explorer process terminates. In Internet Explorer?7, these circular references are broken when users navigate away from page that contains the leaks.

Here are four simplified examples of patterns that would leak memory in previous versions of Internet Explorer:

Direct Circular References

The DOM object refers to itself and an object not in the tree:

function leaktest1()
{
    var elem1 = document.createElement("DIV");
    elem1.thing = elem1;
}

Circular references between DOM objects not in tree:

function leaktest2()
{
    var elem1 = document.createElement("DIV");
    var elem2 = document.createElement("DIV");
    elem1.thing = elem2;
    elem2.item = elem1;
}

Circular References Created by Closures

Closures with element created dynamically:

function leak3()
{
    var elem = document.createElement("DIV");
    elem.onload = function ()
    {
        var y = elem;
    }
}

Leaks caused by function pointers:

function leak4()
{
    var elem = document.createElement("DIV");
    elem.thing = elem.setAttribute;
}

In Internet Explorer?8 Beta 2, the JScript garbage collector treats DOM objects referenced by JScript objects as any other JScript object. Rather than wait until page navigation as in Internet Explorer?7 or process termination as in Internet Explorer?6, the garbage collector manages the lifetime of these DOM objects, and breaks circular references whenever possible throughout the lifetime of the site.

JScript Runtime Improvements

In addition to eliminating many sources of circular reference memory leaks, the Internet Explorer?8 Beta 2 JScript engine bakes in impressive optimizations to directly improve scripting speed.

Optimized String Operations

One of the most common JScript operations in use today is the concatenation of strings. Performance of string concatenation has significantly improved over previous versions of Internet Explorer. In some cases these changes have improved the speed of the + and += operators (as well as the built-in String.concat method) by several orders of magnitude. Coupled with further improvements to other string methods, these enhancements should significantly improve methods that use string concatenation, and obviate the need for developers to devise complex alternative solutions.

Optimized Array Operations

In addition to the great work to improve string operations, array storage and access within the JScript engine has resulted in order-of-magnitude performance gains for many built-in array methods. JScript authors implementing their own array methods (such as Array.push and Array.pop) as a faster replacement for the built-in array methods should consider using the built-in methods to improve code performance.

Optimized Execution Engine

Apart from optimizations to strings and array operations, the JScript execution engine shipped within Internet Explorer?8 Beta 2 also optimizes and improves the performance of function calls, object creation, accessing object prototype properties and specific lookup patterns for JScript variables scoped to the window or this objects.

The improvements to the Internet Explorer?8 Beta 2 scripting engine combine to improve pure JScript performance by 400% on the SunSpider benchmarking suite and speed up Google Gmail by over 30% compared to Internet Explorer?7.

What this means for users is that they will have a faster and more reliable browsing experience on their favorite sites. Developers, in turn, can once again create great new content without having to expend effort managing object lifetime.

Unblocked Downloads

Beyond improvements to the Internet Explorer?8 Beta 2 scripting engine, another important aspect of site performance is the ability to quickly download page elements. When navigating to a Web page, Internet Explorer typically attempts to parallelize the download of page elements. In the case where Internet Explorer encounters an external script to download, however, previous browser versions would block parallel downloads until the script download was complete.

This approach was sensible when bandwidth was constrained, processing power was expensive, and sites were simple. Since the scripts being downloaded could alter the makeup of the page (and thus determine what should be downloaded) this approach could save valuable processing power that would otherwise be wasted. With CPU cycles relatively cheap and broadband widely available, with Internet Explorer?8 Beta 2 Microsoft recognized an opportunity to speed up browsing by taking advantage of these resources.

As a result, Internet Explorer?8 Beta 2 no longer blocks parallel downloads in the presence of external scripts. What this means is that Internet Explorer?8 Beta 2 can more efficiently use available bandwidth to make sites faster for users like you and me. This is especially true as sites become increasingly complex. Even better, developers do not need to change their sites whatsoever to take advantage of this improvement.

Faster Startup and Navigation

In addition to the vast improvements to the JScript engine and the improved parallel download behavior, Internet Explorer?8 Beta 2 features numerous enhancements to reduce the amount of time it takes to start the browser and to navigate to your favorite sites.

That work has involved streamlining the Safety Filter, which now keeps users safe at minimal cost. Microsoft has also worked hard to reduce memory fragmentation throughout the browser, significantly reduced registry accesses by up to 25% when navigating to some sites, and streamlined aspects of the Internet Explorer user interface. These changes and others have contributed to a much faster Internet Explorer.

Great New Features

In Internet Explorer?8 Beta 2 Microsoft is introducing several new features that developers can take advantage of to improve their site performance. Several of those features have been discussed in other articles in this issue.

One of the things that Web developers have told us is that they need a way to extend the DOM with cutting-edge new features they can deliver as rapidly as their business demands.

Sunava Dutta introduced the Microsoft implementation of the HTML5 specification's DOM Storage, Cross-Document Request (XDR), and Connectivity Events in his article, ?Better AJAX Development with Internet Explorer?8 Beta 2?. Web developers can take advantage of these great cross-platform features to speed up their sites.

Beyond these three key features, John Hrvatin has introduced the JScript profiler built into the Internet Explorer?8 Beta 2 developer tools. A crucial addition to any Web developer's toolbox, the profiler gives site authors the tools they need to understand and improve the speed of their sites.

In addition to these great enhancements, Internet Explorer?8 Beta 2 includes support for several new standards that developers can exploit to build lighting fast sites. The Internet Explorer?8 Beta 2 implementation of the ECMAScript 3.1 JSON recommendation, support for mutable DOM prototypes, and native support for the Selectors API are all cutting edge features that will form the basis for the next generation of Web sites and frameworks.

Native JSON support

JavaScript Object Notation (JSON) is a lightweight data-interchange format based on a subset of the object literal notation of the JScript language and is often used to pass data between components of AJAX websites. Unfortunately, many sites don't use JSON securely and rely on the JavaScript eval method to ?revive? JSON strings back into JavaScript objects.

Security-conscious developers instead use a more secure JSON parser to ensure that the JSON object does not contain executable script, often at the price of a significant performance penalty.

The JScript engine that ships with Internet Explorer?8 Beta 2 implements the ECMAScript 3.1 JSON proposal. The JSON.stringify method accepts a script object and returns a JSON string, while the JSON.parse method accepts a string and safely revives it into a JavaScript object. I am excited at this addition, as it is not only secure but is also much faster than equivalent framework implementations.

To illustrate, here is an example of serializing and deserializing data using the JSON.stringify and JSON.parse methods:

var testObj = new Object();
testObj.numVal = 4;
testObj.strVal = "fool";
testObj.dateVal = new Date(2008, 3, 1);
testObj.arrVal = new Array(1,2,"test");
testObj.boolVal = true;

// Convert the object to a string
var stringifiedValue = JSON.stringify(testObj);

// Create a new object from the string
var parsedValue = JSON.parse(stringifiedValue);

Streamlined DOM Searching

Do you find yourself caught in the trap of assigning an ID to every element in your source code in order to use the ubiquitous getElementById API to retrieve what you are looking for? Perhaps you are a veteran user of getElementsByTagName? Whatever element lookup technique you employ, you have probably run into those scenarios where one of these APIs just does not stretch as far as you need it to.

Once upon a time I too contributed to those geeky Web pages with animations that followed your cursor around the screen; I would write the layout of the page in CSS, and then use JavaScript to perform the animation by judicious use of setTimeout and [element].style.left/top.

No matter the scenario, you may find yourself searching for a better searching API, or you are turning to JavaScript frameworks that include tailored element lookup routines for you (prototype.js and jQuery, for example). Thankfully, with Internet Explorer?8 Beta 2 there is now a better way! You should acquaint yourself with querySelector and querySelectorAll APIs. They will likely become some of the most frequently used APIs in your repertoire. They plug directly into the improved Internet Explorer?8 Beta 2 CSS 2.1 selector support so that you can leverage the selector-matching engine at any time using JavaScript.

To experiment with the syntax, try replacing a call to getElementById(?id') with querySelector(?#id')-the results are the same. The following example uses querySelectorAll to grab all relevant elements by class and turn off their collective display status. Listing 1 illustrates the original unoptimized code demonstrating that the use of the Selectors API results in significantly less-code to download and execute on the client.

function useSelectors(clsName)
{
    // Hide everything...
    var unset = document.querySelectorAll('h3, p, ul, code');
    
    for (var i = 0; i < unset.length; i++)
        unset[i].style.display = 'none';
    
    var set = document.querySelectorAll("." + clsName);
    
    for (var i = 0; i < set.length; i++)
        set[i].style.display = 'block';
}

Listing 1: Original [unoptimized] code to hide articles except those matching a certain class. Without the Selectors API, this code is almost 500% larger.

function showHideContentAreaContent(clsName)
{
    // ***********************************************
    // Begin: Hiding elements that should not be shown
    
    // Hide all the H3's (topic headers for sub-articles)...
    var h3Collection = document.getElementsByTagName('h3');
    for (var i = 0; i < h3Collection.length; i++)
    {
        // ...unless this element has a class that matches.
        if (h3Collection[i].className.indexOf(clsName) != -1)
            h3Collection[i].style.display = 'block';
        else
            h3Collection[i].style.display = 'none';
    }
    
    // Hide the P tags that have a className assigned...
    var pCollection = document.getElementsByTagName('p');
    for (var j = 0; j < pCollection.length; j++)
    {
        // ...unless this element has a class that matches.
        if (pCollection[j].className.indexOf(clsName) != -1)
            pCollection[j].style.display = 'block';
        else
            pCollection[j].style.display = 'none';
    }

    // Hide any UL elements that may be part of an article...
    var ulCollection = document.getElementsByTagName('ul');
    for (var k = 0; k < ulCollection.length; k++)
    {
        // ...unless this element has a class that matches.
        if (ulCollection[k].className.indexOf(clsName) != -1)
            ulCollection[k].style.display = 'block';
        else
            ulCollection[k].style.display = 'none';
    }
        
    // Finally, hide the CODE element on one article unless it needs to be shown.
    var codeColl = document.getElementsByTagName('code');
    for (var m = 0; m < codeColl.length; m++)
    {
        if (codeColl[m].className.indexOf(clsName) != -1)
            codeColl[m].style.display = 'block';
        else
            codeColl[m].style.display = 'none';
    }
    // END: Hiding elements
    // ************************************************
}

The Selectors APIs are available at two different scopes: document and element. If you want to find the first result of a particular selector, then use querySelector (which returns the found element directly). Alternatively, if you want to find all matching elements use querySelectorAll. Using element scope can be important when you want to narrow your results to a particular subtree of the DOM instead of collecting results from everywhere. Interestingly enough, the provided selector-string parameter is first checked against the entire document, however the elements returned must be within the proper subtree of the element on which the API was called.

The folks over at WebKit have written a test that allows you to compare the Internet Explorer?8 Beta 2 native implementation of the Selectors API to common JavaScript implementations-highlighting the fact that you can harness the native implementation to speed up your code dramatically. Just go to http://webkit.org/perf/slickspeed/ in Internet Explorer?8 Beta 2 to see for yourself!

Mutable DOM Prototypes

As with the support for the Selectors APIs, the support for mutable DOM prototypes gives developers the building blocks to create efficient and compact abstractions.

Like many programming languages, JavaScript objects derive from well-defined and documented types, which are discoverable through reflection. Unlike many programming languages, however, JavaScript makes these types directly available and (strangely enough) mutable through its support for prototype inheritance! To illustrate the feature, consider this example:

var arrayInstance = new Array();

// Check to see if there's a "xyz"
// (it should not exist because it is not
// part of the object or its prototype)
alert(arrayInstance.xyz);

// Add xyz to the prototype
Array.prototype.xyz = "xyz string";

// Now xyz is available to the instance
alert(arrayInstance.xyz);

Even with this simplified example, you can see that if xyz is a feature that enhances any and all array accesses, then the inclusion of it on the Array prototype is the right place to get the most impact per line of code. Thanks to our community feedback, Microsoft is pleased to bring the power and flexibility of JavaScript prototypes to the IE DOM as well. You may be thinking that I am getting far too excited by a feature that does not seem particularly remarkable, but bear with me for just a moment longer and I'm certain that you too will be a fan.

Compared to frameworks released by Web developers, features provided by a browser release at a slower pace and cater to a more general audience. One of the things that Web developers have told us is that they need a way to extend the DOM with cutting-edge new features-features only they can deliver as rapidly as their business demands. Essentially, developers need to be able to fill functionality gaps long before a native implementation shows up in any browser. DOM prototypes give Web developers the basic building blocks that they can supplement the DOM directly with extra functionality or replace existing implementations with their own.

Drawing from the previous example, if I want to add a feature to all image elements in the DOM I could add it to the HTMLImageElement prototype:

// Apply the change to the prototype.
HTMLImageElement.prototype.grow = function()
{
    this.width *= 1.5;
    this.height *= 1.5;
}

// Grow all the images in the document.
for (var i= 0; i < document.images.length; i++)
{
    document.images[i].grow();
}

The alternative approach is to add the feature API manually to each individual image element separately-crippling performance. You can see how mutable prototypes provide a much simpler and efficient approach to this common problem.

In addition to providing a staging ground, DOM prototypes enable more efficient JavaScript by providing a single, logical place for element-related helper functions. For many scenarios the Element prototype is the most reasonable location for these additions, as it is a parent to all of the elements in the Internet Explorer DOM. As a result, changes to the Element prototype apply to all elements. A good example of how you can use this approach is to add the getElementsByClassName API to all elements; the draft spec of HTML 5 recently defined this API and Internet Explorer?8 Beta 2 does not implement it natively. You can define this method to immediately treat elements as if they supported it natively. Best of all, that method will be faster than more complex alternatives offered as part of generalized frameworks. See Listing 2 for the implementation of _MSHTML5_getElementsByClassName_Elem.

<div id="div1" class="xyz">Text
    <div id="div2" class="abc xyz">More</div>
</div>
<div id="div3" class="xyz abc box">Other</div>

<script type="text/javascript">
    Element.prototype.getElementsByClassName = _MSHTML5_getElementsByClassName_Elem;

    // Invoke getElementsByClassName.
    var div1 = document.getElementById('div1');
    div1.getElementsByClassName('abc xyz');
</script>

Listing 2: Implementation of the getElementsByClassName JavaScript function.

function _MSHTML5_getElementsByClassName_Elem(classList)
{
    var tokens = classList.split(" ");
    if (tokens.length == 0)
    {
        return null;
        // Per HTML5: "If there are no tokens specified in the
        // argument, then the method must return an empty NodeList."
    }

    // Pre-fill the list with the results of the first token searched.
    var staticNodeList = this.querySelectorAll("." + tokens[0]);
    // Start the iterator at 1 because the first match is already collected.
    for (var i = 1; i < tokens.length; i++)
    {
        // Search for each token independently.
        var tempList = this.querySelectorAll("." + tokens[i]);
        // Collects the "keepers" between loop iterations.
        var resultList = new Array();
        for (var finalIter = 0; finalIter < staticNodeList.length; finalIter++)
        {
            var found = false;
            for (var tempIter = 0; tempIter < tempList.length; tempIter++)
            {
                if (staticNodeList[finalIter] == tempList[tempIter])
                {
                    found = true;
                    break; // Terminate early if found.
                }
            }
            if (found)
            {
                // This element was in both lists; it should
                // continue into the next round of token checking...
                resultList.push(staticNodeList[finalIter]);
            }
        }
        
        // Copy the AND results for the next token.
        staticNodeList = resultList;
    }
    return staticNodeList;
}

Data URI

If you are like me, you have at one point likely built a website that required at least a few small images. In some cases you can use CSS sprites to combine images and avoid network round trips. In some cases, however, I had to resign myself to the inevitable and incur the cost of an extra round trip. No longer!

Normally, URLs act as pointers to network locations that contain data. For instance, http://www.example.com/ie.gif instructs the Web browser to download the image file named ?ie.gif? from the HTTP server running at www.example.com.

Internet Explorer?8 Beta 2 introduces support for Data URIs. Rather than acting as a resource locator, a Data URI contains the resource data directly within the URI string. In order to embed binary data within the string, the data is first encoded using base64 encoding.

For instance, here is a Data URI that represents a 10x10 blue dot:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA
oAAAAKAQMAAAC3/F3+AAAACXBIWXMAAA7DAAAOwwHHb6hkAA
AAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQ
AAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPA
AAAANQTFRFALfvPEv6TAAAAAtJREFUCB1jYMAHAAAeAAEBGN
laAAAAAElFTkSuQmCC

Internet Explorer?8 Beta 2 permits Data URIs of up to 32kb in length. Careful use of Data URIs in place of URLs can help you avoid costly network round trips and improve the overall performance of your sites.

The Big Picture

Now that I have completed my whirlwind tour of some of the great features that Microsoft will deliver in Internet Explorer?8 Beta 2, I think it's important to take a step back to see the big picture. The focus of the performance improvements in Internet Explorer?8 Beta 2 center on building a platform that allows developers to get more done when they build and browse sites.

With that in mind, I hope you are eager to see how Microsoft's investment to improve scripting speed, download pages faster, and reduce browser overhead enables you to browse faster.

The full benefit of Internet Explorer?8 Beta 2 is not limited to these immediate gains. Not only is Internet Explorer?8 Beta 2 speeding up the Web as it exists today, but it is delivering groundbreaking features that will let you build the next generation of lighting fast websites.

With Internet Explorer?8 Beta 2, one thing is clear. It's a great time to be online.