P3PC: ValueClick

April 12, 2010 11:44 am | 1 Comment

P3PC is a project to review the performance of 3rd party content such as ads, widgets, and analytics. You can see all the reviews and stats on the P3PC home page. This blog post looks at ValueClick. Here are the summary stats.

impact on page Page Speed YSlow doc.
write
total reqs total xfer size JS ungzip DOM elems median Δ load time
med 89 98 y 3 2 kB 1 kB 1 na**
* Stats for ads only include the ad framework and not any ad content.
** It’s not possible to gather timing stats for snippets with live ads.
column definitions

I don’t have an account with ValueClick, so my friends over at Zimbio let me use their ad codes during my testing. Since these are live (paying) ads I have to mask the ad codes in the snippet shown here. This means it’s not possible to crowdsource time measurements for these ads.

Snippet Code

Let’s look at the actual snippet code:

1: <script language=”javascript” src=”http://media.fastclick.net/w/get.media?sid=12345&m=6&tp=8&d=j&t=s”></script>
2: <noscript><a href=”http://media.fastclick.net/w/click.here?sid=12345&m=6&c=1″ target=”_top”>
3: <img src=”http://media.fastclick.net/w/get.media?sid=12345&m=6&tp=8&d=s&c=1″ width=300 height=250 border=1></a></noscript>
snippet code as of April 7, 2010

A quick walk through the snippet code:

  • line 1 – Download the get.media script.
  • lines 2-3 – NOSCRIPT block in case JavaScript is not available.

Performance Analysis

This HTTP waterfall chart was generated by WebPagetest.org using IE 7 with a 1.5Mbps connection from Dulles, VA. It shows why this snippet has a significant impact on page load time even with just a few HTTP requests and a very small download size.

Keep in mind that valueclick-waterfall.png represents the actual content on the main page. Notice how that image is pushed back to item 6 in the waterfall chart. That’s because the get.media script (item 2) is downloaded using normal SCRIPT SRC tags. This blocks all subsequent HTTP requests in older browsers including IE 6&7. (Here we’re using IE7.)

In addition, the get.media script is served through a redirect in IE (but not in Firefox). For IE a total of three sequential HTTP requests must be completed before the ad is returned. The ad is inserted using document.write, which can further block the main content on the page. In this one page load, the main content (valueclick-waterfall.png) is blocked for 338 + 345 + 163 = 846 milliseconds.

In my analysis of ad snippets I focus only on the ad framework, not on the actual ads. The ValueClick ad framework is very light – just two redirects and one small script that does document.write. Therefore, there are only a few problem areas in which to look for performance improvements, but they’re big:

1. The redirects block the page.

In IE there are two redirects in front of the get.media script. This is two roundrips from the user’s browser to the ValueClick servers and back again. The fact that these redirects don’t occur in Firefox leads me to believe that there’s a workaround for IE. Given that over 50% of Internet traffic uses IE, removing these redirects would have a positive impact on a significant number of users.

2. The get.media script blocks the main content of the page from loading.

It would be better to load the script without blocking, similar to what BuySellAds.com does.

3. The ad is inserted using document.write.

Scripts that use document.write slow down the page because they can’t be loaded asynchronously. Inserting ads into a page without using document.write can be tricky. BuySellAds.com solves this problem by creating a DIV with the desired width and height to hold the ad, and then setting the DIV’s innerHTML.


Ad networks are an amazing piece of technology. Having so many different companies share such a variety of content across millions of web sites is a real accomplishment. Techniques like document.write and scripts that block have made this possible. But the Web has evolved since these techniques were considered acceptable.

It’s critical that ad providers adopt new web development patterns so they can hit that win-win-win of a fast user experience, publisher content that renders immediately, and ads that appear quickly to drive impressions and click throughs.

1 Comment

Google adds site speed to search ranking

April 9, 2010 7:46 am | 12 Comments

Today, Google announced that a site’s speed has been added as a signal to Google’s search ranking algorithm: Using site speed in web search ranking.

In March 2008, one month after I started working here, Google announced that site speed was being incorporated into Adwords Quality Score. When I wrote my blog post about that change to Adwords (Google fosters a faster Internet) I had no idea that this was the beginning of a long series of contributions from Google for creating a faster Web. Since that time Google has released:

