Crockford, webhosting, online dating, JSON, alert

December 10, 2009 11:14 am | 23 Comments

This is a fun story that has a security and performance point to it.

Earlier today, Dion Almaer tweeted:

Wow, Doug added an alert() to http://www.json.org/json2.js which just alerted a LOT of people on the Internet. Proving a point on hotlinks?

I was talking to Doug about his keynote at Add-on-Con tomorrow, and asked him what the motivation was for this alert message. It turns out his webhosting service had contacted him about the unusually high amount of traffic on json.org. Doug investigated and discovered that OnlineBootyCall was linking directly to http://json.org/json.js, in spite of this statement in the file:

USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL.

Linking directly to http://json.org/json.js is bad. Certainly, it puts a load on Doug’s webhosting company that shouldn’t be there. But more importantly, it exposes the content site to security and performance vulnerabilities. Loading third party scripts into the parent window gives that third party access to cookies and other potentially confidential information in the page. Accessing that script from a third party domain requires an additional DNS lookup (which can be costly). Also, if the script is at the top of the page (which it is in this case) and the third party site is slow or not responding, the entire page is left blank for thirty seconds or more.

It’s best to reduce the number of third party scripts on your site. That was the reason Doug added the alert message to the top of json.js. If you haven’t gone to OnlineBootyCall yet today, here’s what you would’ve seen:

In Doug’s words,

I’m helping onlinebootycall improve its performance.

23 Comments

Speed Tracer – visibility into the browser

December 10, 2009 7:46 am | 9 Comments

Is it just me, or does anyone else think Google’s on fire lately, lighting up the world of web performance? Quick review of news from the past two weeks:

Speed Tracer was my highlight from last night’s Google Campfire One. The event celebrated the release of GWT 2.0. Performance and “faster” were emphasized again and again throughout the evening’s presentations (I love that). GWT’s new code splitting capabilities are great for performance, but Speed Tracer easily wowed the audience – including me. In this post, I’ll describe what I like about Speed Tracer, what I hope to see added next, and then I’ll step back and talk about the state of performance profilers.

Getting started with Speed Tracer

Some quick notes about Speed Tracer:

  • It’s a Chrome extension, so it only runs in Chrome. (Chrome extensions is yet another announcement this week.)
  • It’s written in GWT 2.0.
  • It works on all web sites, even sites that don’t use GWT.

The Speed Tracer getting started page provides the details for installation. You have to be on the Chrome dev channel. Installing Speed Tracer adds a green stopwatch to the toolbar. Clicking on the icon starts Speed Tracer in a separate Chrome window. As you surf sites in the original window, the performance information is shown in the Speed Tracer window.

Beautiful visibility

When it comes to optimizing performance, developers have long been working in the dark. Without the ability to measure JavaScript execution, page layout, reflows, and HTML parsing, it’s not possible to optimize the pain points of today’s web apps. Speed Tracer gives developers visibility into these parts of page loading via the Sluggishness view, as shown here. (Click on the figure to see a full screen view.) Not only is this kind of visibility great, but the display is just, well, beautiful. Good UI and dev tools don’t often intersect, but when they do it makes development that much easier and more enjoyable.

Speed Tracer also has a Network view, with the requisite waterfall chart of HTTP requests. Performance hints are built into the tool flagging issues such as bad cache headers, exceedingly long responses, Mozilla cache hash collision, too many reflows, and uncompressed responses. Speed Tracer also supports saving and reloading the profiled information. This is extremely useful when working on bugs or analyzing performance with other team members.

Feature requests

I’m definitely going to be using Speed Tracer. For a first version, it’s extremely feature rich and robust. There are a few enhancements that will make it even stronger:

  • overall pie chart – The “breakdown by time” for phases like script evaluation and layout are available for segments within a page load. As a starting point, I’d like to see the breakdown for the entire page. When drilling down on a specific load segment, this detail is great. But having overall stats will give developers a clue where they should focus most of their attention.
  • network timing – Similar to the issues I discovered in Firebug Net Panel, long-executing JavaScript in the main page blocks the network monitor from accurately measuring the duration of HTTP requests. This will likely require changes to WebKit to record event times in the events themselves, as was done in the fix for Firefox.
  • .HAR support – Being able to save Speed Tracer’s data to file and share it is great. Recently, Firebug, HttpWatch, and DebugBar have all launched support for the HTTP Archive file format I helped create. The format is extensible, so I hope to see Speed Tracer support the .HAR file format soon. Being able to share performance information across tools and browsers is a necessary next step. That’s a good segue…

