Degrading Script Tags

by John Resig in eJohn, Tue, 26 Aug 2008 23:47:45 GMT

One thing has always annoyed me about the script tag. Script tags that reference external resources (via the src attribute) are no longer able to execute script embedded within the tag itself.

It doesn't make sense to me that we're forced to write:

<script src="some-lib.js">

when this is so much more elegant:

<script src="some-lib.js">
  var foo = use_some_lib();
  foo.do.stuff();

Only one tag - and the semantics would work like this: The external script would attempt to be loaded (as normal). If the load and execution was error-free then the internal script would be executed as well. If the load or execution failed then the internal script would not be executed (this being the important distinction from the first example, shown above).

We can verify these two facts with some tests:

  1. Test 1: Verify that internal scripts aren't executed, even if an external src is loaded.
  2. Test 2: Verify that internal scripts aren't executed, even if an external src is not loaded.

Running the tests in Firefox, Opera, Safari, and IE show them all passing (the internal scripts are unable to execute).

With this knowledge in place now, let's get to the juicy part: How do we actually implement the above style of script-tag-writing in a way that melds well with our desired style of development?

It's actually terribly simple. I took a copy of jQuery and tacked the following two lines on to the end of the script:

var scripts = document.getElementsByTagName("script");
eval( scripts[ scripts.length - 1 ].innerHTML );

Taking a look at a demo shows it working, using only one script tag:

<script src="jquery1.js">
jQuery(document).ready(function(){
  jQuery("p").addClass("pretty");
});

We have succeeded! but how does the above code work? The short snippet tags advantage of the way in which script tags are loaded and executed. Each script tag within a page may be downloaded in any order (for example, Internet Explorer 8 and Firefox 3.1 are starting to download many scripts in parallel). BUT their execution must come in order AND they must be executed in their exact place in the DOM.

This means that when the script finally executes that it'll be the last script in the DOM - and even the last element in the DOM (the rest of the DOM is built incrementally as it hits more script tags, or until the end of the document).

This particular behavior occurs because scripts are able to document.write, affecting the very nature of the document. The following is perfectly legal (even if you can imagine the trauma that it must cause browser vendors - preventing them from performing some perfectly good optimizations):


With the above taken in mind - let's consider a further optimization to our code. While the above code snippet is generic to any external source file, what if we were to take advantage of the nature of jQuery, simplifying its behavior?

Virtually all jQuery-using code is encased within a call to the document ready function (which delays execution of attached handlers until the DOM is full loaded).

If we were to make some adjustments to our script addition, like so:

var scripts = document.getElementsByTagName("script");
var script = scripts[ scripts.length - 1 ].innerHTML;
if ( script ) {
  jQuery(document).ready(function(){
    jQuery.globalEval( script );
  });
}

We can now get the full advantage of having our scripts inline and not having to write out a document ready call, like so:

<script src="jquery2.js">
jQuery("p").addClass("pretty");

Pretty sexy, huh?

The only thing holding me back from blindly adding the above snippet directly in to jQuery, today, is a small possibility: The chance that someone could copy the full library and stick it in an embedded script tag (rather than calling it from an external file).

Right now if you were to stick either of the above snippets in an embedded script tag you would end up with a never-ending loop. Consider this code:

This code would look for the last script on the page, find it (it would be the script itself), and execute - causing a piece of recursion to occur. It would become necessary to flag the script to prevent it from executing again.

With a little bit of extra work, we can make it possible (demo):

(function(){
var scripts = document.getElementsByTagName("script");
var curScript = scripts[ scripts.length - 1 ];

if ( curScript.executed )
  return;

// ... jQuery ...

curScript.executed = true;
var script = curScript.innerHTML;
if ( script ) {
  jQuery(document).ready(function(){
    jQuery.globalEval( script );
  });
}
})();

I think this particular technique could serve to simplify a number of web pages, even if it's only because:

  1. There's one less script tag on the page.
  2. The dependency link between the script being loaded and the script being executed becomes exceedingly obvious.
  3. The dependent script won't execute (and subsequently cause errors) if the external script is unable to load.
  4. The need for user-authored window load, document ready, etc. functions are no longer necessary (can be hidden within the library).

It's definitely something that'll need to be mulled over as it's pretty fundamentally changing the existing behavior of the script tag (although, it is being done in a completely safe and backwards-compatible manner). But if there's sufficient interest it seems as if this is one area in which external scripts could stand to offer an obvious improvement to the developer.

View: Degrading Script Tags - More entries from eJohn, Web Development

Useful Cloud Computing Blogs

in High Scalability, Tue, 26 Aug 2008 15:04:40 GMT

Can't get enough cloud computing? Then you must really be a glutton for punishment! But just in case, here are some cloud computing resources, collected from various sources, that will help you transform into a Tesla silently flying solo down the diamond lane.