Two years ago when I talked to people about the Adwords change, most people thought it was a good idea, but the most frequent response was, “Doesn’t this favor larger companies that care about performance?” In my experience, small companies that care about performance are able to make improvements much more quickly than large companies. Small companies are typically more agile and have less legacy code to worry about.

I’m excited to see web performance optimization become a competitive advantage, and look forward to helping web developers around the world make their sites even faster. Make sure to run Page Speed and YSlow to find the most important performance improvements. If you still have questions, feel free to contact me. I’ll be happy to analyze your web site and give you some tips.

As much as I’m excited about how Google’s announcement raises awareness about web performance optimization among companies and developers, I’m most excited about what this means for users. Faster web sites lead to a better user experience. And that’s what it’s all about.

12 Comments

Speed Doesn’t Matter

April 1, 2010 9:33 am | 16 Comments

[Note the date this blog post was written.]

Six years. Wasted.

That’s how I’m feeling after reading a recent performance-related article from WebSundries.com. The article reviews the results of various performance changes made to their web site, and the impact it had on their business. Although the improvements did in fact improve several metrics, at the end of the day they found it didn’t matter than much

The conclusions are a surprise, to say the least. But DeWitt Leighter, WebSundries’ VP of Engineering who authored the article, brought up several good points to support their interpretation of the data:

Focusing on improving the speed of our web site did have benefits. Conversions increased by 27%. Unique users nearly doubled (97% increase), and session length increased from 12 to 19 minutes. But the costs to achieve this were also significant, and in our interpretation outweighed the benefits.

Among the costs of improving their web site performance was the development effort. Later Leighter described how their developers were burdened by having to learn how to program, and worry about the impact of their changes. Leighter says this was an unsustainable cost with no end in sight. The result?

We’ve gone full circle. The entire front page is now a single image. We use a technique called image maps to take the user directly to the product they wish to purchase. We reduced the size of our HTML document from nearly 17 kB to just under 200 bytes, and that’s before compression.

In response to the increases in conversions and users, DeWitt cited the fact that revenue was not one of their key business metrics, and user satisfaction was hard to measure and thus easy to ignore. When asked about the impact of downloading their 26 MB image map on mobile devices, Leighter recalled recent studies that show bandwidth is increasing and mobile usage is on the decline. As evidence he cited the fact that their web logs show almost no mobile users.

Chilling results to say the least. I’ll be watching closely to see how this alternative approach to web site performance plays out for WebSundries.com.

About WebSundries.com

WebSundries.com has been the destination for shoppers for nearly two centuries. Starting in 1826 as Leighter’s Dry Goods and Mercantile, they’re perhaps best known for their heavy investment in vacuum tubes and rotary phones, for which they still hold the world’s largest inventories. Rebranded as WebSundries.com in 1998, the company boasts having one of the most consistent customer bases on the Internet, with almost no change since they first launched their site.

16 Comments

P3PC: Google AdSense

March 29, 2010 1:44 pm | 6 Comments

P3PC is a project to review the performance of 3rd party content such as ads, widgets, and analytics. You can see all the reviews and stats on the P3PC home page. This blog post looks at Google AdSense. Here are the summary stats:

impact on page Page Speed YSlow doc.
write
total reqs total xfer size JS ungzip DOM elems median Δ load time
big 87 84 y 8 41 kB 76 kB 9 222 ms
column definitions
Click here to see how your browser performs compared to the median load time shown above.

After signing up for Google AdSense, you can setup different types of ads. I chose “AdSense for Content” (listed first). Here’s what an example ad looks like. (This is a static image. Go to the Compare page to see the snippet live.)

Snippet Code

Let’s look at the actual snippet code:

1: <script type=”text/javascript”><!–
2: google_ad_client = “pub-0478442537074871”;
3: /* 300×250, created 3/6/10 */
4: google_ad_slot = “4427977761”;
5: google_ad_width = 300;
6: google_ad_height = 250;
7: //–>
8: </script>
9: <script type=”text/javascript”
10: src=”http://pagead2.googlesyndication.com/pagead/show_ads.js”>
11: </script>
snippet code as of March 10, 2010

A quick walk through the snippet code:

  • lines 2-6 – Define global variables that are used by the show_ads.js script.
  • lines 9-11 – Load the show_ads.js script.

Performance Analysis