Developers need more

Three years ago, there was only one tool for profiling web pages: Firebug. Developers love working in Firefox, but sometimes you just have to profile in Internet Explorer. Luckily, over the last year we’ve seen some good profilers come out for IE including MSFast , AOL Pagetest, WebPagetest.org, and dynaTrace Ajax Edition. DynaTrace’s tool is the most recent addition, and has great visibility similar to Speed Tracer, as well as JavaScript debugging capabilities. There have been great enhancements to Web Inspector, and the Chrome team has built on top of that adding timeline and memory profiling to Chrome. And now Speed Tracer is out and bubbling to the top of the heap.

The obvious question is:

Which tool should a developer choose?

But the more important question is:

Why should a developer have to choose?

There are eight performance profilers listed here. None of them work in more than a single browser. I realize web developers are exceedingly intelligent and hardworking, but no one enjoys having to use two different tools for the same task. But that’s exactly what developers are being asked to do. To be a good developer, you have to be profiling your web site in multiple browsers. By definition, that means you have to install, learn, and update multiple tools. In addition, there are numerous quirks to keep in mind when going from one tool to another. And the features offered are not consistent across tools. It’s a real challenge to verify that your web app performs well across the major browsers. When pressed, rock star web developers I ask admit they only use one or two profilers – it’s just too hard to stay on top of a separate tool for each browser.

This week at Add-on-Con, Doug Crockford’s closing keynote is about the Future of the Web Browser. He’s assembled a panel of representatives from Chrome, Opera, Firefox, and IE. (Safari declined to attend.) My hope is they’ll discuss the need for a cross-browser extension model. There’s been progress in building protocols to support remote debugging: WebDebugProtocol and Crossfire in Firefox, Scope in Opera, and ChromeDevTools in Chrome. My hope for 2010 is that we see cross-browser convergence on standards for extensions and remote debugging, so that developers will have a slightly easier path for ensuring their apps are high performance on all browsers.

9 Comments

(down)Loading JavaScript as strings

December 7, 2009 10:58 am | 13 Comments

The Gmail mobile team and Charles Jolley from SproutCore have recently published some interesting techniques for loading JavaScript in a deferred manner. Anyone building performant web apps is familiar with the pain inflicted when loading JavaScript. These new techniques are great patterns. Let me expand on how they work and the context for using them. FYI – Charles is presenting this technique at tomorrow’s Velocity Online Conference. Check that out if you’re interested in finding out more and asking him questions.

When to defer JavaScript loading

I’ve spent much of the last two years researching and evangelizing techniques for loading scripts without blocking. These techniques address the situation where you need to load external scripts to render the initial page. But not all JavaScript is necessary for loading the initial page. Most Web 2.0 apps include JavaScript that’s only used later in the session, depending on what the user clicks on (dropdown menus, popup DIVs, Ajax actions, etc.). In fact, the Alexa top ten only use 25% of the downloaded JavaScript to load the initial page (see Splitting the Initial Payload).

The performance optimization resulting from this observation is clear – defer the loading of JavaScript that’s not part of initial page rendering. But how?

Deferred loading is certainly achievable using the non-blocking techniques I’ve researched – but my techniques might not be the best choice for this yet-to-be-used JavaScript code. Here’s why: Suppose you have 300K of JavaScript that can be deferred (it’s not used to render the initial page). When you load this script later using my techniques, the UI locks up while the browser parses and executes that 300K of code. We’ve all experienced this in certain web apps. After the web app initially loads, clicking on a link doesn’t do anything. In extreme situations, the browser’s tab icon stops animating. Not a great user experience.

If you’re certain that code is going to be used, then so be it – parse and execute the code when it’s downloaded using my techniques. But in many situations, the user many never exercise all of this deferred code. She might not click on any of the optional features, or she might only use a subset of them.