Meta Sources

  • Cloud Computing Email List: An often lively email list discussing cloud computing.
  • Cloud Computing Blogs & Resources. An excellent and big list of cloud resources.
  • Cloud Computing Portal: A community edited database for making the vendor selection process easier.
  • List of Cloud Platforms, Providers, and Enablers.
  • datacenterknowledge.com's Recap: More than 70 Industry Blogs : A nice set of blog's for: Data Center, Web Hosting, Content Delivery Network (CDN), Cloud Computing
  • Specific Blogs

  • James Urquhart's The Wisdom of Clouds : Cloud Computing and Utility Computing for the Enterprise and the Individual. James writes great articles and has a regular can't miss links style post summarizing much of what you need need to know in cloud world.
  • Many more below the fold.

    read more

    Firebug 1.2 Released

    by John Resig in eJohn, Mon, 25 Aug 2008 09:28:09 GMT

    The final version of Firebug 1.2 has been released. The release should be up on the Mozilla Add-ons site today, but it's also up on GetFirebug.com right now.

    John J Barton and Jan Odvarko put a ton of work into this release (you may have noticed the rapid-fire series of beta releases last week - just trying to smooth out the rough edges).

    There have been a number of improvements made (not to mention countless bug fixes). Some of the major points of this release include:

    Firefox 3 support.

    If you've been using the Firebug 1.2 betas you're already on top of this. Now is a good time to verify the version of Firebug that you're using. Go to Tools > Add-ons in Firefox and see what version of Firebug you're running. If it's anything other than 1.2.0bX (where X is a number 1-15) you'll need to forcefully go to the above Firebug URLs and install the new version (the auto-update isn't working for older versions). The most common report of Firebug problems has been related to running Firebug 1.1 in Firefox 3 - which is a mess (hence Firebug 1.2).

    Quality Improvements.

    The Script panel (the JavaScript debugger), the Net panel (network monitoring), and Console panel have all seen considerable updates. They're all much more performant and have a huge number of bug fixes.

    Specifically the Console panel has seen a number of security improvements. We'll be discussing the specific nature of these changes once everyone has had enough time to upgrade to Firebug 1.2.

    A list of all the bug fixes can be found in the full release notes.

    Selective Panel Enablement.

    This is the most drastic UI change of the release. It's also a, seemingly, bizarre addition to the extension. When you now click Firebug for a site you'll encounter an interface that looks something like this:

    Some back story is needed in order to explain why the extension is now set up in this manner. These three panels (Console, Script, Net) have the potential to incur a great deal of overhead into any web sites that utilizes them. There are two pain points, in particular: The Mozilla JavaScript debugger and network monitoring.

    The Mozilla JavaScript debugger is used in two ways in Firebug: First it is used in the Script panel (to debug JavaScript code, naturally), second it is used to figure out where JavaScript errors are coming from in the console. Network monitoring is, naturally, used for the Net panel.

    Here's the important point: The Mozilla JavaScript debugger and network monitoring are both global to Firefox not localized to a single window or tab. This means that when you enable a panel, such as the script panel, it will turn on the JavaScript debugger for all JavaScript code in Firefox.

    Rob Campbell has run some initial numbers and has found that, simply, enabling the script panel anywhere in the browser immediately slows down all JavaScript execution by 25% - for all JavaScript on all tabs in the browser.

    We don't have solid numbers on the networking monitoring overhead yet but we imagine it to be much less, although still occurring on a global all-tabs scale which isn't desirable.

    The important question here is: What is being done to stop this?

    First, it must become necessary to not incur any overhead when using the console panel. This is a ubiquitous part of Firebug and any global overhead presented by it must be removed. This can be done but not without some internal API changes to how Firefox handles and reports error messages. We hope to have something introduced in an upcoming version of Firefox so that we can compensate appropriately in Firebug.

    Second, the JavaScript debugger must be improved. A number of bugs have been filed on this subject and we hope that some of them will make their way into upcoming versions of Firefox (Firebug will be able to immediately improve when that happens). Specializing the debugger to only work against a single tab at a time may not be possible (based upon how Firefox works, internally) but if it is that will be an immediate benefit. Of course, any performance improvements to the debugger will always be helpful.

    Finally, the overhead of network monitoring (if there really is that much - we haven't run performance analysis her yet) needs to be diminished in any way possible.

    All of these things are points that the new Mozilla Firebug team is trying to tackle for the upcoming Firebug 1.3 release.

    Who enabled me?

    Taking in to consideration the above performance points (namely the fact that enabling the Console, Script, or Net panels have the potential to incur a global overhead on all browser tabs) a feature was added to help you minimize your use of the panels in errant tabs.

    If you position your mouse over the Firebug icon, in the Firefox tray, a tooltip will pop up telling you two things: The version of Firebug that you're using and which tabs have some Firebug panels enabled in them.

    It should be noted that the Firebug will be a gray color if no tabs currently have a Firebug panel enabled at all.

    Using the above tooltip you can now go in and selectively disable any panel usage that you are no longer utilizing.

    Suspend/Resume Firebug.

    Of course, when using the above tooltip (or seeing that the Firebug icon is lit up), you'll just want to suspend all use of Firebug panels straight out without having to poke-around each individual tab.

    A new Suspend/Resume menu option has been added that will suspend/resume all active panels. This is a one-click way to keep Firebug in check.


    So what's next for Firebug? I discussed some of the performance auditing that we were doing recently and that will be continuing.

    Specifically, however, we plan on releasing some minor updates to Firebug 1.2 to quell bugs and improve performance (there will likely be a 1.2.1 release coming soon).

    As I mentioned before, Firebug 1.3 is going to be all about performance, quality, and testing. Firebug is the de facto tool for web developers and we need to make sure that its quality does not wane and that we tackle performance head-on (with the eventual goal of having a seamless web development experience).

    View: Firebug 1.2 Released - More entries from eJohn, Web Development

    A Scalable, Commodity Data Center Network Architecture

    in High Scalability, Sun, 24 Aug 2008 20:16:02 GMT

    Looks interesting...

    Abstract:
    Today’s data centers may contain tens of thousands of computers with significant aggregate bandwidth requirements. The network architecture typically consists of a tree of routing and switching elements with progressively more specialized and expensive equipment moving up the network hierarchy. Unfortunately, even when deploying the highest-end IP switches/routers, resulting topologies may only support 50% of the aggregate bandwidth available at the edge of the network, while still incurring tremendous cost. Nonuniform bandwidth among data center nodes complicates application design and limits overall system performance.
    In this paper, we show how to leverage largely commodity Ethernet switches to support the full aggregate bandwidth of clusters consisting of tens of thousands of elements. Similar to how clusters of commodity computers have largely replaced more specialized SMPs and MPPs, we argue that appropriately architected and interconnected commodity switches may deliver more performance at less cost than available from today’s higher-end solutions. Our approach requires no modifications to the end host network interface, operating system, or applications; critically, it is fully backward compatible with Ethernet, IP, and TCP.

    TraceMonkey: JavaScript Lightspeed

    by Brendan Eich in Brendan's Roadmap, Sat, 23 Aug 2008 19:31:00 GMT
    I'm extremely pleased to announce the launch of TraceMonkey, an evolution of Firefox's SpiderMonkey JavaScript engine for Firefox 3.1 that uses a new kind of Just-In-Time (JIT) compiler to boost JS performance by an order of magnitude or more.

    Results

    Let's cut straight to the charts. Here are the popular SunSpider macro- and micro-benchmarks average scores, plus results for an image manipulation benchmark and a test using the Sylvester 3D JS library's matrix multiplication methods:

    assorted-benchmarks.png

    Here are some select SunSpider micro-benchmarks, to show some near-term upper bounds on performance:

    micro-benchmarks.png

    This chart shows speedup ratios over the SpiderMonkey interpreter, which is why "empty loop with globals" (a loop using global loop control and accumulator variables) shows a greater speedup -- global variables in JavaScript, especially if undeclared by var, can be harder to optimize in an interpreter than local variables in a function.

    Here are the fastest test-by-test SunSpider results, sorted from greatest speedup to least:

    sunspider-part-1.png

    The lesser speedups need their own chart, or they would be dwarfed by the above results:

    sunspider-part-2.png

    (Any slowdown is a bug we will fix; we're in hot pursuit of the one biting binary-trees, which is heavily recursive -- it will be fixed.)

    With SunSpider, some of the longest-running tests are string and regular-expression monsters, and since like most JS engines, we use native (compiled C ) code for most of the work, there's not as much speedup. Amdahl's Law predicts that this will bound the weighted-average total Sunspider score, probably to around 2. No matter how fast we JIT the rest of the code, the total score will be... 2.

    But this is only a start. With tracing, performance will keep going up. We have easy small linear speedup tasks remaining (better register allocation, spill reduction around built-in calls). We will trace string and regular expression code and break through the "2" barrier. We will even trace into DOM methods. The tracing JIT approach scales as you move more code into JS, or otherwise into view of the tracing machinery.

    Finally, schrep created a screencast (UPDATE: link fixed) that visually demonstrates the speedup gained by TraceMonkey. These speedups are not just for micro-benchmarks. You can see and feel them.

    How We Did It

    We've been working with Andreas Gal of UC Irvine on TraceMonkey, and it has been a blast. We started a little over sixty days (and nights ;-) ago, and just yesterday, shaver pushed the results of our work into the mozilla-central Hg repository for inclusion in Firefox 3.1. The JIT is currently pref'ed off, but you can enable it via about:config -- just search for "jit" and, if you are willing to report any bugs you find, toggle the javascript.options.jit.content preference (there's a jit.chrome pref too, for the truly adventurous).

    Before TraceMonkey, for Firefox 3, we made serious performance improvements to SpiderMonkey, both to its Array code and to its interpreter. The interpreter speedups entailed two major pieces of work:

    • Making bytecode cases in the threaded interpreter even fatter, so the fast cases can stay in the interpreter function.
    • Adding a polymorphic property cache, for addressing properties found in prototype and scope objects quickly, without having to look in each object along the chain.
    I will talk about the property cache and the "shape inference" it is based on in another post.

    By the way, we are not letting moss grow under our interpreter's feet. Dave Mandelin is working on a combination of inline-threading and call-threading that will take interpreter performance up another notch.

    While doing this Firefox 3 work, I was reminded again of the adage:

    Neurosis is doing the same thing over and over again, expecting to get a different result each time.
    But this is exactly what dynamically typed language interpreters must do. Consider the operator:
    a = b   c;
    
    Is this string concatenation, or number addition? Without static analysis (generally too costly), we can't know ahead of time. For SpiderMonkey, we have to ask further: if number, can we keep the operands and result in machine integers of some kind?

    Any interpreter will have to cope with unlikely (but allowed) overflow from int to double precision binary floating point, or even change of variable type from number to string. But this is neurotic, because for the vast majority of JS code, in spite of the freedom to mutate type of variable, types are stable. (This stability holds for other dynamic languages including Python.)

    Another insight, which is key to the tracing JIT approach: if you are spending much time in JS, you are probably looping. There's simply not enough straight line code in Firefox's JS, or in a web app, to take that much runtime. Native code may go out to lunch, of course, but if you are spending time in JS, you're either looping or doing recursion.

    The Trace Trees approach to tracing JIT compilation that Andreas pioneered can handle loops and recursion. Everything starts in the interpreter, when TraceMonkey notices a hot loop by keeping cheap count of how often a particular backward jump (or any backward jump) has happened.

    for (var i = 0; i < BIG; i  ) {
        // Loop header starts here:
        if (usuallyTrue())
            commonPath();
        else
            uncommonPath();
    }
    

    Once a hot loop has been detected, TraceMonkey starts recording a trace. We use the Tamarin Tracing Nanojit to generate low-level intermediate representation instructions specialized from the SpiderMonkey bytecodes, their immediate and incoming stack operands, and the property cache "hit" case fast-lookup information.

    The trace recorder completes when the loop header (see the comment in the code above) is reached by a backward jump. If the trace does not complete this way, the recorder aborts and the interpreter resumes without recording traces.

    Let's suppose the usuallyTrue() function returns true (it could return any truthy, e.g. 1 or "non-empty" -- we can cope). The trace recorder emits a special guard instruction to check that the truthy condition matches, allowing native machine-code trace execution to continue if so. If the condition does not match, the guard exits (so-called "side-exits") the trace, returning to the interpreter at the exact point in the bytecode where the guard was recorded, with all the necessary interpreter state restored.

    If the interpreter sees usuallyTrue() return true, then the commonPath(); case will be traced. After that function has been traced comes the loop update part i (which might or might not stay in SpiderMonkey's integer representation depending on the value of BIG -- again we guard). Finally, the condition i < BIG will be recorded as a guard.

    // Loop header starts here:
    inlined usuallyTrue() call, with guards
    guard on truthy return value
    guard that the function being invoked at this point is commonPath
    inlined commonPath() call, with any calls it makes inlined, guarded
    i   code, with overflow to double guard
    i < BIG condition and loop-edge guard
    jump back to loop header
    

    Thus tracing is all about speculating that what the interpreter sees is what will happen next time -- that the virtual machine can stop being neurotic.

    And as you can see, tracing JITs can inline method calls easily -- just record the interpreter as it follows a JSOP_CALL instruction into an interpreted function.

    One point about Trace Trees (as opposed to less structured kinds of tracing): you get function inlining without having to build interpreter frames at all, because the trace recording must reach the loop header in the outer function in order to complete. Therefore, so long as the JITted code stays "on trace", no interpreter frames need to be built.

    If the commonPath function itself contains a guard that side-exits at runtime, then (and only then) will one or more interpreter frames need to be reconstructed.

    Let's say after some number of iterations, the loop shown above side-exits at the guard for usuallyTrue() because that function returns a falsy value. We abort correctly back to the interpreter, but keep recording in case we can complete another trace back to the same loop header, and extend the first into a trace tree. This allows us to handle different paths through the control flow graph (including inlined functions) under a hot loop.

    What It All Means

    Pulling back from the details, a few points deserve to be called out:

    • We have, right now, x86, x86-64, and ARM support in TraceMonkey. This means we are ready for mobile and desktop target platforms out of the box.
    • As the performance keeps going up, people will write and transport code that was "too slow" to run in the browser as JS. This means the web can accomodate workloads that right now require a proprietary plugin.
    • As we trace more of the DOM and our other native code, we increase the memory-safe codebase that must be trusted not to have an exploitable bug.
    • Tracing follows only the hot paths, and builds a trace-tree cache. Cold code never gets traced or JITted, avoiding the memory bloat that whole-method JITs incur. Tracing is mobile-friendly.
    • JS-driven
    TraceMonkey advances us toward the Mozilla 2 future where even more Firefox code is written in JS. Firefox gets faster and safer as this process unfolds.

    I believe that other browsers will follow our lead and take JS performance through current interpreter speed barriers, using just-in-time native code compilation. Beyond what TraceMonkey means for Firefox and other Mozilla projects, it heralds the JavaScript Lightspeed future we've all been anticipating. We are moving the goal posts and changing the game, for the benefit of all web developers.

    Acknowledgments

    I would like to thank Michael Franz and the rest of his group at UC Irvine, especially Michael Bebenita, Mason Chang, and Gregor Wagner; also the National Science Foundation for supporting Andreas Gal's thesis. I'm also grateful to Ed Smith and the Tamarin Tracing team at Adobe for the TT Nanojit, which was a huge boost to developing TraceMonkey.

    And of course, mad props and late night thanks to Team TraceMonkey: Andreas, Shaver, David Anderson, with valuable assists from Bob Clary, Rob Sayre, Blake Kaplan, Boris Zbarsky, and Vladimir Vukićević.

    Latency is Everywhere and it Costs You Sales - How to Crush it

    in High Scalability, Fri, 22 Aug 2008 21:28:11 GMT

    Latency matters. Amazon found every 100ms of latency cost them 1% in sales. Google found an extra .5 seconds in search page generation time dropped traffic by 20%. A broker could lose $4 million in revenues per millisecond if their electronic trading platform is 5 milliseconds behind the competition.

    The Amazon results were reported by Greg Linden in his presentation Make Data Useful. In one of Greg's slides Google VP Marissa Mayer, in reference to the Google results, is quoted as saying "Users really respond to speed." And everyone wants responsive users. Ka-ching! People hate waiting and they're repulsed by seemingly small delays.

    The less interactive a site becomes the more likely users are to click away and do something else. Latency is the mother of interactivity. Though it's possible through various UI techniques to make pages subjectively feel faster, slow sites generally lead to higher customer defection rates, which lead to lower conversation rates, which results in lower sales. Yet for some reason latency isn't a topic talked a lot about for web apps. We talk a lot about about building high-capacity sites, but very little about how to build low-latency sites. We apparently do so at the expense of our immortal bottom line.

    I wondered if latency went to zero if sales would be infinite? But alas, as Dan Pritchett says, Latency Exists, Cope!. So we can't hide the "latency problem" by appointing a Latency Czar to conduct a nice little war on latency. Instead, we need to learn how to minimize and manage latency. It turns out a lot of problems are better solved that way.

    How do we recover that which is most meaningful--sales--and build low-latency systems?

    read more

    TraceMonkey

    by John Resig in eJohn, Fri, 22 Aug 2008 16:31:21 GMT

    I've been waiting to blog about this for a long time now. A fantastic new improvement to Mozilla's JavaScript engine (SpiderMonkey) has landed. Code-named TraceMonkey this engine utilizes a techniques, called trace trees (PDF), which adds just-in-time native code compilation to SpiderMonkey.

    A major goal of the project has been to set JavaScript up to compete with natively-compiled code, rather than simply against other interpreters. This means that we're starting to see speeds that are completely out of this league when it comes to performance.

    Results and Try it Yourself

    Here are the results from four benchmarks to give you a taste:


    (Graph courtesy of Brendan Eich.)

    The tests are:

    If you want to try these out for yourself, just snag a nightly of Firefox 3.1, open about:config, and set the following preference to true:

    javascript.options.jit.content

    You should be, happily, in just-in-time tracing land. It's still buggy (hence the reason for hiding behind the preference wall) but it should be good enough to handle most web sites.

    What's especially exciting is that this code is working on x86, x86-64, and ARM - which means that these improvements won't be limited to just the desktop - you'll be able to receive them on your mobile devices as well.

    How Tracing Works

    In simple terms tracing works by watching for commonly-repeated actions (such as loops, function calls, or type checking) and tries to optimize their resulting native code into the lowest number of actions. The premise is rather simple - and it's an advance that we'll probably see proliferate to many interpreters and engines in the upcoming years.

    Andreas Gal published a paper (PDF) on the subject and Brendan Eich has written up a TraceMonkey-specific explanation.

    Some of the improvements made by tracing include:

    • Function Inlining: Removing the overhead of function calls by simply replacing them with their resulting native code.
    • Type Inference: Removing checks surrounding common operators (like " ") when the types contained within a variable are already known. This means that the engine will have already pre-determined, for example, that two strings need to be concated when it sees the " " operator.
    • Looping: The overhead of looping has been grossly diminished. It's one of the most common areas of overhead in JavaScript applications (common repetition of a task) and the constant determining of bounds and the resulting inner code is made negligible.

    The code for this project has come from a number of places - one of which is coming from some code contributed to Mozilla, from Adobe: Tamarin Tracing, specifically the nanojit code that's able to work a lot of this just-in-time magic.

    Development

    The work began just about 60 days ago, working with Andreas Gal of UC Irvine, to integrate the nanojit technology into Spidermonkey. You can hear more about the development from those that were involved: Andreas Gal, Mike Shaver, and Brendan Eich.

    The full code can be found in the TraceMonkey mercurial repository (the commit to merge TraceMonkey into Mozilla core is massive, clocking in at about 4MB).

    If you want to try running your own copy of TraceMonkey on the command-line, just follow these steps:

    hg clone http://hg.mozilla.org/tracemonkey/
    cd tracemonkey/js/src
    make -f Makefile.ref BUILD_OPT=1
    Darwin_OPT.OBJ/js -j

    (The above assumes that you already have Mercurial installed, and are trying to compile on OS X. Your milage may vary. The -j option is what enables jit-ing on the command-line.)

    There is still a ton of work to be done. The incredible speed-ups that we're seeing are only just the beginning. A lot can be done to improve how registers are currently being allocated which will provide even more speed-ups.

    Right now there isn't any tracing being done into DOM methods (only across pure-JavaScript objects) - but that is something that will be rectified. Being able to trace through a DOM method would successfully speed up, not only, math and object-intensive applications (as it does now) but also regular DOM manipulation and property access.

    Ramification

    So what does this all mean? It means that JavaScript is no longer confined by the previously-challenging resource of processing power. With this improvement it's leap-frogged any sort of traditional and has gone head-to-head with computationally-powerful languages like C.

    I fully expect to see more, massive, projects being written in JavaScript. Projects that expect the performance gains that we're starting to see. Applications that are number-heavy (like image manipulation) or object-heavy (like relational object structures).

    One area that I'm especially excited about is in relation to Canvas. The primary thing holding back most extensive Canvas development hasn't been rendering - but the processor limitations of the language (performing the challenging mathematical operations related to vectors, matrices, or collision detection). I expect this area to absolutely explode after the release of Firefox 3.1 as we start to see this work take hold.

    Seeing releases like this are absolutely exciting for me. JavaScript is absolutely the little-language-that-could - continually routing around any of its short-comings and blowing away all of its expectations. I look forward to using it for many, many, years to come.

    View: TraceMonkey - More entries from eJohn, Web Development

    Dojo’s Query System: No, Really, It’s That Fast

    by Alex Russell in Continuing Intermittent Incoherency, Thu, 21 Aug 2008 23:51:59 GMT

    As outlined by JQuery lead John Resig in this post, it’s hard not to notice how much Dojo’s query engine stomps on the the competition on current browsers. Dojo will load even quicker when we’re able to remove the XPath branch in the query engine which is currently only being kept on life support for the benefit of Firefox. The rest of Dojo has been designed with the same eye to real-world performance factors in mind, hence the build and package systems which help you implement Steve Souders’ performance recommendations gradually, without major code changes.

    Regardless of how good it feels to see our numbers recognized for all the hard work that has gone into the Dojo design, I think it’s also good to keep them in perspective. Most of the available query engines are “fast enough” – although there’s really no reason why your query engine of choice should be twice as slow as Dojo’s, given that ours is 100-point Open Source. Having a native implementation is nice, but the primary benefit now is in reducing the number of bytes we need to send on the wire, not in actual query speed advantages. Making queries faster isn’t in the critical path for improving the real-world performance of any Dojo apps I know of, and I bet the same is true for JQuery users. Reducing the size of the libraries, on the other hand, is still important. Now that we’re all fast enough, it’s time that we stopped beating on this particular drum lest we lose the plot and the JavaScript community continue to subject itself to endless rounds of benchmarketing.

    querySelectorAll in Firefox 3.1

    by John Resig in eJohn, Wed, 20 Aug 2008 21:38:09 GMT

    A brand-new implementation of the Selectors API has landed in the latest Firefox nightlies (and in Firefox 3.1a1) - on track to head your way in the upcoming Firefox 3.1 release.

    I've talked about this API before (1, 2) and while I do have some misgivings about the current API (which will be remedied in upcoming revisions of the spec) there is one thing that is undeniable about it: It is extraordinarily fast.

    Thankfully, implementations haven't scarified specification compatibility for performance and we can see both the Firefox and WebKit implementations coming in at 99.3% passing the Selectors API test suite. Opera is working on their implementations, slated for Opera 10, and Microsoft has an implementation in beta 1 of Internet Explorer 8. This means that by late this year all browsers will have an implementation of the Selectors API in the market.

    JavaScript libraries have already been working to utilize this new API, preparing for when it'll eventually be ready for all to use. The current score is:

    • Dojo has querySelectorAll support in Dojo 1.1.1, although support for Safari 3.1 is disabled (there were troublesome crashing bugs in early versions of Safari 3.1 that have since been resolved).
    • Prototype has querySelectorAll support in their Git repository (presumably to be rolled into their next release).
    • jQuery has querySelectorAll support in an experimental plugin (to land in the next release).

    This has lead to some interesting numbers (utilizing the same testing techniques employed by the WebKit team):

    Library Time (ms)
    Prototype 1.6.0.2 44677
    Prototype Git 9914 (123% slower than native, 351% faster than DOM)
    jQuery 1.2.7 Plugin 35045
    jQuery Plugin 4731 (7% slower than native, 641% faster than DOM)
    Dojo 1.0.2 20782
    Dojo 1.1.1 5669 (28% slower than native, 267% faster than DOM)
    Native 4441

    That means that libraries that utilize querySelectorAll will be running 2-6x faster than their previous versions. This is already quite impressive.

    There are two points to consider when using this API:

    1. That you need to try and keep the overhead on top of the querySelectorAll method as low as possible.
    2. That it becomes advantageous to avoid the querySelectorAll API in some extreme cases (for example, jQuery avoids it for #id queries, allowing it to go over 10x faster than querySelectorAll).

    A lot of bare-bones selectors library implementations are going to look something like this:

    function querySelectorAll(selector){
      try {
        return Array.prototype.slice.call(
          document.querySelectorAll( selector ) );
      } catch(e){}
     
      return myOtherLibrary( selector );
    }

    Note two points: There's a try-catch block there to capture any syntax errors that are generated by querySelectorAll (syntax errors could be generated by APIs that the implementation doesn't understand - like jQuery's div:first, for example). If no exception is thrown while retrieving the results we need to convert it into an array (most libraries convert result sets into arrays - or bless them in some manner).

    Tackling both of these points will introduce some level of overhead in a library (on top of the native querySelectorAll implementation). Of course it's never as simple as it should be, many libraries extend these return sets with additional functionality so the overhead will be that much greater.

    Regardless it's readily apparent that this API will be quite instrumental in trivializing one of the most difficult parts of implementing a new JavaScript library. Everything after this is just gravy.

    Name Soup

    by Alex Russell in Continuing Intermittent Incoherency, Mon, 18 Aug 2008 18:57:27 GMT

    There still seems to be an amazing amount of FUD going around regarding the Harmony announcement. There is clearly a very different perspective from those who have been sitting inside the WG for the past year (as Kris Zyp and I have been lucky to). Inside the WG, the change seems a welcome way to break a logjam of reasonably held opinions of people who are all acting in good faith. From the outside, it all looks like confusion and game-playing.

    One of the things, though, that keeps getting me frustrated as I read the “coverage” is that the names people use are confused. Probably because the names are confusing. Here’s a quick glossary:

    ECMAScript 3
    Aka: JavaScript, ES3, ECMAScript 262-3, and JScript.

    The current JavaScript that every browser implements (more or less). This is the current ratified standard and represents the 3rd edition of the ECMAScript spec. It is very old. Nothing else in this list is (yet) a ratified standard of any sort.

    ECMAScript 4
    Aka: ES4, “JavaScript 2″.

    A new language which was to be mostly backwards compatible but add optional (gradual) typing and class-based inheritance. Based loosely on Adobe’s ActionScript 3. This is the language effort which died as a result of Harmony.

    ECMAScript 3.1
    Aka: ES3.1. A set of small additions to ES3.

    Planning for this edition was started at Microsoft and Yahoo’s behest late last year, causing the split in the working group which has been healed by the Harmony announcement.

    ActionScript 3
    Aka: AS3

    Adobe’s current JavaScript-like language, only with many features lifted from languages like Java which also enforce types and class-based semantics. This was the starting point for much of the work which became known as ES4.

    Tamarin
    A JIT-ing byte-code virtual machine (VM) which is at the core of the Flash Player and was donated by Adobe to the Mozilla Foundation. This is the VM that runs ActionScript 3 code today but will likely run “real” JavaScript for Mozilla in the future. It is not a full implementation of ES3 or ES4, but instead implements its own byte-code and needs to be wedded to a “front end” (like the ActionScript 3
    compiler from Adobe) in order to be usable by programmers.
    Tamarin-tracing
    A VM which implements the same byte-code language as Tamarin (known as “ABC”) but which is designed for use in mobile devices and other scenarios where code size and VM footprint are important. It implements trace-tree JIT-ing as a way to speed up hot-spots. Also donated to Mozilla by Adobe.
    TC39
    The name of the ECMA technical committee which is chartered to evolve the JavaScript language.
    Harmony
    A new code-name for a language which is to come after ES3.1. It will feature many of the things ES4 was trying to accomplish, but may attempt them from different directions and will
    focus much more on incremental, step-wise evolution of the language.
    JavaScript 2
    A now-defunct name. This name was originally given to Waldemar Horwat’s first proposal at a large-scale evolution of the JavaScript language in 1999. That effort did not succeed (although Microsoft implemented some of it in JScript.NET) and subsequent work via the current TC39 charter to build ES4 has sometimes been given the name “JavaScript 2″, but it never really stuck. Not a name that describes any ratified standard or current proposal.
    ECMAScript
    The formalized name of the JavaScript language. Since Sun Microsystems owns the name JavaScript and has no idea what to do with the trademark (but has been benevolent thus far), the ECMA committee which standardized the language was forced to adopt a different name.

    Wuala - P2P Online Storage Cloud

    in High Scalability, Mon, 18 Aug 2008 11:39:41 GMT

    How do you design a reliable distributed file system when the expected availability of the individual nodes are only ~1/5? That is the case for P2P systems. Dominik Grolimund, the founder of a Swiss startup Caleido will show you how! They have launched Wuala, the social online storage service which scales as new nodes join the P2P network.

    The goal of Wua.la is to provide distributed online storage that is:

    • large
    • scalable
    • reliable
    • secure

    by harnessing the idle resources of participating computers.

    This challenge is an old dream of computer science. In fact as Andrew Tanenbaum wrote in 1995:
    "The design of a world-wide, fully transparent distributed filesystem fot simultaneous use by millions of mobile and frequently disconnected users is left as an exercise for the reader"

    After three years of research and development at at ETH Zurich, the Swiss Federal Institute of Technology on a distributed storage system, Caleido is ready to unveil the result: Wuala. Wuala is a new way of storing, sharing, and publishing files on the internet. It enables its users to trade parts of their local storage for online storage and it allows us to provide a better service for free. In this Google Tech Talk, Dominik will explain what Wuala is and how it works, and he will also show a demo.

    read more

    Strategy: Serve Pre-generated Static Files Instead Of Dynamic Pages

    in High Scalability, Sat, 16 Aug 2008 16:53:31 GMT

    Pre-generating static files is an oldy but a goody, and as Thomas Brox Røst says, it's probably an underused strategy today. At one time this was the dominate technique for structuring a web site. Then the age of dynamic web sites arrived and we spent all our time worrying how to make the database faster and add more caching to recover the speed we had lost in the transition from static to dynamic.

    Static files have the advantage of being very fast to serve. Read from disk and display. Simple and fast. Especially when caching proxies are used. The issue is how do you bulk generate the initial files, how do you serve the files, and how do you keep the changed files up to date? This is the process Thomas covers in his excellent article Serving static files with Django and AWS - going fast on a budget", where he explains how he converted 600K thousand previously dynamic pages to static pages for his site Eventseer.net, a service for tracking academic events.

    Eventseer.net was experiencing performance problems as search engines crawled their 600K dynamic pages. As a solution you could imagine scaling up, adding more servers, adding sharding, etc etc, all somewhat complicated approaches. Their solution was to convert the dynamic pages to static pages in order to keep search engines from killing the site. As an added bonus non logged-in users experienced a much faster site and were more likely to sign up for the service.

    The article does a good job explaining what they did, so I won't regurgitate it all here, but I will cover the highlights and comment on some additional potential features and alternate implementations...

    read more

    Registration Open for jQuery Conference 2008

    in JQuery Blog, Fri, 15 Aug 2008 11:35:55 GMT

    Registration for jQuery Conference 2008 is officially open. Register now to ensure your spot!
    As announced, this one-day conference will be held in Boston on Sunday, September 28, and will feature two tracks of presentations (beginner and advanced) from jQuery project members and a few special guest speakers. A registration fee of $50 will help cover the cost of the venue, as well as food, beverages, and T-shirts for all attendees.

    We’re finalizing a convenient venue, especially for those who will be attending The Ajax Experience conference the following Monday through Wednesday. We’re still firming up the agenda as well, but you can expect this to be a blow-out event.

    If you have any questions, please feel free to contact us at events [at] learningjquery.com

    Podcast #2, SXSW, Ninja Articles

    by John Resig in eJohn, Fri, 15 Aug 2008 11:21:34 GMT

    Open Web Podcast #2

    The second edition of the Open Web Podcast is now live. In this episode we brought on Brendan Eich and Arun Ranganathan (both of Mozilla) to discuss the recent changes that occurred in the ECMAScript 3.1/ECMAScript 4 processes that resulted in ECMAScript Harmony. This is a dense podcast - going just over an hour.

    The podcast is available as an mp3, ogg, an RSS feed, and on iTunes.

    Next week we're hoping to bring on some people from the Microsoft JScript team to discuss the recent changes and how they plan on implementing them in Internet Explorer. The topic isn't clear for the week after that, but we'll probably want to get back to discussing HTML 5 of the new Open Web Foundation.

    Also, we now have a dedicated site for the podcast: openwebpodcast.com.

    SXSW 2009

    I've submitted two talks to South by Southwest 2009 - naturally both on JavaScript. If these talks interest you please feel free to vote on them appropriately. Last year there were a lot of complaints concerning the lack of technical talks - I hope to rectify that this year.

    More Secrets of JavaScript Libraries

    In a reprise from last year's popular panel - the JavaScript libraries authors are getting together again to impart their what they've learned from their experience in developing solid, world-class, JavaScript libraries. Covering everything from advanced aspects of the JavaScript language, to handling cross-browser issues, all the way up to packaging and distribution. A complete set of knowledge for a JavaScript developer.

    I plan on having representatives from Dojo, Yahoo UI, and Prototype on the panel (will probably switch up the speakers from last year, just to keep things interesting).

    Practical JavaScript Development

    Modern JavaScript development can be quite harrowing. With a multitude of browsers to support and a bevy of design and performance considerations - only the best solutions will suffice. In this talk JavaScript developers will be given the best advice for improving the quality of your JavaScript code, writing reusable JavaScript code-bases, and tackling difficult cross-browser situations; providing you with an expert level of knowledge, immediately.

    Secrets of the JavaScript Ninja Articles

    Work continues on my upcoming book (about halfway done at this point - working on Chapter 10). But in the meantime some article extracts have been released on Ajaxian:

    Enjoy! Note that these are only extracts of the larger chapters: Closures and Function Prototypes.

    Harmony Fallout

    by Alex Russell in Continuing Intermittent Incoherency, Fri, 15 Aug 2008 08:33:17 GMT

    There’s a lot of weirdness going on around the Harmony announcement. This post in particular tries to dig into some of the wrangling that caused the ES4/3.1 split and what the Oslo resolution “means”, but I’m afraid that much of the analysis is being done without the benefit of an inside view of the WG process.

    At the risk of talking too much out of school, I want to set the record straight in some ways. First, let me set some facts out:

    • ES4, as outlined last fall, was not ActionScript 3. Major changes to the semantics of Adobe’s initial contribution ensured that any truly compliant ES4 implementation from Adobe would have required many concessions, including the inclusion of a client-side compiler. ES4 without eval() (ala AS3) would never have cut it as a “real” ES4.
    • Adobe had not donated “ActionScript 3″ to Mozilla nor Open Sourced ActionScript 3. Adobe had donated a high-performance byte-code VM which a separate front-end compiler targeted. It is absolutely possible that the Tamarin VM can and will run whatever syntax for the next version of JavaScript is ratified. The design of the VM is, of course, predicated upon the language semantics but lets not confuse the front-end compiler and the language that it consumes with the VM and byte-code format which it executes. The front-end compiler was not donated to Mozilla (although something similar exists in the OSS’d Flex SDK) nor does it ship inside of the Flash player today. Adobe can continue to evolve their developer languages and byte-code VMs independently so long as they never ship an eval() feature. Even if they do, there are other (harder to swallow) options available, but no road is cut off to Adobe which was not already long-since abandoned in other ways by the ES4 process.
    • Like Adobe, Microsoft has jumped ahead in the evolution of JavaScript via the seemingly forgotten JScript.NET. Like Adobe, Microsoft has had to come back from that position to meet the web where it really is. Microsoft now ships 3 – yes, that’s right, three – JavaScript-ish languages which are capable of running in a browser:
      • JScript (via Windows Scripting Host)
      • JScript.NET
      • JScript for the DLR (via Silverlight)

      Make no mistake about it, these are all separate implementations which likely share little if any code. The DLR variant is even new in the last several years. Creating a new JavaScript compiler and runtime is not an overly onerous task for MSFT and clearly not one that will take a long time should the occasion arise. What’s confusing and can likely be tied to strategic wrangling is the puzzling lack of progress in the WSH version of JScript (the one everyone uses day-to-day). Any strategic discussion of JScript as a platform needs to start from this perspective.

    • Much in ES4 was new. The gradual typing system (which I’m a big supporter of) was something of a large-scale experiment coupled with as much rigor as I’ve ever seen in a standards body in proving things out in an RI. The Class system (which I wasn’t a big supporter of) needed to marry class-based inheritance to prototypal inheritance in ways which were new. ES4 contained many good features and syntactic forms which were borrowed from other places, but as Brendan Eich has said, it was a process of synthesis plus invention. In my opinion, much of the failure of ES4 as an initiative can be traced to significant failings of ActionScript 3 as a language. AS3 is a Java-like language with a Java-like execution model. JavaScript is a dynamic language with a dynamic execution model. The gulf in expectations between those camps turns up in every corner of the language design. For instance: what does it mean to load new code? Are classes forever “closed” or can they be re-opened? Do you really need the static and final keywords? Solving these issues in the context of the old is easy. In the context of the new, it’s hard. ES4 suffered because it had to do it in a new world which no one was yet writing code for.

    So, lets pop up and talk about strategy for a minute. Fundamentally, very little has changed in terms of available strategic options for any of the players:

    • MSFT can still hold the web hostage to their ailing WSH VM by continuing to ignore its performance, regardless of bug fixes and syntactic updates. Doesn’t matter if it’s amputation or debilitating arthritis, crippled is crippled. For what it’s worth, my interactions with the MSFT reps on TC39 give me no reason to believe that they won’t be improving their VM.
    • Adobe can still chose to implement a language which implements an ECMA spec. They can do this any time they damn-well please. It may not align so cleanly with their current technology roadmap, but it’s absolutely feasible and when Mozilla ships a “regular JavaScript” front-end to the Tamarin back-end, it’ll be even easier. Note that this plan can be done in parallel with AS3 evolution since Tamarin (as a VM) need not be aware of any language semantics on its own.
    • Browser vendors can still wring large speedups out of ES3 and 3.1

    What died here wasn’t Adobe’s attempts to “own” a spec. If there were such hopes in play, they had been quietly put down one rational, backwards compatible decision after another in the year preceding the Oslo meeting. What died was an assumption that the web can evolve without implementations being out in front of the spec. AS3 was one implementation of a JavaScript-like language that might have been a contender for crown of “the next one”, but so was JScript.NET. That neither of them “won” simply because they had been built in good faith is as true a sign as I can find that the process is working. Adobe gets it. Lets end the silly meme that “Adobe lost” or that “Microsoft won”. The game has hardly begun and it won’t be settled in a standards body anyway. What matters – and what we all need to keep our eyes keenly trained on – is what the big implementations do in the way of compatibility, performance, and feature set once ES3.1 arrives.

     

    Web Development

    Web development is a broad term that incorporates all areas of developing a web site for the World Wide Web. This can include e-commerce business development, web design, web content development, client-side/server-side coding, and web server configuration. However, among web professionals, "web development" usually refers only to the non-design aspects of building Web sites, e.g. writing markup and coding. Web development can range from developing the simplest static single page of plain text to the most complex web-based internet applications, electronic businesses, or social network services.

    Feeds