This HTTP waterfall chart was generated by WebPagetest.org using IE 7 with a 1.5Mbps connection from Dulles, VA. It reveals a lot of idiosyncrasies with scripts, browsers, and HTTP. Let’s step through each request.

  • item 1: compare.php – The HTML document.
  • item 2: show_ads.js – The main script. All other downloads are blocked because this is loaded using the SCRIPT SRC HTML tag.
  • items 3-5 – Other scripts that are loaded dynamically by show_ads.js. This dynamic loading is done by using document.write. Using document.write causes the scripts themselves to be downloaded in parallel in IE (as evidenced by the waterfall chart). However, subsequent resources are still blocked (item 7).
  • item 6: ads – The actual ad content from doubleclick.net. Google AdSense creates an iframe to hold the ad, so this is the HTML document contained in that iframe.
  • item 7: *-waterfall.png – The waterfall image in this page. This is the main content of the page. Notice how it’s blocked by the previous four scripts.
  • item 8-9: abg-en-100c-0000000.png – The “Ads by Google” image. This is loaded twice in IE because it’s referenced twice in the ad: as an IMG and as part of AlphaImageLoader.
  • item 10: sma8.js – A script loaded by the ad. Because the ad is in an iframe, this script won’t block any resources in the main page.

Now that we have a handle on the HTTP requests involved, let’s look at the most important performance issues along with recommended solutions.

1. The scripts block the main content of the page from loading.

It would be better to load the scripts without blocking. This isn’t possible with the current implementation because the ad is inserted using document.write. Calling document.write from scripts loaded asynchronously may lead to ads being inserted in the wrong location or potentially the entire page being blank. The ideal solution would be create a DIV with the desired width and height to hold the ad and load the scripts asynchronously, similar to what BuySellAds.com does.

2. Most of the resources are only cacheable for a day.

It’s understandable that show_ads.js is only cacheable for a day. If this script changed (bug fix, new feature), there would be no way to rev the filename (since the snippet is embedded in the publishers’ pages). A short expiration date ensures users will get the updated version sooner (within a day). However, expansion_embed.js, abg-en-100c-000000.png, and sma8.js are also only cacheable for a day. These should have a far future expiration date (a year or more). If there was a change to expansion_embed.js (for example), the new version could be pushed with a modified filename (expansion_embed.1.1.js) and the code in show_ads.js could be modified to reference this new filename.

3. abg-en-100c-000000.png is downloaded twice.

This is happening because an AlphaImageLoader filter is used to achieve alpha transparency in IE 6. The HTML looks like this:

1: <span style=”display:inline-block;height:16px;width:78;
2:     pxfilter:progid:DXImageTransform.Microsoft.AlphaImageLoader(
3:     src=’http://…/abg-en-100c-000000.png’);”>
4: <img src=http://…/abg-en-100c-000000.png
5:     alt=”Ads by Google” border=0 height=16 width=78
6:     style=filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0)>
7: </span>

Notice that abg-en-100c-000000.png is used in the src in both lines 3 and 4. I’m not sure why the IMG is being used with an opacity of 0 (preserve space?), but I bet there’s a workaround. Also, this should only be necessary in IE 6, so the AlphaImageLoader should be skipped for IE 7&8.

4. Five scripts are downloaded.

Some of the scripts could be combined to reduce the number of HTTP requests.


6 Comments

P3PC: Quantcast

March 23, 2010 5:57 pm | Comments Off on P3PC: Quantcast

P3PC is a project to review the performance of 3rd party content such as ads, widgets, and analytics. You can see all the reviews and stats on the P3PC home page. This blog post looks at Quantcast. Here are the summary stats:

impact on page Page Speed YSlow doc.
write
total reqs total xfer size JS ungzip DOM elems median Δ load time
small 93 98 n 2 3 kB 3 kB 2 53 ms
column definitions
Click here to see how your browser performs compared to the median load time shown above.

Quantcast does web analytics. They go beyond the typical traffic stats providing information about user demographics for advertisers. It was easy to signup for Quantcast and embed their snippet. Go to the Compare page to see the snippet in action.

Snippet Code

Let’s look at the actual snippet code:

1: <!– Start Quantcast tag –>
2: <script type=”text/javascript”>
3: _qoptions={
4: qacct:”p-d0TvozDaU_91o”
5: };
6: </script>
7: <script type=”text/javascript” src=”http://edge.quantserve.com/quant.js”></script>
8: <noscript>
9: <img src=”http://pixel.quantserve.com/pixel/p-d0TvozDaU_91o.gif” style=”display: none;” border=”0″ height=”1″ width=”1″ alt=”Quantcast”/>
10: </noscript>
11: <!– End Quantcast tag –>
snippet code as of March 22, 2010