Is there a way to download this code in a deferred way, without locking up the browser UI?

Deferred loading without locking up the UI

I recently blogged about a great optimization used in mobile Gmail for loading JavaScript in a deferred manner: Mobile Gmail and async script loading. That team was acutely aware of how loading JavaScript in the background locked up mobile browsers. The technique they came up with was to wrap the JavaScript in comments. This allows the code to be downloaded, but avoids the CPU lockup for parsing and execution. Later, when the user clicks on a feature that needs code, a cool dynamic technique is used to extract the code from the comments and eval it.

This technique has many benefits. It gets the download delays out of the way, so the code is already in the client if and when the user needs it. This technique avoids the CPU load for parsing and executing the code – this can be significant given the size of JavaScript payloads in today’s web apps. One downside of this technique results from cross-site scripting restrictions – the commented out code must be in the main page or in an iframe.

This is where Charles Jolley (from the SproutCore team) started his investigation. He wanted a technique that was more flexible and worked across domains. He presents his new technique (along with results from experiments) in two blog posts: Faster Loading Through Eval() and Cut Your JavaScript Load Time 90% with Deferred Evaluation. This new technique is to capture the deferred JavaScript as strings which can be downloaded with negligible parsing time. Later, when the user triggers a feature, the relevant code strings are eval’ed.

His experiment includes three scenarios for loading jQuery:

  • Baseline – load jQuery like normal via script tag.  jQuery is parsed and executed immediately on load.
  • Closure – load jQuery in a closure but don’t actually execute the closure until after the onload event fires.  This essentially means the jQuery code will be parsed but not executed until later.
  • String – load jQuery as a giant string.  After the onload event fires, eval() the string to actually make jQuery ready for use.

The results are promising and somewhat surprising – in a good way. (Note: results for IE are TBD.)

Charles reports two time measurements.

  • The load time (blue) is how long it takes for the onload event to fire. No surprise – avoiding execution (“Closure”) results in a faster load time than normal script loading, and avoiding parsing and execution (“String”) allows the page to load even faster.
  • The interesting and promising stat is the setup time (green) – how long it takes for the deferred code to be fully parsed and executed. The importance of this measurement is to see if using eval has penalties compared to the normal way of loading scripts. It turns out that in WebKit, Firefox, and iPhone there isn’t a significant cost for doing eval. Chrome is a different story and needs further investigation.

These techniques for deferred loading of JavaScript are great additions to have for optimizing web site performance. The results for IE are still to come from Charles, and will be the most important for gauging the applicability of this technique. Charles is presenting this technique at tomorrow’s Velocity Online Conference. I’m hoping he’ll have the IE results to give us the full picture on how this technique performs.

13 Comments

How browsers work

December 4, 2009 1:11 pm | 2 Comments

My initial work on the Web was on the backend – C++, Java, databases, Apache, etc. In 2005, I started focusing on web performance. To get a better idea of what made them slow, I surfed numerous web sites with a packet sniffer open. That’s when I discovered that a bulk of the time spent loading a web site occurs on the frontend, after the HTML document arrives at the browser.

Not knowing much about how the frontend worked, I spent a week searching for anything that could explain what was going on in the browser. The gem that I found was David Hyatt’s blog post entitled Testing Page Load Speed. His article opened my eyes to the complexity of what the browser does, and launched my foray into finding ways to optimize page load times resulting in things like YSlow and High Performance Web Sites.

Today’s post on the Chromium Blog (Technically speaking, what makes Google Chrome fast?), contains a similar gem. Mike Belshe, Chrome developer and co-creator of SPDY, talks about the performance optimizations inside of Chrome. But in so doing, he also reveals insights into how all browsers work and the challenges they face. For example, until I saw this, I didn’t have a real appreciation for the performance impact of DOM bindings – the connections between the JavaScript that modifies web pages and the C++ that implements the browser. He also talks about garbage collection, concurrent connections, lookahead parsing and downloading, domain sharding, and multiple processes.

Take 16.5 minutes and watch Mike’s video. It’s well worth it.

2 Comments

Google Analytics goes async

December 1, 2009 4:36 pm | 55 Comments

Today’s announcement that Google Analytics Launches Asynchronous Tracking is music to my ears. Not only does it make web sites faster, switching over to this async pattern improves uptime and increases the amount of analytics data gathered. I’ll touch on each of these three benefits, and wrap-up with an overview of the new code snippet.

Faster

The pain of loading JavaScript files is that they block the page from rendering and block other resources from downloading. There are workarounds to these problems. Chapter 4 of Even Faster Web Sites describes six techniques for Loading Scripts Without Blocking. One of those, the Script DOM Element approach, is the technique used in the new Google Analytics async pattern. Google Analytics’ ga.js file is a perfect example of a script that should be loaded asynchronously – it doesn’t add any content to the page, so we want to load it without blocking the images and stylesheets that give users what they really came to see.

Improved Uptime

What happens if a script takes a long time to load, or fails to load? Because scripts block rendering, users are left staring at an empty page. Google Analytics has an amazing infrastructure behind it, but any resource, especially from third parties, should be added cautiously. It’s great that the GA team is evangelizing a pattern that allows the web site to render while ga.js is being downloaded.

More Data

One workaround to the blocking problem is to move scripts to the bottom of the page. In fact, this is exactly what’s suggested in the old ga.js snippet. But this means users who leave a page quickly won’t generate any analytics data (they leave before the script at the bottom finishes loading). Moving to the async pattern and loading it at the bottom of the page’s head, as suggested, means more of these quick page views get measured. This is too good to believe – not only do you get a faster, more resilient page, but you actually get better insights into your traffic.

The Async Snippet

Just to be clear, ga.js will continue to work even if web site owners don’t make any changes. But, if you want a faster site, greater uptime, and more data, here’s what the new async snippet looks like:

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);

(function() {
var ga = document.createElement('script');
ga.src = ('https:' == document.location.protocol ?
    'https://ssl' : 'http://www') +
    '.google-analytics.com/ga.js';
ga.setAttribute('async', 'true');
document.documentElement.firstChild.appendChild(ga);
})();

It’s extremely cool to see this pattern being evangelized for such a major piece of the Internet. A few items of note:

  • Obviously, you have to replace “UA-XXXXX-X” with your ID.
  • Since ga.js is being loaded asynchronously, there has to be a way for web site owners to couple their desired GA functions with the code when it finishes loading. This is done by pushing commands onto the Google Analytics queue object, _gaq.
  • Once all your callback commands are queued up, the ga.js script gets loaded. This is wrapped inside an anonymous function to avoid any namespace conflicts.
  • Inside the anonymous function is where we see the Script DOM Element approach being used – with two nice improvements. A ‘script’ element is created and its SRC is set to the appropriate ga.js URL. Looking ahead to support of asynchronous scripts in HTML5, the ‘async’ attribute is set to ‘true’. Very nice! The main benefit of this is it tells the browser that subsequent scripts can be executed immediately – they don’t have to wait for ga.js. The last line adds the script element to the DOM. This is what triggers the actual download of ga.js. In most of my code I do document.getElementsByTagName(“head”)[0].appendChild, but that fails if the document doesn’t have a head element. This is a more robust implementation.

It’s always hard to find the right spot on the complexibility curve. This async snippet hits it just right. It’s slightly more complex than the old pattern, but not by much. Besides the benefits highlighted here, this new pattern is able to support more advanced usage patterns, including pushing an array of commands and pushing functions.

The theme driving much of my work this year is fast by default. I want high performance to be baked into the major components of the Web, so things are just fast. Seeing Google Analytics adopt this high performance async pattern is a huge win. But the proof is in the pudding. If you switch over to the new async pattern, measure how it affects your page load times and the amount of data gathered, and add a comment below. My prediction: 200ms faster and 10% more data. What do you see?

55 Comments

Chrome dev tools

November 30, 2009 5:23 pm | 2 Comments

I just finished reading the latest post on the Chromium Blog: An Update for Google Chrome’s Developer Tools. Dynatrace’s Ajax Edition was impressive – just take a look at what John Resig had to say. I’m also impressed by what’s been added to WebKit’s Web Inspector and Chrome’s dev tools. You should definitely take them for a spin, but I’ll give you a preview here.