A quick walk through the snippet code:

  • lines 3-4 – Define some variables used by the script.
  • line 7 – Load the quant.js script.
  • lines 8-10 – Provide a NOSCRIPT block that loads an image beacon using HTML.

Performance Analysis

This HTTP waterfall chart was generated by WebPagetest.org using IE 7 with a 1.5Mbps connection from Dulles, VA. Let’s step through each request.

  • item 1: compare.php – The HTML document.
  • item 2: quant.js – The main Quantcast script. This is loaded using normal SCRIPT SRC HTML tags, so it blocks subsequent resources in IE7 and older browsers, but not in newer browsers.
  • item 3: pixel.quantserve.com/pixel.gif – A beacon back to Quantcast.
  • item 4: *-waterfall.png – The waterfall image in this page. This is the main content of the page. Notice how it’s blocked by quant.js in IE7.

The Quantcast snippet is fairly performant. The few things worth noting are:

1. The quant.js script blocks resources and rendering.

The quant.js script is loaded using normal SCRIPT SRC HTML tags. Newer browsers (IE 8, Firefox 3.6, Safari 4, Chrome 2+) download this in parallel with subsequent resources. But in IE 6&7 and Opera all subsequent resources are blocked until quant.js is done downloading, as shown in the waterfall chart. In all browsers, all DOM elements below the SCRIPT tag are blocked from rendering and all JavaScript is blocked from executing. Since nothing else in the page depends on quant.js, it would be better to load it asynchronously, as is done with Google Analytics’ async snippet.

2. quant.js is only cacheable for one day.

This is the script that publishers add to their pages. As such, it has to have a short expiration time so that the end users will update their cache somewhat frequently to get bug fixes and other updates. However, one day might be too aggressive. As a point of comparison, Google Analytics’ ga.js is cacheable for one week.

3. The beacon returns a 200 HTTP status code.

I recommend returning a 204 (No Content) status code for beacons. A 204 response has no body and browsers will never cache them, which is exactly what we want from a beacon. In this case, the image body is less than 100 bytes, and the beacon’s HTTP headers prevent it from being cached. Although the savings are minimal, using a 204 response for beacons is a good best practice. Quantcast’s NOSCRIPT beacon, on the other hand, should return a 200 status code to avoid the browser thinking there’s an error.

Overall, Quantcast has a small impact on page performance. The most important improvement would be to load quant.js asynchronously.

Other posts in the P3PC series:


Comments Off on P3PC: Quantcast

P3PC: BuySellAds.com

March 16, 2010 7:09 am | 4 Comments

P3PC is a project to review the performance of 3rd party content such as ads, widgets, and analytics. You can see all the reviews and stats on the P3PC home page. This blog post looks at BuySellAds.com. Here are the summary stats:

impact on page Page Speed YSlow doc.
write
total reqs total xfer size JS ungzip DOM elems median Δ load time
small 81 92 n 3 7 kB 14 kB 9 28 ms
column definitions
Click here to see how your browser performs compared to the median load time shown above.

After signing up for BuySellAds.com, you can setup different types of ads. I chose an image-only 125×125 ad. Since this is a test page, I can’t get real ads. Check out Webdesigner Depot or All Things Cupcake to see some real ads. The folks at BuySellAds.com set me up with a test ad for demo purposes. Here’s what the test ad looks like. (This is a static image. Go to the Compare page to see the snippet live.)

Snippet Code

Let’s look at the actual snippet code:

1: <!– BuySellAds.com Ad Code –>
2: <script type=”text/javascript”>
3:     (function(){
4:         var bsa = document.createElement(‘script’);
5:         bsa.type = ‘text/javascript’;
6:         bsa.async = true;
7:         bsa.src = ‘//s3.buysellads.com/ac/bsa.js’;
8:         (document.getElementsByTagName(‘head’)[0] || document.getElementsByTagName(‘body’)[0]).appendChild(bsa);
9:     })();
10: </script>
11: <!– END BuySellAds.com Ad Code –>
12: <!– BuySellAds.com Zone Code –>
13: <div id=”bsap_1245700″ class=”bsarocks bsap_84a5f8f4c8e4c1bb2c57948fba2d9cc4″></div>
14: <!– END BuySellAds.com Zone Code –>
snippet code as of March 14, 2010

A quick walk through the snippet code:

  • lines 3-9 – Dynamically load the bsa.js script.
  • line 13 – Create a DIV to hold the ad.

Performance Analysis

This HTTP waterfall chart was generated by WebPagetest.org using IE 7 with a 1.5Mbps connection from Dulles, VA. Let’s step through each request.

  • item 1: compare.php – The HTML document.
  • item 2: bsa.js – The main script. This is loaded dynamically, so it doesn’t block other downloads.
  • item 3: *-waterfall.png – The waterfall image in this page. This is the main content of the page. Notice how it loads in parallel with bsa.js.
  • item 4: s_84a5f8f4c8e4c1bb2c57948fba2d9cc4.js – A JSON response containing the ad content. This resource was added dynamically by bsa.js.
  • item 6: 18446-1268342919.png – The image contained in the test ad.
  • item 7: imp.gif – A beacon.

The amazing thing about the BuySellAds.com snippet is that it loads ads asynchronously. Most web developers are familiar with the performance delays inflicted by ads with scripts that block the main content in the page, or even worse scripts that use document.write so any hope of parallelization is dashed. BuySellAds.com is the only ad snippet that I’ve seen that avoids these blocking issues. (If you know of others, please add a comment mentioning them.)

Asynchronous loading is achieved as a result of two things:

  1. dynamically loading bsa.js (as opposed to using normal SCRIPT SRC HTML tags)
  2. creating a DIV placeholder for the ad content (as opposed to using document.write)

How is the ad actually loaded into the DIV? The bsa.js script dynamically adds a script (s_84a5f8f4c8e4c1bb2c57948fba2d9cc4.js) containing the ad as a JSON response. That JSON response calls a function from bsa.js (interpret_json) that extracts the DIV’s id from the JSON object and sets its innerHTML. I like how the DIV’s id and classname are used, as opposed to doing this through JavaScript variables set in the snippet.

Loading ads asynchronously is a big advantage of BuySellAds.com. But there are still a few more performance improvements that could be made.

1. The size of the DIV changes causing the page to re-layout.

I used WebPagetest.org to create a filmstrip of images showing the page loading. Notice how the waterfall chart appears at 1.5 seconds. At 2.0 seconds the ad is loaded causing the waterfall chart to shift downward. It would better if the snippet set the DIV’s width and height to the appropriate values for the selected ad size.

2. bsa.js isn’t cached.

This is the script that publishers add to their pages. As such, it has to have a short expiration time so that the file cached by users is updated frequently. However, no expiration date causes browsers to check for updates too frequently. A 1 day or 1 week expiration date would strike a better balance between performance and update frequency.

3. The beacon returns a 200 HTTP status code.

I recommend returning a 204 (No Content) status code. A 204 response has no body and browsers will never cache them, which is exactly what we want from a beacon. In this case, the image body is less than 100 bytes, and the beacon’s HTTP headers prevent it from being cached. Although the savings are minimal, using a 204 response for beacons is a good best practice.

Hats off to the folks at BuySellAds.com for showing that asynchronous ads are possible. I’ll examine a few more ad snippets in the coming weeks. We’ll see how they stack up when it comes to performance.

Other posts in the P3PC series:


4 Comments

Velocity OLC, upcoming events

March 8, 2010 8:46 pm | 5 Comments

Velocity is the O’Reilly conference Jesse Robbins and I co-chair. This is our third year and it’ll be bigger and better than ever. Dates are June 22-24. We’re almost done reviewing proposals and the speaker line-up so far looks great: mobile, browsers, tools, JavaScript, metrics, and more all covered from a performance perspective. I hope you’ll be able to make it.

As a warm up to Velocity in June, O’Reilly had the great idea of starting Velocity OLC (OnLine Conference). We had the first one on December 8 with great speakers including Mike Belshe (Chrome, SPDY), Charles Jolley (SproutCore), and J Chris Anderson (CouchDB). The next Velocity OLC is coming up fast – March 17 9-11:15am (PST). The agenda is:

  • Site Performance in Google Webmaster Tools – Sreeram Ramachandran (Google)
  • MySQL Abuse – Kellan Elliott-McCrea (Flickr)
  • Keeping Track of Your Performance Using Show Slow – Sergey Chernyshev (truTV)
  • Provisioning Toolchain – Lee Thompson (DTO Solutions)
  • Diagnose and Prevent JavaScript/AJAX Performance Issues in Internet Explorer – Andreas Grabner (dynaTrace Software)