A key part to any tool’s success is the assurance that there’s support behind it in the way of documentation, tutorials, issue tracking, etc. This blog post links to the new chrome dev tools site that has been put together, including several video tutorials. I spent most of my time walking through the full tutorial. To see these new tools, make sure to get on the Chrome dev channel. Finally, any issues can be seen and added via the chromium issues page.

Once you’ve got the latest Chrome dev release, you can access these tools by clicking on the Page menu () and select Developer -> Developer Tools. There are six panels to choose from. The Elements panel shows the DOM tree. A nice feature here is the ability to see the event listeners, including anonymous functions, attached to any element.

Much of my time analyzing web sites is spent looking at HTTP waterfall charts. This is captured in the Resources panel. Since this slows down web sites, it’s off by default. You can make it enabled permanently or for the current session. Doing so reloads the current web page automatically so you can see the HTTP waterfall chart. The DOMContentLoaded and Onload events are shown (blue and red vertical lines respectively). This is incredibly helpful for developers who are tuning their page for faster performance, so they can confirm deferred actions are happening at the right time. The only other tool I know that does this is Firebug’s Net panel.

JavaScript debugging has gotten some major enhancements including conditional breakpoints and watch expressions.

Developers can finally get insight into where their page’s load time is being spent by looking at the Timeline panel. In order to get timeline stats, you have to start and stop profiling by clicking on the round dot in the status bar at the bottom. The overall page load sequence is broken up into time segments spent on loading, JavaScript execution, and rendering.

The most differentiating features show up in the Profiles panel. Here, you can track CPU and memory (heap) stats. A couple other tools track CPU, but this is the only tool I’m aware of that tracks heap for each type of constructor.

Most of these features are part of WebKit’s Web Inspector. The new features added by the Chrome team are the timeline and heap panels. All of these improvements have arrived in the last month, and result in a tool that any web developer will find useful, especially for building even faster web sites.

2 Comments

Velocity CFP now open!

November 20, 2009 5:41 pm | 4 Comments

Velocity 2010 is just around the corner!

Well, actually, it’s not until June 22-24, 2010. But Jesse and I have already been working with the O’Reilly conferences team for a few months. We have the venue – Hyatt Regency Santa Clara. We have the theme – Fast by Default. We have the cool blur motion speed image. The Program Committee signed on for another year: John Allspaw, Artur Bergman, Scott Ruthfield, Eric Schurman, and Mandi Walls. We’re already fielding calls from sponsors and exhibitors. The next step is speakers. That’s where you come in.

The Call for Participation for Velocity 2010 just opened today. We want to hear proposals for web performance and operations topics that you’re passionate to share. Some suggested areas include:

  • Web frameworks with built-in performance
  • Effective cloud computing
  • Profiling web applications (esp. JavaScript)
  • Network performance – HTTP, TCP, DNS
  • NoSQL
  • Mobile performance
  • Evangelizing performance within your company

This is Velocity’s third year. The first two years were incredible. I’d love to see you at this year’s conference. If you’ve been working on something that other SpeedGeeks should hear about, submit a proposal now.

4 Comments

Fewer requests through resource packages

November 18, 2009 12:31 am | 39 Comments

A few months back, I visited Alexander Limi at the Mozilla offices to discuss his proposal for resource packages. I liked the idea then and am excited that he has published the proposal in his article Making browsers faster: Resource Packages. I’ll start by reviewing the concept, provide my comments on some of the issues that have come up, and then provide some data on how this would impact the Alexa U.S. top 10 web sites in terms of HTTP requests.

Over the last few years I’ve talked with several people about the concept of bundling multiple resources into a single response, with the ultimate goal being to increase bandwidth utilization on the client. Typically, browsers only take advantage of about 30% of their bandwidth capacity when loading a web page because of the overhead of HTTP and TCP, and the various blocking behaviors in browsers. These previous resource bundling discussions got waylaid by implementation details and deployment challenges. The strength of Alexander’s proposal is its simplicity around these two tenets:

  1. the resource package is a zip file – Zip files have widespread support, are easy to create, require low CPU to zip and unzip, and are well understood by developers and users.
  2. the implementation is transparent to browsers that don’t support it – Developers can add resource packages to their existing pages with a LINK tag using the “resource-package” relationship. Browsers that don’t recognize “resource-package” LINKs (which is all browsers right now), ignore it and load the page the same way they do today. As browsers start to support “resource-package” LINKs, users start getting faster pages. Developers only have to create one version of their HTML.