The event is free! I invited the performance speakers, Sreeram, Sergey, and Andi, because they’ve released these amazing, free tools that all web developers focused on performance should know about. I hope you’ll tune in.

I also want to mention my next few speaking appearances.

JSConf.US (April 17&18, DC) – I missed the first two years of this conference and was bummed. I heard so many good things about it, I jumped at the chance to speak at JSConf.EU last November in Berlin and it exceeded my high expectations. Now I get to experience the main event. And I’ll be back in my old (20 years ago) stomping grounds!

Web 2.0 Expo San Francisco (May 3-6) – This event is sentimental for me. 4 years ago Tenni Theurer and I showed up to do a workshop on Sunday. It was beautiful outside and we figured everyone would be out sightseeing. Instead, 300+ people showed up. That was the first conference I had spoken at in a decade, and was the beginning of the evangelism campaign that I carry on today. I’ve spoken here every year and it’s always a great, smart crowd. Super hallway discussions.

@media (London, June 8-11) – Dion and Ben turned me on to Web Directions, speaking highly of all the conferences they run. I reached out to John Allsopp and he was kind enough to put me on the speaker list. I’m pysched to see some of the speakers I know well, plus some I’ve never met. And it’s a great opportunity for me to touch base with EU web devs focused on performance. Use the “SOUDERS” discount code.

Definitely grab me if you’re at any of these events. I want to know about your biggest performance bottleneck, and tips & tricks you’d like to share. And I’m always happy to sit down with a packet sniffer and do some performance analysis on the fly.

5 Comments

WebPagetest.org – top tool

March 5, 2010 8:04 am | 12 Comments

I’m loving WebPagetest.org. In Even Faster Web Sites I said, “[WebPagetest] hasn’t gotten the wide adoption it deserves.” It got a boost after Matt Cutts mentioned WebPageTest.org in his interview with WebProNews. But I still meet people who aren’t aware that this great performance tool is out there, so let me bang their drum some more.

Pat Meenan and Eric Goldsmith are the team behind AOL Pagetest and WebPagetest.org. AOL Pagetest is the Windows tool that works in IE. Pat took that and put it behind a web server running in his basement and called it WebPagetest. That was two years ago. He took the Open Source route and now there are instances of WebPagetest running in Virginia, California, UK, China, and New Zealand hosted by AOL as well as Strangeloop Networks, Aptimize, and Daemon Solutions.

The power of WebPagetest.org is that it’s web-based – you don’t have to do any installs and you can run it on any OS and browser. On the backend, WebPagetest runs the page in either IE7 or IE8 and displays the results. This might be a limitation for some folks – if you want to test a page on Mac OS X using Safari you’ll have to do that with some other tool. But the fact that IE 7&8 are the dominate browsers means you can see the most typical experience regardless of what platform you’re currently working on. Since many developers work on Mac using Safari or Firefox, and more are moving to Chrome, it’s important that they can easily see how their web pages load for a majority of their users.

New Test

Here’s how it works: Go to the New Test tab. Enter the URL you want to test and click submit. Pretty easy! 90% of the time that’s what I do, but there are other options you can tweak:

  • pick a geo location – VA, CA, UK, CN, or NZ
  • choose IE7 or IE8
  • choose a connection speed – Dial, DSL, FIOS (Dial and DSL are done via throttling)
  • test just the first (empty cache) page load or first and repeat
  • repeat the test up to 10 times to get a bigger sample size
  • opt to keep your test results private if desired

Results