These are simple principles, but they are why this proposal stands out.

How It Would Work

The first step is to identify which resources to bundle. There’s no simple recipe for doing this. It’s similar to figuring out which images to sprite, or which scripts to concatenate together. You have to look across your web pages and see if there is a core set of resources that are used over and over – rounded corners, logos, core JavaScript and CSS files, etc. You don’t want to bundle every image, script, and stylesheet across all your pages into one resource package. Similarly, you don’t want to create a separate resource package for every page – it’s wasteful to have the same resources repeated across multiple packages. Take the middle path.

The next step is to create a manifest.txt file that lists the resources, for example:

js/jquery.js
js/main.js
css/reset.css
css/grid.css
css/main.css
images/logo.gif
images/navbar.png

Then zip the manifest.txt and the files together.

Finally, add a line like this to your HTML document:

<link rel="resource-package" type="application/zip" href="pkg.zip" />

This causes the browser to download the zip file, extract the files, and cache them. As the browser continues parsing the HTML page, it encounters other resources, such as:

<script src="js/jquery.js" type="text/javascript"></script>

Browsers that don’t support resource packages would make a separate HTTP request for jquery.js. But browsers that support resource packages would already have jquery.js in cache, avoiding the need for any more HTTP requests. This is where the performance benefit is achieved.

Why? What about…?

To a large degree, bundling is possible today. Multiple scripts can be concatenated together. Similar story for stylesheets. Images can be sprited together. But even if you did all of this, you’d have three HTTP requests. Resource packages bundle all of these into one HTTP request. Also, although stylesheets are typically (hopefully) all in the document HEAD, you might have some scripts at the top of your HTML document and others at the bottom. You’d either have to bundle them all together at the top (and slow down your page for JavaScript that could have been loaded lower), or create two concatenated scripts. And even though I’ve created SpriteMe, creating sprites is still hard. Resource packages allow for files (scripts, stylesheets, images, etc.) to be developed and maintained separately, but more easily bundled for efficient download to the client.

Comments on various blogs and threads have raised concerns about resource packages hurting performance because they decrease parallel downloading. This should not be a concern. Worst case, developers could create two resource packages to get parallel downloading, but that won’t be necessary. I haven’t done the tests to prove it, but I believe downloading multiple resources across a single connection in streaming fashion will achieve greater bandwidth utilization than sharding resources across multiple domains for greater parallelization. Also, there will always be other resources that live outside the resource package. Jumping ahead a little bit, across the Alexa U.S. top 10 web sites, 37% of the resources in the page would not make sense to put into a resource package. So there will be plenty of opportunity for other downloads to happen in parallel.

Another advantage of zip files is that they can be unpacked as the bytes arrive. That’s where the manifest.txt comes in. By putting the manifest.txt first in the zip file, browsers can peel off the resources one-by-one and start acting on them immediately. But this means browsers are likely to block parsing the page until at least the manifest.txt has arrived (so that they know what to do when they encounter the next resource in the page). There are multiple reasons why this is not a concern.

  • Some of the non-packaged resources could be placed above the resource package – presumably browsers would start those downloads before blocking for the resource package’s manifest.txt.
  • The resource package’s LINK tag could (should) be included in the first part of the HTML document that is flushed early to the client, so the browser could start the request for the zip file even before the entire HTML document has arrived.
  • A final idea that isn’t in the proposal – I’d like to consider adding the manifest to the HTML document. This would add page weight, but if manifest blocking was an issue developers could use this workaround.
  • There should also be an ASYNC or DEFER attribute for resource packages that tells the browser not to wait. Again, only developers who felt this was an issue could choose this path.

My main issue with resource packages was giving up the granularity of setting caching headers for each resource individually. But as I thought about this, many web sites I look at version their resources today – giving them the same expiration dates. This was further confirmed during my examination of the top 10 sites (next section). If there are some resources that change frequently (less than weekly), they might be better in a separate resource package, or not packaged at all.