The results page shows summary stats (page load times, bytes downloaded, # of HTTP requests) and a mini performance analysis (compression, image optimization, concatenating scripts and stylesheets). But the piece I love is the waterfall chart.

If you click on the mini waterfall, it takes you to a larger view where you can do additional customizations. I’ve been relying on this for my current series of blog posts on P3PC (performance of 3rd party content). And Pat even added a few options I requested. You can set the size of the image, remove certain requests (for example, I sometimes remove favicon.ico), and whether to show the extra bits on CPU and bandwidth utilization. I end up with clean waterfall charts like this:

And there’s more – Video!

When you create a new test, you can opt to record a video of the page loading (go to the Video tab under “Step 4 – Test Options” in the figure above). WebPagetest generates a filmstrip of images as well as a video. The image filmstrip shows what the page looks like as it loads. You can choose different time increments (0.1, 0.5, 1 and 5 seconds). Wikipedia is pretty straightforward as it loads. Here’s the filmstrip for FOX Sports. Content arrives in the 0-5 second range, more images (like the logo) are filled in from 5-10 seconds, and flash arrives by the 15 second mark. You can also view the video.

Pat does a lot of this work on his own time and all the video features are in Alpha, so be tolerant. I use WebPagetest.org daily and it has become one of my favorite performance tools. Definitely give it a try.

12 Comments

P3PC: Google Analytics

March 3, 2010 7:25 pm | 16 Comments

P3PC is a project to review the performance of 3rd party content such as ads, widgets, and analytics. You can see all the reviews and stats on the P3PC home page. This blog post looks at Google Analytics. Here are the summary stats:

impact on page Page Speed YSlow doc.
write
total reqs total xfer size JS ungzip DOM elems median Δ load time
small 91 99 n 2 18 kB 24 kB 2 19 ms
column definitions
Click here to see how your browser performs compared to the median load time shown above.

Google Analytics recently had a nice performance upgrade. The old snippet used document.write and thus blocked other resources and rendering, making pages feel slower. On Dec 1, 2009, Google announced the launch of their new asynchronous snippet. The old snippet still works, but sites that want a significant speedup should use the new async snippet.

My analysis focuses on the new async snippet for Google Analytics.

Snippet Code

Let’s look at the actual snippet code:

1: <script type=”text/javascript”>
2: var _gaq = _gaq || [];
3: _gaq.push([‘_setAccount’, ‘UA-15026169-1’]);
4: _gaq.push([‘_trackPageview’]);
5:
6: (function() {
7: var ga = document.createElement(‘script’); ga.type = ‘text/javascript’; ga.async = true;
8: ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘http://www’) + ‘.google-analytics.com/ga.js’;
9: (document.getElementsByTagName(‘head’)[0] || document.getElementsByTagName(‘body’)[0]).appendChild(ga);
10: })();
11: </script>
snippet code as of March 3, 2010

A quick walk through the snippet code:

  • lines 2-4 – Push commands onto a queue to be executed once the async script finishes loading.
  • lines 6-10 – Create a script DOM element and set the src to fetch ga.js.

Performance Analysis

This HTTP waterfall chart was generated by WebPagetest.org using IE 7 with a 1.5Mbps connection from Dulles, VA. Notice how the image in the main page (google-analytics-waterfall.png) is not blocked by ga.js – they both download in parallel.

Here are the most important performance issues along with recommended solutions.

1. 24 kB seems like a lot of JavaScript for sending a tracking beacon.

My example is very straightforward and doesn’t use much Google Analytics functionality. The three sites I run that use Google Analytics are all simple. I’d like to see a “lite” version of ga.js for sites like mine and whittle that 24 kB down to 5 kB or so.

2. The beacon returns a 200 HTTP status code.

I recommend returning a 204 (No Content) status code. A 204 response has no body and browsers will never cache them, which is exactly what we want from a beacon. In this case, no body only saves 35 bytes, and the beacon’s HTTP headers prevent it from being cached. Although the savings are minimal, using a 204 response for beacons is a good best practice.

What you can do now: The new async version of the Google Analytics snippet is pretty slim. Even YSlow and Page Speed can’t find much wrong with it. My main advice would be to switch over to this async version if you’re still using the old document.write snippet. Cruising through the Alexa U.S. top 50 web sites I found two web sites that use the new async snippet: Huffington Post and Answers.com. But these web sites haven’t moved over yet: Twitter, FOXNews.com, Reference.com, Photobucket, Hulu, DoubleClick.com, and (ahem) Blogger. To be fair, the new snippet was launched as Beta just a few months ago, but all of these sites should switchover to the async snippet and speed things up for their users.


16 Comments

P3PC: Facebook Share

March 1, 2010 8:35 pm | 1 Comment

P3PC is a project to review the performance of 3rd party content such as ads, widgets, and analytics. You can see all the reviews and stats on the P3PC home page. This blog post looks at Facebook Share. Here are the summary stats:

impact on page Page Speed YSlow doc.
write
total reqs total xfer size JS ungzip DOM elems median Δ load time
small 90 92 n 5 8 kB 7 kB 15 104 ms
column definitions
Click here to see how your browser performs compared to the median load time shown above.

Facebook Share is a way to share a URL with the Facebook community. Here’s what it looks like. (This is a static image. Go to the Compare page to see the live widget.)

Snippet Code

Let’s look at the actual snippet code:

1: <a name=”fb_share” type=”button_count” share_url=”https://stevesouders.com/” href=”http://www.facebook.com/sharer.php”>Share</a>
2: <script src=”http://static.ak.fbcdn.net/connect.php/js/FB.Share” type=”text/javascript”></script>
snippet code as of March 1, 2010

A quick walk through the snippet code:

  • line 1 – The anchor that will be filled in later.
  • line 2 – The FB.Share script is downloaded. The actual code is minified, but I’ve expanded some of it here for easier readability. The _onFirst function is called (line 1 below). _onFirst inserts the share-button-css stylesheet (lines 2-6) and then calls renderPass. renderPass calls fetchData which inserts the restserver.php script (lines 12-14). The insert function appends the DOM element (stylesheet or script) to the head or body of the document (line 19).
    1: _onFirst: function() {
    2: var a=document.createElement(‘link’);
    3: a.rel=’stylesheet’;
    4: a.type=’text/css’;
    5: a.href=’http://static.ak.fbcdn.net/connect.php/css/share-button-css’;
    6: this.insert(a);
    7: renderPass();
    8: […]
    9: },
    10:
    11: fetchData: function() {
    12: var a=document.createElement(‘script’);
    13: a.src=this.addQS(‘http://api.ak.facebook.com/restserver.php’, {v:’1.0′,method:[…]});
    14: this.insert(a);
    15: […]
    16: },
    17:
    18: insert: function(a) {
    19: (document.getElementsByTagName(‘HEAD’)[0]||document.body).appendChild(a);
    20: },

Performance Analysis

This HTTP waterfall chart was generated by WebPagetest.org using IE 7 with a 1.5Mbps connection from Dulles, VA. Item 5 (facebook-sharer-waterfall.png) is the first resource that’s part of the main page. Notice how it’s blocked by the first Facebook Share script, but then loads in parallel with the widget’s stylesheet and second script.

Here are the most important performance issues along with recommended solutions.

1. The FB.Share script blocks resources and rendering.

It’s great that the stylesheet (share-button-css) and second script (restserver.php) are loading dynamically and don’t block the main page’s resources (facebook-sharer-waterfall.png). But the first script (FB.Share) is loaded with the typical SCRIPT SRC tags and so does block in older browsers, and even in newer browsers will have some blocking effects. Because there are no code dependencies and no use of document.write (yay!), the FB.Share script can also be loaded asynchronously. Here’s what the async snippet might look like. (Warning: I haven’t tested this on all browsers.)

1: <a name=”fb_share” type=”button_count” share_url=”https://stevesouders.com/” href=”http://www.facebook.com/sharer.php”>Share</a>
2: <script type=”text/javascript”>
3: (function() {
4: var domscript = document.createElement(“script”);
5: domscript.type = “text/javascript”;
6: domscript.src = “http://static.ak.fbcdn.net/connect.php/js/FB.Share”;
7: (document.getElementsByTagName(“head”)[0] || document.getElementsByTagName(“body”)[0]).appendChild(domscript);
8: }());
9: </script>

This async snippet is used in the Facebook Sharer Improved example. The HTTP waterfall chart for this async snippet is shown below. The most important thing about loading the FB.Share script asynchronously is that the main page’s content can load more quickly. Notice how the image in the main page (facebook-sharer-waterfall.png) moves from item 5 to item 3, and its load time moves from ~1100 ms to ~780 ms. Another benefit is that the overall page load time is faster, dropping from ~1100 ms to ~900 ms.

2. share-button-css is only cached for a few minutes

share-button-css should be given a far future expiration date. If it’s changed, the filename could be modified in FB.Share guaranteeing that everyone got the updated file.

3. The CSS could be reduced.

Page Speed reports that 50% (2.9 kB) of the CSS isn’t used. It’s possible the CSS is used in other manifestations of the widget but not in this default view.

What you can do now: Facebook Share is a lightweight widget as widgets go. In addition to a small transfer size and small amount of JavaScript, its images and CSS selectors are also optimized. But if you wanted to reduce the impact even farther, you could try loading FB.Share asynchronously.


1 Comment