Survey of Resource Package Potential

I’m all about ideas that make a real impact. So I wanted to quantify how resource packages could be used in the real world. I examined the Alexa U.S. top 10 web sites and cataloged every resource that was downloaded. For each web site, I identified one or two domains that hosted the bulk of the resources. For the resources on those domains, I only included resources that had an expiration date at least one week in the future. Although you could package resources that weren’t cacheable, this would likely be a greater burden on the backend. It makes the most sense to package resources that are intended to be cached. The full details are available in this Google spreadsheet.

With this raw data in hand, I looked at the potential savings that could be achieved by using resource packages. On average, these websites have:

  • 42 resources (separate HTTP requests)
  • 26 of these would make sense to put into one or two resource packages

Using resource packages would drop the total number of HTTP requests on these sites from 42 to 17!

The results for each top 10 web site are shown in the following table. The last two columns show a size comparison. In the case of Amazon, for example, there were 73 HTTP requests for resources in the page. Of these, 47 were being downloaded from two main domains with a future expiration date, so could be put into a resource package. The download size of those 47 individual responses was 263K. After zipping them together, the size of the zip file was 232K.

original #
of requests
# of requests
packaged
individual file
size
zip file
size
Amazon 73 47 263K 232K
Bing 20 11 33K 30K
Blogger 43 34 105K 81K
eBay 48 38 179K 159K
Facebook 43 43 303K 260K
Google 11 8 29K 25K
MySpace 41 10 39K 35K
Wikipedia 61 21 73K 63K
Yahoo 48 45 294K 271K
YouTube 27 5 78K 71K
average 42 26 140K 123K

This is a best case analysis. It’s possible some of these resources might be page-specific or short-lived, and thus not good candidates for packaging. Also, the zip file size does not include the manifest.txt file size, although this would be small.

Resource packages promise to greatly reduce the number of HTTP requests in web pages, producing pages that load faster. Once we have browsers that support this feature, the impact on page load times can be measured. I’m excited to hear from Alexander that Firefox 3.7 will support resource packages. I hope other browsers will comment on this proposal and support this performance feature.

39 Comments

CSSEmbed – automatically data: URI-ize

November 16, 2009 10:51 am | 6 Comments

Nicholas Zakas (Yahoo, author, and JS guru) has been analyzing the performance benefits of data: URIs, mostly in the context of CSS background images. This follows on the heels of a great blog post from the 280 North folks about using data: URIs in Cappuccino. Quick background – data: URIs are a technique for embedding resources as base 64 encoded data, avoiding the need for extra HTTP requests. It’s a technique I describe in Chapter 1 of High Performance Web Sites. For more background, refer to Nicholas’ Data URIs explained blog post.

Data: URIs are a well known performance best practice, but until now have been largely a manual process or customized build script. Nicholas addresses these shortcomings with his release of two open source projects. CSSEmbed is a commandline tool that converts your stylesheet’s image references to data: URIs. DataURI is the lower-level commandline tool used by CSSEmbed to convert files to data: URI format. After downloading the JAR file, the usage is simple:

java -jar cssembed-x.y.z.jar -o styles_new.css styles.css

The commandline version is key for releasing production code. I’d also like to see an online version of these services. Another great enhancement would be to have an option to generate a stylesheet that works in Internet Explorer 6 & 7, where data: URIs aren’t supported. (See the blog post from Stoyan Stefanov and examples from Hedger Wang for more info on this MHTML alternative.)

To get wide adoption of these web performance techniques, it’s critical that they be automated as much as possible. Kudos to Nicholas for creating these tools to ease the burden for web developers. Read Nicholas’ original blog post Automatic data URI embedding in CSS files for examples and more links.

6 Comments

SpeedGeeks LA videos now available

November 15, 2009 12:23 pm | 1 Comment

Quick follow-up on my blog post about SpeedGeeks LA, the performance meetup hosted at Shopzilla on Oct 26: Videos and slides from the presentations are now available:

Definitely checkout the cool cars in Paddy’s slides.

1 Comment