<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">
   <channel>
      <title>YahooPerformancBlogS</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=PKsaYeBk3RG_sHO91JzWFw</link>
      <pubDate>Tue, 24 Nov 2009 08:00:07 -0800</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>An Engineer's Guide to Bandwidth</title>
         <link>http://developer.yahoo.net/blog/archives/2009/10/a_engineers_gui.html</link>
         <description>&lt;style type=&quot;text/css&quot;&gt;
.figure {text-align:center;width:100%;}
.figure img {margin:10px;}
.note {font-size:93%;}
&lt;/style&gt;&lt;p&gt;&lt;img src=&quot;http://farm2.static.flickr.com/1053/525734621_06674aaf7e_m.jpg&quot; alt=&quot;&quot; style=&quot;float:right;margin:10px;&quot; height=&quot;240&quot; width=&quot;161&quot;&gt;Web app developers spend most of our time not thinking about how data is actually transmitted through the bowels of the network stack. Abstractions at the application layer let us pretend that networks read and write whole messages as smooth streams of bytes. Generally this is a good thing. But knowing what's going underneath is crucial to performance tuning and application design. The character of our users' internet connections is changing and some of the rules of thumb we rely on may need to be revised.&lt;/p&gt; &lt;p&gt;In reality, the Internet is more like a giant cascading multiplayer game of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Pachinko&quot;&gt;pachinko&lt;/a&gt;. You pour some balls in, they bounce around, lights flash and &amp;mdash;usually&amp;mdash; they come out in the right order on the other side of the world.&lt;/p&gt; &lt;h3&gt;What we talk about, when we talk about bandwidth&lt;/h3&gt; &lt;p&gt;It's common to talk about network connections solely in terms of &quot;bandwidth&quot;. Users are segmented into the high-bandwidth who get the best experience, and low-bandwidth users in the backwoods. We hope some day everyone will be high-bandwidth and we won't have to worry about it anymore.&lt;/p&gt; &lt;p&gt;That mental shorthand served when users had reasonably consistent wired connections and their computers ran one application at a time. But it's like talking only about the top speed of a car or the MHz of a computer. Latency and asymmetry matter at least as much as the notional bits-per-second and I argue that they are becoming even more important. The quality of the &quot;last mile&quot; of network between users and the backbone is in some ways getting worse as people ditch their copper wires for shared wifi and mobile towers, and clog their uplinks with video chat.&lt;/p&gt; &lt;p&gt;It's a rough world out there, and we need to to a better job of thinking about and testing under realistic network conditions. A better mental model of bandwidth should include:&lt;/p&gt; &lt;ul&gt; &lt;li class=&quot;bullist&quot;&gt;packets-per-second&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;packet latency&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;upstream vs downstream&lt;/li&gt;
&lt;/ul&gt; &lt;h3&gt;Packets, not bytes&lt;/h3&gt;
&lt;p&gt;The quantum of internet transmission is not the bit or the byte, it's the &lt;em&gt;packet&lt;/em&gt;. Everything that happens on the 'net happens as discrete pachinko balls of regular sizes. A message of N bytes is chopped into &lt;code&gt;ceil(N / 1460)&lt;/code&gt; packets [&lt;a rel=&quot;nofollow&quot; href=&quot;#note1&quot; title=&quot;Note 1&quot;&gt;1&lt;/a&gt;] which are then sent willy-nilly. That means there is little to no difference between sending 1 byte or 1,000. It also means that sending 1,461 bytes is &lt;em&gt;twice&lt;/em&gt; the work of sending 1,460: two packets have to be sent, received, reassembled, and acknowledged.&lt;/p&gt; &lt;pre&gt; Packet #1 Payload ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ..................................................................... ........................................................... Packet #2 Payload .
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Listing 0: Byte 1,461 aka The Byte of Doom&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Crossing the packet line in HTTP is very easy to do without knowing it. Suppose your application uses a third-party web analytics library which, like most analytics libraries, stores a big hunk of data about the user inside long-lived cookie tied to your domain. Suppose you also stuff a little bit of data into the cookie too. This cookie data is thereafter echoed back to your web server upon each request. The boilerplate HTTP headers (Accept, User-agent, etc) sent by every modern browser take up a few hundred more bytes. Add in the actual URL, Referer header, query parameters... and you're dead. There is also the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://josephscott.org/archives/2009/08/xmlhttprequest-xhr-uses-multiple-packets-for-http-post/&quot;&gt;little-known fact&lt;/a&gt; that browsers &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://yuiblog.com/blog/2007/03/01/performance-research-part-3/#comment-59531&quot;&gt;split certain POST requests&lt;/a&gt; into at least two packets regardless of the size of the message.&lt;/p&gt; &lt;p&gt;One packet, more or less, who cares? For one, none of your fancy caching and CDNs can help the client send data upstream. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Slow-start&quot;&gt;TCP slow-start&lt;/a&gt; means that the client will wait for acknowledgement of the first packet before sending the second. And as we'll see below, that extra packet can make a large difference in the responsiveness of your app when it's compounded by latency and narrow upstream connections.&lt;/p&gt; &lt;h3&gt;Packet Latency&lt;/h3&gt; &lt;p&gt;Packet latency is the time it takes a packet to wind through the wires and hops between points A and B. It is roughly a function of the physical distance (at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Optical_fiber#Index_of_refraction&quot;&gt;2/3 of the speed of light&lt;/a&gt;) plus the time the packet spends queued up inside various network devices along the way. A typical packet sent on the 'net backbone between San Francisco and New York will take about 60 milliseconds. But the latency of a user's last-mile internet connection can vary enormously [&lt;a rel=&quot;nofollow&quot; href=&quot;#note2&quot;&gt;2&lt;/a&gt;]. Maybe it's a hot day and their router is running slowly. The EDGE mobile network has a best-case latency of 150msec and a real-world average of 500msec. There is a semi-famous &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://rescomp.stanford.edu/%7Echeshire/rants/Latency.html&quot;&gt;rant from 1996&lt;/a&gt; complaining about &lt;em&gt;100&lt;/em&gt;msec latency from substandard telephone modems. If only.
&lt;/p&gt; &lt;h3&gt;Packet loss&lt;/h3&gt; &lt;p&gt;Packet loss manifests as packet latency. The odds are decent that a couple packets that made up the copy of this article you are reading got lost along the way. Maybe they had a collision, maybe they stopped to have a beer and forgot. The sending end then has to notice that a packet has not been acknowledged and re-transmit.&lt;/p&gt; &lt;p&gt;Wireless home networks are becoming the norm and they are unfortunately very susceptible to interference from devices sitting on the 2.4GHz band, like microwaves and baby monitors. They are also notorious for cross-vendor incompatibilities. Another dirty secret is that consumer-grade wifi devices you'll find in cafés and small offices don't do &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Traffic_shaping&quot;&gt;traffic shaping&lt;/a&gt;. All it takes is one user watching a video to flood the uplink.&lt;/p&gt; &lt;h3&gt;Upstream &amp;lt; Downstream&lt;/h3&gt; &lt;p&gt;Internet providers lie. That &quot;6 Megabit&quot; cable internet connection is actually 6mbps down and 1mbps up. The bandwidth reserved for upstream transmission is often 20% or less of the total available. This was an almost defensible thing to do until users started file sharing, VOIPing, video chatting, etc en masse. Even though users still pull more information down than they send up, the asymmetry of their connections means that the upstream is a chokepoint that will probably get worse for a long time.&lt;/p&gt; &lt;h3&gt;A Dismal Testing Harness&lt;/h3&gt; &lt;p class=&quot;figure&quot;&gt;
&lt;img src=&quot;http://farm3.static.flickr.com/2551/3951382520_b75c61362f.jpg&quot; alt=&quot;A laptop sitting on top of a microwave with a cup of tea inside. The microwave is labeled 'packet loss generator'. The laptop is labeled 'packet loss measurement device'.&quot; height=&quot;500&quot; width=&quot;350&quot;&gt;&lt;br&gt;
&lt;em&gt;Figure 0: It's popcorn for dinner tonight, my love. I'm doing science!&lt;/em&gt;&lt;/p&gt; &lt;p&gt;We need a way to simulate high latency, variable latency, limited packet rate, and packet loss. In the olden days a good way to test the performance of a system through a bad connection was to configure the switch port to run at half-duplex. Sometimes we even did such testing on purpose. :) &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.torproject.org/&quot;&gt;Tor&lt;/a&gt; is pretty good for simulating a crappy connection but it only works for publicly-accessible sites. Microwave ovens consistently cause packet loss (my parents' old monster kills wifi at 20 paces) but it's a waste of electricity.&lt;/p&gt; &lt;p&gt;The &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man8/ipfw.8.html&quot;&gt;ipfw&lt;/a&gt; on Mac and FreeBSD comes in handy for local testing. The command below will approximate an iPhone on the EDGE network with a 350kbit/sec throttle, 5% packet loss rate and 500msecs latency. Use &lt;code&gt;sudo ipfw flush&lt;/code&gt; to deactivate the rules when you are done.&lt;/p&gt; &lt;pre&gt; $ sudo ipfw pipe 1 config bw 350kbit/s plr 0.05 delay 500ms $ sudo ipfw add pipe 1 dst-port http
&lt;/pre&gt; &lt;p&gt;Here's another that will randomly drop half of all DNS requests. Have fun with that one.&lt;/p&gt; &lt;pre&gt; $ sudo ipfw pipe 2 config plr 0.5 $ sudo ipfw add pipe 2 dst-port 53
&lt;/pre&gt; &lt;p&gt;To measure the effects of latency and packet loss I chose a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://yui.yahooapis.com/2.8.0r4/build/datatable/datatable-min.js&quot;&gt;highly-cached 130KB file&lt;/a&gt; from Yahoo's servers. I ran a script to download it as many times as possible in 5 minutes under various ipfw rules [&lt;a rel=&quot;nofollow&quot; href=&quot;#note3&quot;&gt;3&lt;/a&gt;]. The &quot;baseline&quot; runs were the control with no ipfw restrictions or interference.
&lt;/p&gt; &lt;p class=&quot;figure&quot;&gt;
&lt;img src=&quot;http://farm3.static.flickr.com/2639/3967843800_a613e9c8ce.jpg&quot; alt=&quot;A graph showing number of request in 300 seconds on the X axis and packet latency on the Y axis. With increasing packet latency the number of requests decreases&quot; height=&quot;301&quot; width=&quot;500&quot;&gt;&lt;br&gt;
&lt;em&gt;Figure 1: The effect of packet latency on download speed&lt;/em&gt;
&lt;/p&gt; &lt;p class=&quot;figure&quot;&gt;
&lt;img src=&quot;http://farm3.static.flickr.com/2506/3967842708_f143eca6db.jpg&quot; alt=&quot;A graph showing number of request in 300 seconds on the X axis and packet loss on the Y axis. With increasing packet loss the number of requests decreases.&quot; height=&quot;300&quot; width=&quot;500&quot;&gt;&lt;br&gt;
&lt;em&gt;Figure 2: Effect of packet loss on download speed&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Just 100 milliseconds of packet latency is enough to cause a smallish file to download in an average of 1500 milliseconds instead of 350 milliseconds. And that's not the worst part: the individual download times ranged from 1,000 to 3,000 milliseconds. Software that's consistently slow can be endured. Software that halts for no obvious reason is maddening.&lt;/p&gt; &lt;p class=&quot;figure&quot;&gt;
&lt;img src=&quot;http://farm3.static.flickr.com/2461/3950605017_2fee97f5de.jpg&quot; alt=&quot;A graph showing the response time in seconds from 0 to 3 on the Y axis with time on the X axis. The response times fluctuate between 0.25 and 3 seconds until a point in time labeled 'tea is done' when they become consistent between 0.25 and 0.75s.&quot; height=&quot;193&quot; width=&quot;500&quot;&gt;&lt;br&gt;
&lt;em&gt;Figure 3: Extreme volatility of response times during packet loss.&lt;/em&gt;&lt;/p&gt; &lt;h3&gt;So, latency sucks. Now what?&lt;/h3&gt; &lt;p&gt;Yahoo's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html&quot;&gt;web performance guidelines&lt;/a&gt; are still the most complete resource around, and backed up by real-world data. The key advice is to reduce the number of HTTP requests, reduce the amount of data sent, and to order requests in ways that use the observed behavior of browsers to best effect. However there is a simplification which buckets users into high/low/mobile categories. This doesn't necessarily address poor-quality bandwidth across all classes of user. The user's connection quality is often very bad and getting worse, which changes the calculus of what techniques to employ. In particular we should also take into account that:&lt;/p&gt; &lt;ul&gt; &lt;li class=&quot;bullist&quot;&gt;Upstream packets are almost always expensive.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;Any client can have high or low overall bandwidth.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;High latency is not an error condition, it's a fact of life.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;TCP connections and DNS lookups are expensive under high latency.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;Variable latency is in some ways worse than low bandwidth.&lt;/li&gt;
&lt;/ul&gt; &lt;p&gt;Assuming that a large but unknown percentage of your users labor under adverse network conditions, here are some things you can do:&lt;/p&gt; &lt;ul&gt; &lt;li class=&quot;bullist&quot;&gt;To keep your user's HTTP requests down to one packet, stay within a budget of about 800 bytes for cookies and URLs. Note that every byte of the URL counts twice: once for the URL and once for the Referer header on subsequent clicks. An interesting technique is to store app state that doesn't need to go to the server in fragment identifiers instead of query string parameters, e.g. &lt;code&gt;/blah#foo=bar&lt;/code&gt; instead of &lt;code&gt;/blah?foo=bar&lt;/code&gt;. Nothing after the # mark is sent to the server.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;If your app sends largish amounts of data upstream (excluding images, which are already compressed), consider implementing client-side compression. It's possible to get 1.5:1 compression with a simple LZW+Base64 function; if you're willing to monkey with ActionScript you could probably do &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://probertson.com/projects/gzipencoder/&quot;&gt;real gzip compression&lt;/a&gt;.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;&lt;p&gt;YSlow says you should &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html#flush&quot;&gt;flush() early&lt;/a&gt; and put &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html#js_bottom&quot;&gt;Javascript at the bottom&lt;/a&gt;. The reasoning is sound: get the HTML &amp;lt;head&amp;gt; portion out as quickly as possible so the browser can start downloading any referenced stylesheets and images. On the other hand, JS is supposed to go on the bottom because script tags halt parallel downloads. The trouble comes when your page arrives in pieces over a long period of time: the HTML and CSS are mostly there, maybe some images, but the JS is lost in the ether. That means the application may look like it's ready to go but actually isn't &amp;mdash; the click handlers and logic and ajax includes haven't arrived yet.&lt;/p&gt; &lt;p class=&quot;figure&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3532/3951381234_f55f000299_o.jpg&quot; alt=&quot;Partly loaded images on Google docs view of this article&quot;&gt;&lt;br&gt;
&lt;em&gt;Figure 4: docs is loading slowly... dare I click?&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Maybe in addition to the CSS/HTML/Javascript sandwich you could stuff a minimal version of the UI into the first 1-3KB, which gets replaced by the full version. Google Docs presents document contents as quickly as possible but disables the buttons until its sanity checks pass. Yahoo's home page does something similar.&lt;/p&gt; &lt;p&gt;This won't do for heavier applications, or those that don't have a lot of passive text to distract the user with while frantic work happens offstage. Gmail compromises with a loading screen which times out after X seconds. On timeout it asks the user to choose whether to reload or use their lite version.&lt;/p&gt;&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;Have a plan for disaster: what should happen when one of your scripts or styles or data blobs never arrives? Worse, what if the user's cached copy is corrupted? How do you detect it? Do you retry or fail? A quick win might be to add a checksum/eval step to your javascript and stylesheets.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;We also recommend that you should make as much CSS and Javascript as possible external and to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html#cdn&quot;&gt;parallelize HTTP requests&lt;/a&gt;. But is it wise to do more DNS lookups and open new TCP connections under very high latency? If each new connection takes a couple seconds to establish, it may be better to inline as much as possible.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;The trick is how to decide that an arbitrary user is suffering high latency. For mobile users you can pretty much take high latency as a given [&lt;a rel=&quot;nofollow&quot; href=&quot;#note4&quot;&gt;4&lt;/a&gt;]. Armed with per-IP statistics on client network latency from bullet #4 above, you can build a lookup table of high-latency subnets and handle requests from those subnets differently. For example if your servers are in Seattle it's a good bet that clients in the 200.0.0.0/8 subnet will be slow. 200.* is for Brasil but the point is that you don't need to know it's for Brasil or iPhone or whatever &amp;mdash; you're just acting on observed behavior. Handling individual users from &quot;fast&quot; subnets who happen to have high latency is a taller order. It may be possible to get information from the socket layer about how long it took to establish the initial connection. I don't know the answer yet but there is promising research here and there.&lt;/li&gt; &lt;li class=&quot;bullist&quot;&gt;A good technique that seems to go in and out of fashion is KeepAlive. Modern high-end load balancers will try to keep the TCP connection alive between themselves and the client, no matter what, while also honoring whatever KeepAlive behavior the webserver asks for. This saves expensive TCP connection setup and teardown without tying up expensive webserver processes (the reason why some people turn it off). There's no reason why you couldn't do the same with a software load balancer / proxy like Varnish.&lt;/li&gt;
&lt;/ul&gt; &lt;p&gt;This article is the first in a series and part of ongoing research on bandwidth and web app performance. It's still early in our research, but we chose to share what we've found early so you can join us on our journey of discovery. Next, we will dig deeper into some of the open questions we've posed, examine real-world performance in the face of high latency and packet loss, and suggest more techniques on how to make your apps work better in adverse conditions based on the data we collect.&lt;/p&gt; &lt;p&gt;Carlos Bueno&lt;br/&gt;
Software Engineer, Yahoo! Mail&lt;/p&gt; &lt;p&gt;Read more about &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/&quot;&gt;how to optimize your web site performance&lt;/a&gt; with the Yahoo! performance guidelines.&lt;/p&gt; &lt;h3&gt;Notes&lt;/h3&gt; &lt;p class=&quot;note&quot; id=&quot;note1&quot;&gt;[1] ceil(N / 1460) is the same algorithm you use to figure out how many trips it takes to carry your laundry down the stairs. (ceil is geekspeak for rounding up.) Say you have 50 pounds of clothes and the basket holds 13 pounds. 50 / 13 = 3 remainder 11, so you need to make 4 trips. The bigger the basket the fewer the trips. So why not use huge packets? On private networks you might see configurations for &quot;Jumbo frames&quot;. But in the wild you have to consider the cost of packet loss, typical message sizes, old or incompatible routers, etc.&lt;/p&gt; &lt;p class=&quot;note&quot;&gt;That specific number (aka Maximum Segment Size) comes from the maximum packet size (aka Maximum Transmission Unit) of 1,500 octets (aka bytes) set in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.faqs.org/rfcs/rfc1191.html&quot;&gt;RFC 1191 (aka Ethernet v2)&lt;/a&gt;, minus the space reserved for the source and destination addresses, flags, etc. IPv6, which has been coming any day now since the Clinton administration, will probably converge on an MSS of 1,220 or 1,440 in the wild. Point being, we're stuck with tiny packets for the rest of our lifetimes.&lt;/p&gt; &lt;p class=&quot;note&quot; id=&quot;note2&quot;&gt;[2] DNS can also cause latency. We tend to take hostname lookups for granted, but an ISP's DNS resolvers are often unloved. It once took me several years to convince BellSouth's customer service that one of their DNS resolvers was actually off the network. User DNS problems are doubly nasty because we as application developers can't control or even detect them.&lt;/p&gt; &lt;p class=&quot;note&quot; id=&quot;note3&quot;&gt;[3] The script was single-threaded and used a new TCP connection for each request. A single restriction was used per run, ie X milliseconds latency or Y% packet loss. The wifi was a Linksys WRT45g at a distance of 5 meters, with standard firmware in 802.11g mode and WPA2 encryption. The uplink was a &quot;6mbps&quot; home cable connection about 50 miles and ten network hops away from the nearest Yahoo caching server, during off-peak hours.&lt;/p&gt; &lt;p class=&quot;note&quot; id=&quot;note4&quot;&gt;[4] The Google mobile team recently put out an &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ajaxian.com/archives/gmail-mobile-latency&quot;&gt;interesting fact&lt;/a&gt;: &quot;On an iPhone 2.2 device, 200k of JavaScript held within a block comment adds 240ms during page load, whereas 200k of JavaScript that is parsed during page load added 2600 ms.&quot;&lt;/p&gt; &lt;p class=&quot;note&quot;&gt;Image Credit: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.flickr.com/photos/toestubber/525734621/&quot;&gt;Pachinko&lt;/a&gt; by the_toe_stubber on Flickr.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2009/10/a_engineers_gui.html</guid>
         <pubDate>Thu, 01 Oct 2009 09:00:35 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>Not Just a Pretty Face: Performance and the New Yahoo! Search</title>
         <link>http://developer.yahoo.net/blog/archives/2009/09/search_performance.html</link>
         <description>&lt;p&gt;Today we announced the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://search.yahoo.com/search?p=cute%20puppies&quot;&gt;new Yahoo! Search Results Page&lt;/a&gt;, which ships with a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ysearchblog.com/2009/09/22/welcome-to-the-new-yahoo-search/&quot;&gt;wide array of rich new features&lt;/a&gt;. What you might be surprised to learn is that the new design is actually a little &lt;em&gt;faster&lt;/em&gt; than the original. Through diligent use of modern performance techniques, we not only held the line on the total page size and number of HTTP requests, but we also made a number of improvements to the load time of the page. Now that you've seen the new search results page, let's walk through some of the performance considerations we used when constructing the new template.&lt;/p&gt; &lt;h3&gt;Code Refactoring&lt;/h3&gt; &lt;p&gt;Any sweeping design change like this is a great opportunity to refactor, and we took full advantage, rebuilding the Yahoo! Search page's HTML, CSS, and JavaScript foundation from scratch. If you think of the template as a shell that wraps the &quot;10 blue links&quot; in the center of the page, &lt;em&gt;all&lt;/em&gt; the markup around the middle content well has been rewritten. This allowed us to get rid of old cruft and take advantage of quite a few new techniques and best practices, reducing core pageweight and render complexity in the process.&lt;/p&gt; &lt;p&gt;As just one quick example of what's new, our search page now uses CSS image flipping. Rather than including separate images in our sprite for up and down arrows, we actually only include a down arrow. To generate an up arrow for all A-grade browsers, we use vendor-provided CSS hooks:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;-moz-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The actual byte savings are small, but every little bit counts, and this was relatively easy to implement.&lt;/p&gt; &lt;p&gt;We also took this opportunity to improve page structure and accessibility. As far as we are concerned, the philosophy that you have to create a separate experience for accessibility is a fallacy; we believe you can write accessible markup without hurting performance. A key improvement in the new design is simply creating better document structure using &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;, which enables screenreaders to navigate the page more easily. We've also added some better keyboard interactions, such as making sure the first tab key press takes you directly to the search box instead of hitting navigation links, and enabling &lt;code&gt;CTRL-SHIFT DOWN&lt;/code&gt; to jump past the header and sidebar and put focus on the first web result.&lt;/p&gt; &lt;h3&gt;Data URI Images&lt;/h3&gt; &lt;p&gt;The new design incorporates several subtle, repeating gradients, which look great but can be absolute performance killers. To help alleviate this problem, we took advantage of an obscure feature supported by all modern browsers called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.websiteoptimization.com/speed/tweak/inline-images/&quot;&gt;Data URI images&lt;/a&gt;. This technique enables you to embed the encoded data for individual images right into your CSS. The technique has been around for a while, but it's only recently become widely supported enough to use in production.&lt;/p&gt; &lt;p&gt;Data URI images enabled us to avoid the extra sprite weight associated with repeating gradients, while at the same time improving perceived performance by avoiding the &quot;pop-in&quot; effect that you sometimes see with template images. In a traditional CSS file that refers to external images, the browser loads the CSS, parses the CSS, and starts rendering the page. Any image references in the CSS spawn a new HTTP request. Depending on your connection speed, the page might have already rendered by the time the image returns, which causes the image to appear like it suddenly popped in to the page. Data URI images helped us eliminate the pop-in effect entirely and significantly &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html&quot;&gt;reduce the number of HTTP requests&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;To maintain backwards compatibility, we provided a separate gradient-only sprite for IE6 and IE7. This means that those browsers encounter slightly worse performance than more modern browsers, but the net effect is still an overall win. Of course, managing a split code base is a little risky. Many sites prefer to do this at runtime, using conditional comments or other techniques. In our case, the overall difference is actually pretty small &amp;mdash; our build tools push the right static resources to our CDN, and our frontend does browser sniffing and swaps in the right CSS file.&lt;/p&gt; &lt;h3&gt;Semantic Page Flushing&lt;/h3&gt; &lt;p&gt;Rather than waiting until the server generates the entire page and then sending everything at once, we send the page to the client in three semantically meaningful chunks, which enables the browser to start rendering the page and requesting static resources more quickly.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;The first chunk includes the page header and search box, and is sent before we even request search results from the backend. This enables the browser to begin downloading static resources while our server is still processing the search request.&lt;/li&gt; &lt;li&gt;The second chunk includes all the visible page content and ads, but no JavaScript. This enables the user to instantly begin scanning and interacting with their search results before the browser downloads and executes any Javascript code.&lt;/li&gt; &lt;li&gt;The final chunk includes the JavaScript that adds rich but non-critical functionality like &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tools.search.yahoo.com/newsearch/searchassist&quot;&gt;Search Assist&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tools.search.yahoo.com/newsearch/searchpad.html&quot;&gt;Search Pad&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt; &lt;p&gt;The net effect is that the user sees the page loading and can begin interacting with it much sooner. By sending the browser the info it needs to download static components as early as possible, we also reduce overall round-trip time.&lt;/p&gt; &lt;p&gt;Note that the old design also used semantic page flushing, but not quite as aggressively. The key difference is that in the previous design, the first chunk only included markup up to the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;. By refactoring how our backend logic works, we were able to push the chunk down into the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; and include key visual components such as the page header and search box. By getting the visual markup started down the wire, this creates the perception that the page is loading, that &quot;something is happening.&quot;&lt;/p&gt; &lt;h3&gt;Lazy Loading&lt;/h3&gt; &lt;p&gt;The core JavaScript and CSS used on the SRP now loads in two distinct chunks. The first chunk includes only the bare minimum CSS and JavaScript required to render 100% of search result pageviews, so that the base experience loads as quickly as possible. The second chunk includes additional (but heavy) functionality such as Search Assist and Search Pad. We also load additional chunks of CSS and JavaScript for shortcuts and other dynamic features only as necessary, ensuring that we never waste time loading code that we're unlikely to need.&lt;/p&gt; &lt;p&gt;As a search site, we can get away with heavy use of lazy-loading because the search experience is such a fundamental user experience on the web. When a user requests a search page, they typically scan and click &lt;em&gt;very&lt;/em&gt; quickly. As long as we make that core experience as fast as possible, we can defer other components for later. If your site has some other usage paradigm, you have to be more careful; you can't lazy load components that the user wants to interact with right away.&lt;/p&gt; &lt;h3&gt;Designers and Engineers Agree: Performance First!&lt;/h3&gt; &lt;p&gt;Beyond the technical considerations listed above, perhaps the most important factor was our philosophy that performance is &lt;em&gt;everybody's&lt;/em&gt; problem, at all stages. Our frontend engineering team started thinking about and planning for performance even before the designs were past the rough draft stage. This enabled us to give early feedback to our User Experience Design (UED) department and work closely with them as they refined their designs.&lt;/p&gt; &lt;p&gt;Our designers had already taken into account many performance concepts they had learned over the years, such as sprite optimization. However, the new design uses gradients far more heavily than the previous design, which can get expensive &amp;mdash; particularly if you stretch the gradients vertically or horizontally across the page.&lt;/p&gt; &lt;p&gt;Fortunately, our designers brought these considerations to us early, and we were able to brainstorm with them about how to use graphical components more efficiently. Once our designers understood some of the techniques we wanted to use and some of the limitations we had, they were able to knock out some absolutely gorgeous designs that still fit within our performance constraints. After those initial meetings, at each stage in the design our UED team would ping the performance engineers to ensure that we stayed within our performance targets. This close collaboration helped keep us from having to be reactive about performance.&lt;/p&gt; &lt;p&gt;In other words, new tricks and performance techniques only get you so far. Thanks to countless hours of hard work by individual designers and engineers, the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://search.yahoo.com/search?p=the%20simpsons&quot;&gt;new Yahoo! Search Page&lt;/a&gt; delivers far more functionality and design components in an even faster package. And we're still working hard with our designer colleagues to make the search experience even more fast and engaging over the coming weeks and months. If you have any questions about Yahoo! Search and frontend performance, we welcome your feedback!&lt;/p&gt; &lt;p&gt;Ryan Grove&lt;br&gt;Yahoo! Frontend Engineer&lt;/p&gt; &lt;p&gt;Stoyan Stefanov&lt;br&gt;Yahoo! Performance Engineer&lt;/p&gt; &lt;p&gt;Venkateswaran Udayasankar&lt;br&gt;Yahoo! Performance Engineer&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2009/09/search_performance.html</guid>
         <pubDate>Tue, 22 Sep 2009 11:57:43 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>YSlow Release</title>
         <link>http://developer.yahoo.net/blog/archives/2009/04/yslow_update.html</link>
         <description>&lt;p&gt;One of the most frequent complaints I hear about YSlow grades is, &quot;Some of these performance rules do not apply for my website.&quot; Most web developers want to evaluate site performance according to their own specific design and content criteria. For example: Not all sites use content delivery networks (CDNs). With the latest release of YSlow, it becomes really easy for web developers to configure their own rule sets and get relevant grades for their pages. We've also incorporated nine new rules, in addition to the previous thirteen. The ability to create your own rule set for performance testing is a next step towards opening up YSlow for developers to create and share their own rules.&lt;/p&gt; &lt;p&gt;Improving page performance sometimes involves reducing page weight. Images are one of the biggest contributors to page weight for most sites. Our performance rules talk about &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html#opt_images&quot;&gt;optimizing images&lt;/a&gt; to improve performance. Most often, in-depth knowledge of tools like Photoshop and other design tools is required to publish highly optimized images. We've removed the pain of optimization in this version of YSlow by integrating with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow/smushit&quot;&gt;Smush.it&lt;/a&gt;. Smush.it finds all images on your web page and applies the right techniques to optimize them without visual quality loss. Developers can also download &lt;em&gt;smushed&lt;/em&gt; images in a zip format.&lt;/p&gt; &lt;p&gt;The new look is designed to encourage developers to evaluate their webpage performance more closely and pay attention to small details, like making sure they've used small favicons that are cacheable. Our goal is a better, faster web experience for all.&lt;/p&gt; &lt;p&gt;If you have any questions or feedback, we encourage you to join the conversation on the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tech.groups.yahoo.com/group/exceptional-performance&quot;&gt;Yahoo! Exceptional Performance group&lt;/a&gt;. We look forward to your continued interest and enthusiasm – stay tuned, there's still a lot more to come.&lt;/p&gt; &lt;p&gt;Pramod Khincha&lt;br /&gt;
Exceptional Performance&lt;/p&gt; &lt;p&gt;&lt;br /&gt;
&lt;strong&gt;Note:&lt;/strong&gt; You can download this new &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://addons.mozilla.org/en-US/firefox/addon/5369&quot;&gt;YSlow release for Firefox here&lt;/a&gt;. Thanks to &lt;em&gt;cancel bubble&lt;/em&gt; (below) for providing the reminder and the link. &lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2009/04/yslow_update.html</guid>
         <pubDate>Wed, 29 Apr 2009 09:01:59 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>YSlow 2.0 early preview in China</title>
         <link>http://developer.yahoo.net/blog/archives/2008/12/yslow_20.html</link>
         <description>&lt;p&gt;Earlier this month, I had the pleasure of talking about the next iteration of Yahoo's performance tool YSlow at a conference organized by CSDN in Beijing. While YSlow 2.0 is still under development, it was a great opportunity to share the excitement about the upcoming release and also talk to people who are actually using the current version in their daily development life. We wanted to get a sense of whether we're headed in the right direction.&lt;/p&gt; &lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://csdn.net&quot;&gt;CSDN&lt;/a&gt; stands for China Software Developers Network: a vibrant online community with over 3 million members who create about a million forum posts and 50,000 technology articles, every month. The network runs on an in-house community platform allowing members to join discussions and forums, run blogs, chat, get personal hosting, personalized search and recommendations. The community recognizes and honors contributions through a rating system that rewards the best content with greater visibility. In addition to the online community, CSDN has a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.broadview.com.cn/&quot;&gt;book publishing house&lt;/a&gt;, prints China's authoritative IT technology magazine Programmer, and provides training and talent recruiting services.&lt;/p&gt; &lt;p&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3080/3133047752_913dc255de.jpg&quot; alt=&quot;CSDN keynotes&quot;/&gt;&lt;/p&gt; &lt;p&gt;In addition to the YSlow talk, I also gave one about JavaScript, you can check out the slides on Slideshare:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.slideshare.net/stoyan/yslow-20-presentation/&quot;&gt;YSlow 2.0&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.slideshare.net/stoyan/beginning-objectoriented-javascript-presentation/&quot;&gt;Object-Oriented JavaScript&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/p&gt; &lt;p&gt;Needless to say it was a great experience to meet and talk to the Chinese developers and answer their challenging questions about YSlow and OOJS. And then again, how can you not like a conference that opens in the spirit of the 2008 Beijing Olympics - &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://211.100.26.82/CSDN_Live/245/sdk1.wmv&quot;&gt;with cheerleaders&lt;/a&gt;!&lt;/p&gt; &lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://phpied.com&quot;&gt;Stoyan Stefanov&lt;/a&gt;&lt;br /&gt;
Performance guy / YSlow 2.0 architect&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/12/yslow_20.html</guid>
         <pubDate>Sun, 28 Dec 2008 08:04:34 -0800</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>YUI Theater — Douglas Crockford: &quot;Ajax Performance&quot;</title>
         <link>http://www.yuiblog.com/blog/2008/12/23/video-crockford-performance/</link>
         <description>Douglas Crockford returns to YUI Theater with another chapter in his evolving lecture series. This session, &amp;#8220;Ajax Performance,&amp;#8221; debunks common misconceptions about the relationship between JavaScript and performance and gives engineers a core focus for improving the performance of web apps: Reduce the value of n. Because DOM interactions are generally slow, leveraging [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/12/23/video-crockford-performance/</guid>
         <pubDate>Tue, 23 Dec 2008 08:07:47 -0800</pubDate>
         <content:encoded><![CDATA[<p><a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/4156174/11192533"><img src="http://ericmiraglia.com/assets/crockford-performance2.jpg" width="510" height="306"/></a></p>
<p>Douglas Crockford returns to YUI Theater with another chapter in his evolving lecture series. This session, &#8220;Ajax Performance,&#8221; debunks common misconceptions about the relationship between JavaScript and performance and gives engineers a core focus for improving the performance of web apps: <em>Reduce the value of </em>n. Because DOM interactions are generally slow, leveraging Ajax to reduce the number of DOM operations, Douglas argues, is often the most important optmization you can make. In fact, it usually dwarfs other techniques in terms of its impact on the actual experience of using a website.</p>
<p>This talk joins <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/theater/">an extensive library of Douglas&#8217;s lectures now available on YUI Theater</a>, including his popular series on JavaScript.</p>
<ul>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/assets/crockford-performance.zip">Slides (zipped PPT)</a></li>
<li><a rel="nofollow" target="_blank" href="http://ericmiraglia.com/blog/?p=140">Full text transcript of this talk</a></li>
</ul>
<p><iframe class="embeddedvideo" src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.30" type="application/x-shockwave-flash" width="512" height="322"></iframe></p> 
<p><a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/4141759/11157560">Douglas Crockford: "Ajax Performance"</a> @ <a rel="nofollow" target="_blank" href="http://video.yahoo.com">Yahoo! Video</a></p>
<p><img src="http://us.i1.yimg.com/us.yimg.com/i/nt/ic/ut/bsc/vidcam12_1.gif" border="0" hspace="10"><a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-performance.m4v">download (m4v)</a></p>
<h3>In Case You Missed&#8230;</h3>
<p>Some other recent videos from the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/theater/">YUI Theater series</a>:</p>
<ul>
<li><strong>Nicole Sullivan:</strong> "Design Fast Websites (Don&#8217;t Blame the Rounded Corners)" (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/4156174/11192533">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/sullivan-fast.m4v">.m4v download</a>)</li>
<li><strong>Todd Kloots:</strong> &#8220;Developing Accessible Widgets Using ARIA&#8221; (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/4073211/10996186">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/kloots-aria.m4v">.m4v download</a>)</li>
<li><strong>Nicholas C. Zakas:</strong> "Test-Driven Development with YUI Test" (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/3737228/10267335">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/zakas-yuitest.m4v">.m4v download</a>)</li>
<li><strong>Douglas Crockford:</strong> "Web Forward" (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/3730137/10250950">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-webforward.m4v">.m4v download</a>)</li>
</ul>
<h3>Subscribing to YUI Theater:</h3>
<ul>
<li><a rel="nofollow" target="_blank" href="http://feeds.feedburner.com/yuiblog/yui-theater">YUI Theater RSS feed</a></li>
<li><a rel="nofollow" target="_blank" href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=263846173&amp;s=143441">YUI Theater on iTunes</a></li>
</ul>]]></content:encoded>
         <enclosure length="195027943" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-performance.m4v" type="video/x-m4v"/>
         <enclosure length="173150421" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/sullivan-fast.m4v" type="video/x-m4v"/>
         <enclosure length="123775849" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/kloots-aria.m4v" type="video/x-m4v"/>
         <enclosure length="149378402" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/zakas-yuitest.m4v" type="video/x-m4v"/>
         <enclosure length="144845803" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-webforward.m4v" type="video/x-m4v"/>
      </item>
      <item>
         <title>YUI Theater — Nicole Sullivan: &quot;Design Fast Websites (Don’t Blame the Rounded Corners)&quot;</title>
         <link>http://www.yuiblog.com/blog/2008/12/23/video-sullivan/</link>
         <description>Nicole Sullivan is a website performance specialist and a former member of Yahoo&amp;#8217;s Exceptional Performance Team. She is currently writing a book for O&amp;#8217;Reilly with Stoyan Stefanov on performance optimization and she and Stoyan are the creators of Smushit, an engine for crushing images.
Nicole visited Yahoo last week to do an encore of her &amp;#34;Design [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/12/23/video-sullivan/</guid>
         <pubDate>Tue, 23 Dec 2008 08:04:25 -0800</pubDate>
         <content:encoded><![CDATA[<p><a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/4156174/11192533"><img src="http://ericmiraglia.com/assets/sullivan-fast.jpg" width="510" height="290"/></a></p>
<p><a rel="nofollow" target="_blank" href="http://stubbornella.org">Nicole Sullivan</a> is a website performance specialist and a former member of Yahoo&#8217;s Exceptional Performance Team. She is currently writing a book for O&#8217;Reilly with Stoyan Stefanov on performance optimization and she and Stoyan are the creators of <a rel="nofollow" target="_blank" href="http://smushit.com">Smushit</a>, an engine for crushing images.</p>
<p>Nicole visited Yahoo last week to do an encore of her "Design Fast Websites" talk in which she outlines a set of practical guidelines for building websites that are supremely fast <em>and</em> visually rich. Her advice is to know your craft, to engage your designers, and to make sure that your collaboration with designers works intelligently in the service of users. She was kind enough to let us record the talk and share it with you here on <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/theater/">YUI Theater</a>.</p>
<ul>
<li><a rel="nofollow" target="_blank" href="http://www.slideshare.net/stubbornella/designing-fast-websites-presentation">Slides (on Slideshare)</a></li>
</ul>
<p><iframe class="embeddedvideo" src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.30" type="application/x-shockwave-flash" width="512" height="322"></iframe></p> 
<p><a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/4156174/11192533">Nicole Sullivan: "Design Fast Websites"</a> @ <a rel="nofollow" target="_blank" href="http://video.yahoo.com">Yahoo! Video</a>&lt;/</p>
<p><img src="http://us.i1.yimg.com/us.yimg.com/i/nt/ic/ut/bsc/vidcam12_1.gif" border="0" hspace="10"><a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/sullivan-fast.m4v">download (m4v)</a></p>
<h3>In Case You Missed&#8230;</h3>
<p>Some other recent videos from the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/theater/">YUI Theater series</a>:</p>
<ul>
<li><strong>Todd Kloots:</strong> &#8220;Developing Accessible Widgets Using ARIA&#8221; (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/4073211/10996186">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/kloots-aria.m4v">.m4v download</a>)</li>
<li><strong>Nicholas C. Zakas:</strong> "Test-Driven Development with YUI Test" (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/3737228/10267335">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/zakas-yuitest.m4v">.m4v download</a>)</li>
<li><strong>Douglas Crockford:</strong> "Web Forward" (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/3730137/10250950">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-webforward.m4v">.m4v download</a>)</li>
<li><strong>Eric Miraglia and Matt Sweeney:</strong> "YUI3 &mdash; A Look Ahead" (<a rel="nofollow" target="_blank" href="http://video.yahoo.com/watch/3711767/10207432">Yahoo! Video</a> | <a rel="nofollow" target="_blank" href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/miraglia-yui3.m4v">.m4v download</a>)</li>
</ul>
<h3>Subscribing to YUI Theater:</h3>
<ul>
<li><a rel="nofollow" target="_blank" href="http://feeds.feedburner.com/yuiblog/yui-theater">YUI Theater RSS feed</a></li>
<li><a rel="nofollow" target="_blank" href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=263846173&amp;s=143441">YUI Theater on iTunes</a></li>
</ul>]]></content:encoded>
         <enclosure length="173150421" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/sullivan-fast.m4v" type="video/x-m4v"/>
         <enclosure length="123775849" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/kloots-aria.m4v" type="video/x-m4v"/>
         <enclosure length="149378402" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/zakas-yuitest.m4v" type="video/x-m4v"/>
         <enclosure length="144845803" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-webforward.m4v" type="video/x-m4v"/>
         <enclosure length="113033117" url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/miraglia-yui3.m4v" type="video/x-m4v"/>
      </item>
      <item>
         <title>Image Optimization, Part 5: AlphaImageLoader</title>
         <link>http://www.yuiblog.com/blog/2008/12/08/imageopt-5/</link>
         <description>About the Author: Stoyan Stefanov is a Yahoo! web developer working for the Exceptional Performance team and leading the development of the YSlow performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called Object-Oriented JavaScript. This is part 5 in an ongoing series. You can read the other parts [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/12/08/imageopt-5/</guid>
         <pubDate>Mon, 08 Dec 2008 05:48:09 -0800</pubDate>
         <content:encoded><![CDATA[<div class="interview">
<div class="intro">
<p><img src="http://yuiblog.com/assets/stoyan.jpg" alt="Stoyan Stefanov." align="right" hspace="10" vspace="5"><em><strong>About the Author:</strong><a rel="nofollow" target="_blank" href="http://www.phpied.com"> Stoyan Stefanov</a> is a Yahoo! web developer working for the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Exceptional Performance</a> team and leading the development of the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yslow/">YSlow</a> performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called <a rel="nofollow" target="_blank" href="http://www.packtpub.com/object-oriented-javascript-applications-libraries/book">Object-Oriented JavaScript</a>.</em></p>
</div>
</div>
<p><em>This is part 5 in an ongoing series. You can read the other parts here:</em></p>
<ul>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/10/29/imageopt-1/">Image Optimization Part 1: The Importance of Images</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/04/imageopt-2/">Image Optimization Part 2: Selecting the Right File Format</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/14/imageopt-3/">Image Optimization Part 3: Four Steps to File Size Reduction</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/12/05/imageopt-4/">Image Optimization Part 4: Progressive JPEG&#8230;Hot or Not?</a></li>
</ul>
<p>This installment of the image optimization series is about the IE-proprietary AlphaImageLoader CSS filter, which developers often use as a workaround to solve transparency issues with truecolor PNGs in IE. The problem with AlphaImageLoader is that it hurts page performance and, therefore, hurts user experience. I argue that AlphaImageLoader should be avoided when at all possible.</p>
<h3>Quick Refresher</h3>
<p>As mentioned in a <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/04/imageopt-2/">previous article</a>, <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Portable_Network_Graphics">PNGs</a> come in several different types but can roughly be divided into:</p>
<ul>
<li>Indexed (palette), also referred to as PNG8 which have up to 256 colors.</li>
<li>Truecolor PNG, also referred to as PNG32 or PNG24.</li>
</ul>
<p>Both formats support alpha (variable) transparency and, while PNG8 images degrade to a GIF-like non-variable transparency in IE6 (<a rel="nofollow" target="_blank" href="http://yuiblog.com/assets/png8-transparency.png">example</a>, <a rel="nofollow" target="_blank" href="http://www.sitepoint.com/blogs/2007/09/18/png8-the-clear-winner/">source</a>), truecolor PNGs show an uglyish background in place of the transparent pixels (source <a rel="nofollow">W3C</a>).</p>
<p><img src="http://yuiblog.com/assets/png-transparency.png" alt="truecolor PNG transparency problem in IE6"/></p>
<h3>The AlphaImageLoader fix</h3>
<p>IE6 (and older versions of IE) provides a solution to the problem through its proprietary <code>filter</code> CSS property. The following code will display the proper image cross-browser:</p>
<pre>
#some-element { background: url(image.png); _background: none; _filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png', sizingMethod='crop');
}
</pre>
<p>As you can see, the underscore CSS hack is used to target IE &lt; 7 and</p>
<ol>
<li>&#8220;undo&#8221; the background; and</li>
<li>load the same image, using Microsoft&#8217;s AlphaImageLoader filter.</li>
</ol>
<p>The reason to target IE prior to version 7 is that IE7 supports the alpha transparency natively without the need for filters. (IE8 does too and it actually <a rel="nofollow" target="_blank" href="http://blogs.msdn.com/ie/archive/2008/09/08/microsoft-css-vendor-extensions.aspx">changes the filter syntax</a> completely.)</p>
<p>
It&#8217;s interesting to note that the filter doesn&#8217;t change the image; rather, it changes the HTML element this style is applied to. The other interesting thing is that each element is processed synchronously in a single UI thread. The process applying the filter takes some resources for each element and the more &#8220;filtered&#8221; elements you have, the worse it gets, even if you use the same image for all the elements.
</p>
<p>The question is: How does this affect the overall performance of the page?</p>
<h3>Freeze! Side Effect #1</h3>
<p>Here&#8217;s a simple experiment: Create a page that has a CSS filter and then simulate (and exaggerate) network latency by delaying the image used in the filter by ten seconds. The result? Not only is nothing rendered (blank page) for ten seconds, but the browser freezes, meaning you cannot interact with it, click its icons or menus, type in the URL&#8230;you can&#8217;t even close it.</p>
<p><a rel="nofollow" target="_blank" href="http://yuiblog.com/assets/image-opt-tests/alphatest.html">Here&#8217;s a test example.</a></p>
<p>In the example, I didn&#8217;t use the underscore hack so you can see the (d)effect in IE7 too, even in IE8 in &#8220;compatibility mode&#8221;.</p>
<p>While the effect is exaggerated for demo purposes, network latencies are a fact of life and this is probably the worst user experience you can deliver: Someone comes to your page and their browser freezes.</p>
<p>Note that parallel downloads are not blocked. The browser still downloads the other page components in the background, but there&#8217;s no progressive rendering. You can think of it this way &mdash; since IE will not render anything until the very last bit of CSS comes down the wire (<a rel="nofollow" target="_blank" href="http://www.phpied.com/rendering-styles/">more info</a>), and your because CSS has a dependency on a filtered image, the rendering is blocked until the dependency is satisfied.</p>
<p>What if you have several AlphaImageLoader filters on the page? They are processed synchronously one after the other so the problem is multiplied. If you have 5 images, each delayed 2 seconds on the server, then the browser freezes for a total of 10 seconds.</p>
<h3>Time and Memory &mdash; Side Effects #2 and #3</h3>
<p>Another negative effect of using the AlphaImageLoader is the increase of the amount of memory required to process and apply the filters. These days we might be tempted to think our visitors&#8217; computers have a virtually indefinite supply of memory, but for older computers (those more likely to run IE6 and under) this may not be the case.</p>
<p>And at the end of it, it&#8217;s the performance we&#8217;re most interested in, performance as measured by the time it takes for the page to load in the browser. Let&#8217;s do a test to measure how much time and memory is required by the filters.</p>
<p>First, let&#8217;s have a baseline page &mdash; one that has a hundred &lt;div&gt;s with the same non-filtered background image. Then let&#8217;s have a second page with a filter applied to the divs (all 100 divs use the same). A hundred elements with filtered backgrounds is unlikely to be found in a normal page, but a little exaggeration will help with the measurements.</p>
<p>The time is measured from the start of the page to the onload event of the page, after the images have been cached, thus eliminating the time required to download the page and the images. The memory consumption is measured with the help of the <a rel="nofollow" target="_blank" href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx">ProcessExplorer</a> tool and given as the before/after delta of the private bytes measurement, showing the &#8220;price&#8221; of rendering the page.
<p>Here are the median results from 10 runs in IE6 on a PC with a dual 2GHz CPU and 500M RAM. On a less powerful computer, the load times are likely to be even worse.</p>
<style type="text/css">td.number{text-align:right;}</style>
<table border="1">
<caption>AlphaImageLoader test results</caption>
<tbody>
<tr>
<th>test page</th>
<th>time, seconds</th>
<th>memory, MB</th>
</tr>
<tr>
<td><a rel="nofollow">Test #1 &#8211; no filters</a></td>
<td class="number">0.031</td>
<td class="number">0.6</td>
</tr>
<tr>
<td><a rel="nofollow">Test #2 &#8211; with filters</a></td>
<td class="number">0.844</td>
<td class="number">46.8</td>
</tr>
</tbody>
</table>
<p>As you can see, the AlphaImageLoader effect is pretty bad &mdash; our test page loads 27 times slower and eats up 78 times more memory. These results are, of course, highly speculative &mdash; it&#8217;s just one image tested on just one PC (relatively powerful and underworked). With different images, applied to a different number of elements and on different machines, results may vary considerably, especially when there&#8217;s less RAM or CPU, or if you throw network latency (side effect #1) into the mix. But this example illustrates the important concepts:</p>
<ul>
<li>AlphaImageLoader is slow and requires more memory</li>
<li>It&#8217;s applied per element, not per image</li>
</ul>
<p>If you have a sprite image and you use it for different elements (sprites with alpha filters are trickier, <a rel="nofollow" target="_blank" href="http://www.julienlecomte.net/blog/2007/07/4/">but doable</a>), you&#8217;ll pay the penalty for each element the sprite is used on.</p>
<h3>Yahoo! Search Case Study</h3>
<p>Using lab tests like the one above can give us some idea of the AlphaImageLoader &#8220;price,&#8221; and you might be tempted to test and calculate approximately how much you pay for each filtered element, but there&#8217;s nothing better than a real life test with millions of requests coming form different parts of the world with different browsers, computers and bandwidth.</p>
<p><a rel="nofollow" target="_blank" href="http://search.yahoo.com/search?p=yahoo+search">Yahoo!&#8217;s search results page</a> used to have a truecolor PNG sprite and employed AlphaImageLoader to achieve the transparency (an <a rel="nofollow" target="_blank" href="http://us.js2.yimg.com/us.yimg.com/i/us/sch/el/ngsprt_srp_20071130.png">older version of the sprite</a> is still around if you&#8217;re curious). Replacing the truecolor PNG with a gracefully degrading PNG8 (<a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/04/imageopt-2/">discussed previously</a>) decreased the pageload time by 50-100ms for the users of IE 5 and 6. 100ms may not seem like much, but for a page that loads under a second, it&#8217;s at least 10%. Also, according to <a rel="nofollow" target="_blank" href="http://home.blarg.net/%7Eglinden/StanfordDataMining.2006-11-29.ppt">an Amazon study</a>, 100ms slower means 1% fewer sales (even for their content-heavy pages). Earning 1% more by just replacing an image doesn&#8217;t look like a bad deal at all.</p>
<h3>So Now What?</h3>
<p>The best thing would be to avoid AlphaImageLoader completely and, like Y!Search, take the time to create PNG8 images that degrade nicely in IE6 and look good in all other browsers. How do you create a gracefully degrading PNG8? Well, create a GIF-like image first, one that has only fully transparent or fully opaque pixels. After making sure it looks acceptable (it will look like this in IE6), proceed to enhancing the image with semi-transparent pixels which will smooth any rounded corners or other parts that would benefit from transparency. Unfortunately, as far as I know, Fireworks is currently the only image processing software capable of handling alpha transparency in PNG8. You can also try command line tools such as <a rel="nofollow">pngnq</a> and <a rel="nofollow" target="_blank" href="http://www.libpng.org/pub/png/apps/pngquant.html">pngquant</a>, although automated truecolor-to-palette PNG conversion might not always yield satisfactory results and you might need to pick the fully opaque pixels manually.</p>
<p>There might be cases when you won&#8217;t be able to get by with a PNG8 and absolutely need to use AlphaImageLoader &mdash; for example when most or all pixels are semi-transparent (imagine a &#8220;play&#8221; button over a video thumbnail). Dave Artz of AOL has some <a rel="nofollow" target="_blank" href="http://www.artzstudio.com/2008/07/png-alpha-transparency-no-clear-winner/">other cases</a> where PNG8 will not be good enough. In such cases (but only after you try your best to persuade the designer to reconsider the use of transparency), make sure you use the underscore hack (<code>_filter</code>) so that you don&#8217;t penalize IE7 users.</p>
<p>Sometimes instead of PNG8 people use GIF for IE6 and truecolor PNG for the others, but that&#8217;s not necessary; with one PNG8 you achieve both binary and alpha transparency.</p>
<p>Additional benefits from using a PNG8 are:</p>
<ol>
<li>PNG8 is usually smaller than truecolor PNG,</li>
<li>only one image to maintain for all browsers</li>
<li>cleaner CSS with no hacks, branches or proprietary tags</li>
<li>ability to repeat background</li>
</ol>
<h3>Transparency with VML</h3>
<p>Using VML is yet another option in IE to make a truecolor PNG transparent, and it solves several problems: alpha transparency, performance, and background repeat. Unfortunatelly, it comes with the price of extra non-standard markup (or dependency on JavaScript to generate it if you want your initial markup clean) and more propritary CSS. Here&#8217;s an example on how to implement it.</p>
<p>If, for example, you have an empty div, you need to wrap it in one VML <code>:rect</code> (or <code>:shape</code>) and one <code>:fill</code> element, like this:</p>
<pre>
&lt;v:rect&gt; &lt;v:fill type="tile" src="alphatest.png"&gt; &lt;div&gt;&amp;nbsp;&lt;/div&gt; &lt;/v:fill&gt;
&lt;/v:rect&gt;
</pre>
<p>Somewhere in the markup before that you also need to declare a VML namespace:</p>
<pre>
&lt;xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" /&gt;
</pre>
<p>And in your stylesheet you need:</p>
<pre>
v&#92;:rect { behavior:url(#default#VML); width: 100px; height: 100px; display: block;
} v&#92;:fill { behavior:url(#default#VML);
}
</pre>
<p><a rel="nofollow" target="_blank" href="http://yuiblog.com/assets/image-opt-tests/vml.html">A test page</a> with 100 VML <code>rect</code> elements loads in 0.094 seconds (almost 10 times faster than using filters) and the memory usage is under 4Mb (10 times less than the filtered page).</p>
<p>As you can see this solution adds more markup and proprietary CSS, but it&#8217;s still a solution and doesn&#8217;t have the penalties of the AlphaImageLoader.</p>
<p>(Thanks go to <a rel="nofollow" target="_blank" href="http://dillerdesign.com/experiment/DD_roundies/">this post</a> by Drew Diller and also <a rel="nofollow" target="_blank" href="http://www.htmlremix.com/curved-corner-border-radius-cross-browser/">HTML Remix</a>, who accidentally found this side effect while working on another problem &mdash; rounded corners with VML, via <a rel="nofollow" target="_blank" href="http://snook.ca/archives/html_and_css/ie-rounded/">snook.ca</a>)</p>
<h3>P.S. &#8230;and What about Other Filters</h3>
<p>AlphaImageLoader is not the only filter that exists. Another popular one is the opacity filter. </p>
<p>For example, for 50% element opacity developers use the properties: </p>
<ul>
<li><code>opacity: 0.5</code> (standard),</li>
<li><code>-moz-opacity: 0.5</code> (early Mozilla versions, before Firefox 0.9), and</li>
<li>for IE, <code>filter: alpha(opacity=50)</code>.</li>
</ul>
<p>A quick test in IE6 shows that the opacity filter is not nearly as slow as the AlphaImageLoader, but it&#8217;s still making the page slower and takes the same amount of memory. This test uses color background, not an image, but even with an image the results are pretty much the same.</p>
<table border="1">
<caption>opacity filter test results</caption>
<tbody>
<tr>
<th>test page</th>
<th>time, seconds</th>
<th>memory, MB</th>
</tr>
<tr>
<td><a rel="nofollow">Test #3 &#8211; 100 divs, no opacity</a></td>
<td class="number">0.016</td>
<td class="number">0.2</td>
</tr>
<tr>
<td><a rel="nofollow">Test #4 &#8211; 100 divs with opacity</a></td>
<td class="number">0.093</td>
<td class="number">46.7</td>
</tr>
</tbody>
</table>]]></content:encoded>
      </item>
      <item>
         <title>Image Optimization, Part 3: Four Steps to File Size Reduction</title>
         <link>http://www.yuiblog.com/blog/2008/11/14/imageopt-3/</link>
         <description>About the Author: Stoyan Stefanov is a Yahoo! web developer working for the Exceptional Performance team and leading the development of the YSlow performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called Object-Oriented JavaScript. This is part 3 in an ongoing series. You can read the other parts [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/11/14/imageopt-3/</guid>
         <pubDate>Fri, 14 Nov 2008 08:37:31 -0800</pubDate>
         <content:encoded><![CDATA[<div class="interview">
<div class="intro">
<p><img src="http://yuiblog.com/assets/stoyan.jpg" alt="Stoyan Stefanov." align="right" hspace="10" vspace="5"><em><strong>About the Author:</strong><a rel="nofollow" target="_blank" href="http://www.phpied.com"> Stoyan Stefanov</a> is a Yahoo! web developer working for the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Exceptional Performance</a> team and leading the development of the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yslow/">YSlow</a> performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called <a rel="nofollow" target="_blank" href="http://www.packtpub.com/object-oriented-javascript-applications-libraries/book">Object-Oriented JavaScript</a>.</em></p>
</div>
</div>
<p><em>This is part 3 in an ongoing series. You can read the other parts here:</em></p>
<ul>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/10/29/imageopt-1/">Image Optimization Part 1: The Importance of Images</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/04/imageopt-2/">Image Optimization Part 2: Selecting the Right File Format</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/12/05/imageopt-4/">Image Optimization Part 4: Progressive JPEG…Hot or Not?</a></li>
</ul>
<p>This post is about some common tools you can use to reduce the file size of your images. The idea is to be able to just take the images your designer has created and instead of using them &#8220;as is&#8221;, go ahead and tidy them up in short time and no effort, without even looking at them.</p>
<p>The good news is that this process is:</p>
<ul>
<li><em>lossless</em> &#8211; you strip bytes, hence you lose some information, but not the pixel data and the resulting image looks exactly the same as the source with no quality loss</li>
<li><em>uses free tools</em> &#8211; all the tools we mention here are free and open-source, and work on both Windows and Unix</li>
<li><em>automated</em> &#8211; since these are command line tools, they are easy to script and automate; one example of such automation is the <a rel="nofollow" target="_blank" href="http://smush.it">smush.it</a> tool</li>
</ul>
<h3>Step 1: Crush PNG</h3>
<p>PNGs store information in so-called &#8220;chunks&#8221; and not all of those chunks are required for the display of the image. In fact most of them are not. You can safely use a tool such as <a rel="nofollow" target="_blank" href="http://pmt.sourceforge.net/pngcrush/">pngcrush</a> and strip all the unneeded chunks. For example:</p>
<pre>&gt; pngcrush -rem alla -brute -reduce src.png dest.png</pre>
<p>Let&#8217;s take a look at the options of this command:</p>
<ul>
<li><code>src.png</code> is the source image, <code>dest.png</code> is the destination (result) image</li>
<li><code>-rem alla</code> means remove all chunks but keeps the one for transparency</li>
<li><code>-reduce</code> tries to reduce the number of colors in the palette if this is possible</li>
<li><code>-brute</code> tries over a hundred different methods for optimization in addition to the default 10. It&#8217;s slower and most of the times doesn&#8217;t improve much. But if you&#8217;re doing this process &#8220;offline&#8221;, one or two more seconds are not important since there&#8217;s a chance if a filesize win. Remove this option in performance-sensitive scenarios.</li>
</ul>
<p>Running this command on the PNGs found on Alexa&#8217;s top 10 sites gives us an average file size reduction of <strong>16.05%</strong>. This means you can easily <strong>strip weight off your PNG images</strong>, save bandwidth and disk space and improve load times, without sacrificing quality and without even touching a single line of application code.</p>
<p>PNGcrush is only one of the available tools for this sort of optimizations. Other tools you can take a look at include:
<ul>
<li><a rel="nofollow" target="_blank" href="http://www.pobox.com/~jason1/pngrewrite/">pngrewrite</a></li>
<li><a rel="nofollow" target="_blank" href="http://www.cs.toronto.edu/~cosmin/pngtech/optipng/">OptiPNG</a></li>
<li><a rel="nofollow" target="_blank" href="http://advsys.net/ken/utils.htm">PNGOut</a></li>
</ul>
<p>Now that we&#8217;ve got a pretty good PNG solution, let&#8217;s see if we can do the same for the other image types.</p>
<h3>Step 2: Strip JPG Metadata</h3>
<p>JPEGs files contain meta data such as:
<ul>
<li>comments</li>
<li>application-specific (think Photoshop) meta data</li>
<li>EXIF information such as camera information, date the photo was taken and even thumbnails of the actual image or audio!</li>
</ul>
<p>This meta data is not required for the display of the image and can safely be stripped with no pixel quality loss. As discussed previously, JPEG is a lossy format, which means you lose quality every time you save. But luckily there are some operations that are lossless. Such operations include cropping a part of the image, rotation and the personal favorite &#8211; copying metadata. One tool that allows you to do these is called <a rel="nofollow" target="_blank" href="http://jpegclub.org/">jpegtran</a>.</p>
<p>Here&#8217;s a command to copy the source image, optimize it and don&#8217;t carry over any metadata in the new copy:</p>
<pre>&gt; jpegtran -copy none -optimize src.jpg dest.jpg</pre>
<p>Note that depending on the version you have, you might need to use the syntax ending with <code>src.jpg &gt; dest.jpg</code></p>
<p>The <code>-optimize</code> option will cause jpegtran to optimize the Huffman tables and improve compression.</p>
<p>Running this command on Alexa top 10 sites resulted in average savings of <strong>11.85%</strong>.</p>
<p>You may be able to further improve image size by using jpegtran&#8217;s <code>-progressive</code> option. It produces JPEGs that load progressively in the browser, starting from a lower quality version of the image and improving as new image information arrives.</p>
<p><strong>Important note on stripping meta information: do it only for images that you own, because when jpegtan strips all the meta, it also strips any copyright information contained in the image file.</strong></p>
<h3>Step 3: GIF to PNG</h3>
<p>What&#8217;s the best way to improve a GIF? Convert it to a PNG. As funny as it may sound, it&#8217;s true. Most of the time you get a smaller file size from a PNG and the same quality and browser support, <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/04/imageopt-2/">as we discussed in a previous article</a>. Note that PNG will not always be smaller, but most of the time it will be, so it&#8217;s worth checking after the conversion and keeping the smaller of the two files.</p>
<p>In order to automatically change your GIFs, you can use ImageMagick&#8217;s <code>convert</code>:</p>
<pre>&gt; convert image.gif image.png</pre>
<p>If you want to force PNG8 format you can use:</p>
<pre>&gt; convert image.gif PNG8:image.png</pre>
<p>This is probably not necessary, since GIFs will most likely be converted to a PNG8 anyway because ImageMagick picks the appropriate format based on the number of colors.</p>
<p>Once you&#8217;ve converted the GIF to a PNG, don&#8217;t forget to still crush the PNG result (as shown in step 1).</p>
<p>If the top 10 sites switch all their GIFs for PNGs (except those that don&#8217;t yield a smaller file size), on average, this will result in <strong>20.42%</strong> file size reduction. The only inconvenience here is that you also need to write a search/replace script to find all the references to the GIF files and change them to the new PNG versions.</p>
<h3>Step 4: Optimize GIF animations</h3>
<p>Now that all GIFs are PNGs, PNGs are crushed and so are the JPEGs, what do we have left? GIF animations. One tool that can help you with those guys is called <a rel="nofollow" target="_blank" href="http://www.lcdf.org/gifsicle/">GIFsicle</a>. Since the animations consist of frames and some parts of the image don&#8217;t change from one frame to another, GIFsicle doesn&#8217;t carry over the duplicate pixel information. The way to run it is:</p>
<pre>&gt; gifsicle -O2 src.gif &gt; dest.gif</pre>
<h3>Smush.it</h3>
<p>As we said at the beginning, the beauty of those four steps is that they don&#8217;t cause quality loss, so you don&#8217;t have to open and compare the results before and after. They are also all command-line tools that can be automated easily. So you have nothing to lose by running all your images through those tools before you FTP them to your web server, you can only win.</p>
<p>And you can always try the <a rel="nofollow" target="_blank" href="http://smush.it">smush.it</a> tool, just to get an idea of how much you can potentially save.</p>]]></content:encoded>
      </item>
      <item>
         <title>Image Optimization Part 2: Selecting the Right File Format</title>
         <link>http://www.yuiblog.com/blog/2008/11/04/imageopt-2/</link>
         <description>About the Author: Stoyan Stefanov is a Yahoo! web developer working for the Exceptional Performance team and leading the development of the YSlow performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called Object-Oriented JavaScript. This is part 2 in an ongoing series. You can read the other parts [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/11/04/imageopt-2/</guid>
         <pubDate>Tue, 04 Nov 2008 09:16:42 -0800</pubDate>
         <content:encoded><![CDATA[<div class="interview">
<div class="intro">
<p><img src="http://yuiblog.com/assets/stoyan.jpg" alt="Stoyan Stefanov." align="right" hspace="10" vspace="5"><em><strong>About the Author:</strong><a rel="nofollow" target="_blank" href="http://www.phpied.com"> Stoyan Stefanov</a> is a Yahoo! web developer working for the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Exceptional Performance</a> team and leading the development of the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yslow/">YSlow</a> performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called <a rel="nofollow" target="_blank" href="http://www.packtpub.com/object-oriented-javascript-applications-libraries/book">Object-Oriented JavaScript</a>.</em></p>
</div>
</div>
<p><em>This is part 2 in an ongoing series. You can read the other parts here:</em></p>
<ul>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/10/29/imageopt-1/">Image Optimization Part 1: The Importance of Images</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/14/imageopt-3/">Image Optimization Part 3: Four Steps to File Size Reduction</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/12/05/imageopt-4/">Image Optimization Part 4: Progressive JPEG…Hot or Not?</a></li>
</ul>
<p>This second installment of the image optimization series talks about file formats and how to chose the right one for the job. We&#8217;ll briefly discuss the popular GIF and JPEG formats and then move on to highlighting the rock star, PNG, hopefully helping correct some misconceptions about it.</p>
<h3>GIF</h3>
<p>GIF is a palette (also called &#8220;indexed&#8221;) type of image. It contains a palette of indexed colors, up to 256, and for every pixel of the image there is a corresponding color index. The format is no longer subject to patent issues, so you can create GIFs without the risk of going to jail. (For more on the history of the GIF format, <a rel="nofollow" target="_blank" href="http://www.cloanto.com/users/mcb/19950127giflzw.html">click here</a>.)</p>
<p>GIF is a <em>non-lossy</em> format, which means that when you modify the image and save it, you don&#8217;t lose quality.</p>
<p>GIF also support animations, which, in the dark Web 1.0 ages, resulted in a plethora of blinking &#8220;new&#8221; images, rotating @ signs, birds dropping &#8230; an email, and other annoyances. In the much more civilized Web 2.0 era, we still have &#8220;loading&#8230;&#8221; animations while we wait for the results of the next Ajax request to update the page, but there are also things like the good old shiny sparkles that people like to put in their social network profiles. Nevertheless, animation support is here if you need it.</p>
<p>GIF also supports transparency, which is a sort of boolean type of transparency. A pixel in a GIF image is either fully transparent or it&#8217;s fully opaque.</p>
<h3>JPEG</h3>
<p>JPEG doesn&#8217;t have the 256 colors restriction associated with GIFs; it can contain millions of colors and it has great compression. This makes it suitable for photos and, in fact, most cameras store photos in JPEG format. It&#8217;s a <em>lossy</em> format, meaning you lose quality with every edit, so it&#8217;s best to store the intermediate results in a different format if you plan to have many edits. There are, however, some operations that can be performed losslessly, such as cropping a part of the image, rotating it or modifying meta information, such as comments stored in the image file.</p>
<p>JPEG doesn&#8217;t support transparency.</p>
<h3>PNG</h3>
<p>PNGs is a <em>non-lossy</em> format that comes in several kinds, but for practical purposes, we can think of PNGs as being of two kinds:</p>
<ol>
<li>PNG8, and</li>
<li>truecolor PNGs.</li>
</ol>
<p>PNG8 is a palette image format, just like GIF, and 8 stands for 8 bits, or 2<sup>8</sup>, or 256, the number of palette entries. The terms &#8220;PNG8&#8243;, &#8220;palette PNG&#8221; and &#8220;indexed PNG&#8221; are used interchangeably. </p>
<p>How does PNG8 compare to GIF?</p>
<ul>
<li>Pros:
<ul>
<li>it usually yields a smaller file size</li>
<li>it supports alpha (variable) transparency</li>
</ul>
</li>
<li>Cons:
<ul>
<li>no animation support</li>
</ul>
</li>
</ul>
<p>The second type of PNGs, truecolor PNGs, can have millions of colors, like JPEG. You can also sometimes come across the names PNG24 or PNG32.</p>
<p>And how does truecolor PNG compare to JPEG? On the pros side, it&#8217;s non-lossy and supports alpha transparency, but on the cons side, the file size is bigger. This makes truecolor PNG an ideal format as an intermediate between several edits of a JPEG and also in cases where every pixel matters and the file size doesn&#8217;t matter much, such as taking screeenshots for a help manual or some printed material.</p>
<h3>Internet Explorer and PNG transparency</h3>
<p>We said that both PNG types support alpha transparency, but there are some browser eccentricities that affect both types and about which you should be aware.</p>
<p>With PNG8, whenever you have semi-transparent pixels they appear as fully transparent in IE (version 6 and lower). This is not ideal but it&#8217;s still useful and is the same behavior that you get from a GIF. So by using a PNG8, in the worst case (IE &lt; 7) you get the same user experience as with a GIF, while for other browsers (Firefox, Safari, Opera) you get a better experience. Below is an example that illustrates this, note how in IE6 the semi-transparent light around the bulb is missing (source: <a rel="nofollow" target="_blank" href="http://www.sitepoint.com/blogs/2007/09/18/png8-the-clear-winner/">SitePoint</a>):</p>
<p><img src="http://yuiblog.com/assets/png8-transparency.png" alt="PNG8 alpha transparency"/></p>
<p>For truecolor PNGs, the situation is a much less attractive compromise. All the semi transparent pixels appear grey in IE prior to version 7 (source: <a rel="nofollow" target="_blank" href="http://www.w3.org/Graphics/PNG/inline-alpha.html">W3C</a>).</p>
<p><img src="http://yuiblog.com/assets/png-transparency.png" alt="transparency in truecolor PNG"/></p>
<p>IE7 introduces proper native support for alpha transparency in both PNG8 and truecolor PNGs. For earlier IE versions you need to fix the truecolor PNG transparency issue using CSS and an AlphaImageLoader filter, which we&#8217;ll discuss in more details in a follow-up article. (Spoiler alert: <em>avoid AlphaImageLoader</em>.)</p>
<h3>&#8220;All we are saying is: Give PiNG a chance!&#8221;</h3>
<p>Although PNG8 should be the preferred of the PNGs, because it&#8217;s smaller in filesize and degrades well in early IEs without special CSS filters, there are still some use cases for truecolor PNGs:</p>
<ul>
<li><strong>When the 256 colors of the PNG8 are not enough, you may need a truecolor PNG.</strong> This is a case you should try to avoid. On one hand, if you have thousands and thousands of colors, this starts to look like a case where JPEG will be better suited and will give better compression. On the other hand, if the colors are around a thousand or so, you may try to convert this image to a PNG8 and see if it looks acceptable. Very often, the human eye is not sensitive enough to tell the difference between 200 and 1000 colors. That depends on the image, of course; often you can safely remove 1000 colors, but sometimes removing even 2 colors results in an unacceptable image. In any event, try your potential truecolor PNG candidate as PNG8 and as JPEG and see if you like the result in terms of quality and file size.</li>
<li><strong>When most of the image is semi-transparent.</strong> If only a small part of the image is semi-transparent, like around rounded corners, the GIF-like degradation of PNG8 is often OK. But if most of the image is translucent (think a PLAY button over a video thumbnail), you might not have a choice but to use the AlphaImageLoader hack.</li>
</ul>
<p>At the end, let&#8217;s summarize what was discussed in this article highlighting that:</p>
<ul>
<li>JPEG is the format for photos.</li>
<li>GIF is the format for animations.</li>
<li>PNG8 is the format for everything else &mdash; icons, buttons, backgrounds, graphs&#8230;you name it.</li>
</ul>]]></content:encoded>
      </item>
      <item>
         <title>Image Optimization Part 1: The Importance of Images</title>
         <link>http://www.yuiblog.com/blog/2008/10/29/imageopt-1/</link>
         <description>About the Author: Stoyan Stefanov is a Yahoo! web developer working for the Exceptional Performance team and leading the development of the YSlow performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called Object-Oriented JavaScript. This is part 1 in an ongoing series. You can read the other parts [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/10/29/imageopt-1/</guid>
         <pubDate>Wed, 29 Oct 2008 13:28:35 -0700</pubDate>
         <content:encoded><![CDATA[<div class="interview">
<div class="intro">
<p><img src="http://yuiblog.com/assets/stoyan.jpg" alt="Stoyan Stefanov." align="right" hspace="10" vspace="5"><em><strong>About the Author:</strong><a rel="nofollow" target="_blank" href="http://www.phpied.com"> Stoyan Stefanov</a> is a Yahoo! web developer working for the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Exceptional Performance</a> team and leading the development of the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yslow/">YSlow</a> performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called <a rel="nofollow" target="_blank" href="http://www.packtpub.com/object-oriented-javascript-applications-libraries/book">Object-Oriented JavaScript</a>.</em></p>
</div>
</div>
<p><em>This is part 1 in an ongoing series. You can read the other parts here:</em></p>
<ul>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/04/imageopt-2/">Image Optimization Part 2: Selecting the Right File Format</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/11/14/imageopt-3/">Image Optimization Part 3: Four Steps to File Size Reduction</a></li>
<li><a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/12/05/imageopt-4/">Image Optimization Part 4: Progressive JPEG…Hot or Not?</a></li>
</ul>
<p>This is the first in a series of posts about image optimization. In this series, I&#8217;ll explore how images affect web site performance and what can you do to your images in order to improve page loading times. (I won&#8217;t say how many posts in this series, so that I can claim later that I underpromised and overdelivered&#8230;).</p>
<p>When you think about improving page response time, one of the first obvious things to think about is the page weight. It&#8217;s obvious that, all things being equal, the heavier a page is the slower it will be. If we take this to the extreme, we can say that the fastest page you can possibly have is the blank page. Once you start adding stuff to the blank page, you&#8217;re only making it slower. </p>
<p>On a more serious note, it really is up to you how much content you want to put on a page, so let&#8217;s focus on what comes next. After you&#8217;ve settled on the content, it&#8217;s your job to make sure the content and components are as small as possible. Following our <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/rules.html">Yahoo! performance best practices</a>, you should make sure that all plain text components (HTML, XML, CSS, JavaScript&#8230;) are sent compressed over the wire and that you minify CSS and JavaScript. </p>
<p>But what about the images, how can you speed them up without sacrificing quality and looks? But first, does it really matter?</p>
<h3>How important are the images?</h3>
<p>Before we start, let&#8217;s see if we should even bother with images. Lately we&#8217;ve been witnessing the rise of rich internet applications with lots of JavaScript &mdash; by &#8220;lots&#8221; meaning sometimes 300K or more worth of JavaScript code. In other cases, especially in advertising, Flash seems to be the weapon of choice. So, on average, how much of the page weight is images. It&#8217;s easy to answer this question by just looking at <a rel="nofollow" target="_blank" href="http://www.alexa.com/site/ds/top_sites">Alexa&#8217;s top 10 websites</a> in the world (as of October 2008) and use <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yslow/">YSlow</a> to check what percent of the total page weight is images. The results are given below.</p>
<table border="1" id="imagekweight" width="350">
<caption>Percentage of page weight that goes to images, average 46.6%</caption>
<tbody>
<tr>
<td>1</td>
<td>Yahoo!</td>
<td>39%</td>
</tr>
<tr>
<td>2</td>
<td>Google</td>
<td>75%</td>
</tr>
<tr>
<td>3</td>
<td>YouTube</td>
<td>37%</td>
</tr>
<tr>
<td>4</td>
<td>Live.com</td>
<td>94%</td>
</tr>
<tr>
<td>5</td>
<td>Facebook</td>
<td>39%</td>
</tr>
<tr>
<td>6</td>
<td>MSN</td>
<td>59%</td>
</tr>
<tr>
<td>7</td>
<td>MySpace</td>
<td>36%</td>
</tr>
<tr>
<td>8</td>
<td>Wikipedia</td>
<td>34%</td>
</tr>
<tr>
<td>9</td>
<td>Blogger</td>
<td>28%</td>
</tr>
<tr>
<td>10</td>
<td>Yahoo! JP</td>
<td>25%</td>
</tr>
</tbody>
</table>
<style type="text/css">#chart {width:530px;height:350px;}</style>
<div id="chart">
</div>
<p><br />
 </p> 
<p><br />
 </p> 
<p>On average, <strong>46.6%</strong> of the page weight for these popular sites consists of images, included either inline with <code>&lt;img&gt;</code> tags or via CSS stylesheets. Other studies show that this percent can be even higher, depending on the cross section of sites you examine. The exact number is not important, because every site is unique and different from the average; for example <a rel="nofollow" target="_blank" href="http://amazon.com/">Amazon&#8217;s</a> home page was made of 75% images at the time of the experiment.</p>
<p>This is a massive percentage and it tells us one thing: There&#8217;s huge potential to improve the performance of websites if we can improve the way we handle the image payload. By focusing on images you can make a difference and delight your site visitors with a faster and more pleasant experience.</p>
<h3>To be continued&#8230;</h3>
<p>Over the course of the following weeks, we&#8217;ll be publishing more about image optimization. The topics for discussion include:</p>
<ul>
<li>different image formats and how to pick the right one</li>
<li>ways to put your images on a diet without compromising quality</li>
<li>optimizing generated images</li>
<li>the effect of using <code>AlphaImageLoader</code></li>
<li>favicons</li>
<li>CSS sprites</li>
<li>serving images faster</li>
</ul>
<p>The series of posts will not require Photoshop or other designers&#8217; domain-specific knowledge, so it should be pretty easy for anyone to learn and apply these techniques. More to come soon&#8230;</p>]]></content:encoded>
      </item>
      <item>
         <title>Smushit.com - optimizing images has just become really easy</title>
         <link>http://developer.yahoo.net/blog/archives/2008/09/smushitcom_opti.html</link>
         <description>&lt;p&gt;Nicole Sullivan and Stoyan Stefanov are dedicated to making the web a faster place. As integral parts of the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/&quot;&gt;Exceptional Performance Team&lt;/a&gt; they already shared a lot of crucial information of how to make your web sites faster. &lt;/p&gt; &lt;p&gt;One thing they've been pondering a lot about lately is image optimization for file size. Image editing tools come with all kind of great ways to optimize images for visual quality and file size, but when you look at the image in a text or hex editor you'll find that there is a lot of extra information in the file, for example the name of the editing suite, dates when the picture was created and lots more.&lt;/p&gt; &lt;p&gt;There are a lot of tools that remove this information safely and get the most out of the images without having an effect on their visual quality. The catch is that there are a lot of tools for a lot of image formats, all of them on the command line.&lt;/p&gt; &lt;p&gt;So Nicole and Stefan took their research findings, fired up their code editors and built a web app that does all the optimization for you:&lt;/p&gt; &lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://smushit.com&quot;&gt;&lt;img alt=&quot;Smushit Screenshot&quot; width=&quot;450&quot; height=&quot;323&quot; style=&quot;border:1px solid #ccc;padding:5px;margin:10px auto;display:block;&quot;/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://smushit.com&quot;&gt;Smushit.com&lt;/a&gt; allows you to upload some files or give it a URL. The tool then takes the images, optimizes them and tells you how many bytes you can save. You then get a zip of all the images for download and can replace them on your site.&lt;/p&gt; &lt;p&gt;Here's a video of Stoyan and Nicole presenting Smushit.com at The Ajax Experience in Boston (sorry about the audio):&lt;/p&gt; &lt;p&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://blip.tv/play/AdCdYQA&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;500&quot; height=&quot;410&quot;&gt;&lt;/iframe&gt;&lt;/p&gt; &lt;p&gt;Chris Heilmann&lt;br /&gt;
Yahoo Developer Network&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/09/smushitcom_opti.html</guid>
         <pubDate>Tue, 30 Sep 2008 09:25:02 -0700</pubDate>
      </item>
      <item>
         <title>Non-blocking JavaScript Downloads</title>
         <link>http://www.yuiblog.com/blog/2008/07/22/non-blocking-scripts/</link>
         <description>About the Author: Stoyan Stefanov is a Yahoo! web developer working for the Exceptional Performance team and leading the development of the YSlow performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called Object-Oriented JavaScript. External JavaScript files block downloads and hurt your page performance, but there is an [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/07/22/non-blocking-scripts/</guid>
         <pubDate>Tue, 22 Jul 2008 11:41:39 -0700</pubDate>
         <content:encoded><![CDATA[<div class="interview">
<div class="intro">
<p><img src="http://yuiblog.com/assets/stoyan.jpg" alt="Stoyan Stefanov." align="right" hspace="10" vspace="5"><em><strong>About the Author:</strong><a rel="nofollow" target="_blank" href="http://www.phpied.com"> Stoyan Stefanov</a> is a Yahoo! web developer working for the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Exceptional Performance</a> team and leading the development of the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yslow/">YSlow</a> performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called <a rel="nofollow" target="_blank" href="http://www.packtpub.com/object-oriented-javascript-applications-libraries/book">Object-Oriented JavaScript</a>.</em></p>
</div>
</div>
<p>External JavaScript files block downloads and hurt your page performance, but there is an easy way to work around this problem: use dynamic scripts tags and load scripts in parallel, improving the page loading speed and the user experience.</p>
<h2>The problem: scripts block downloads</h2>
<p>Let&#8217;s first take a look at what the problem is with the script downloads. The thing is that before fully downloading and parsing a script, the browser can&#8217;t tell what&#8217;s in it. It may contain <code>document.write()</code> calls which modify the DOM tree or it may even contain <code>location.href</code> and send the user to a whole new page. If that happens, any components downloaded from the previous page may never be needed. In order to avoid potentially useless downloads, browsers first download, parse and execute each script before moving on with the queue of other components waiting to be downloaded. As a result, any script on your page blocks the download process and that has a negative impact on your page loading speed.</p>
<p>Here&#8217;s how the timeline looks like when downloading a slow JavaScript file (exaggerated to take 1 second). The script download (the third row in the image) blocks the two-by-two parallel downloads of the images that follow after the script:</p>
<p><img src="http://yuiblog.com/assets/non-block-yui/1.png" alt="Timeline - Blocking behavior of JavaScript files" width="325" height="223"/></p>
<p><a rel="nofollow" target="_blank" href="http://yuiblog.com/assets/non-block-yui/before.html">Here&#8217;s the example</a> to test yourself.</p>
<h2>Problem 2: number of downloads per hostname</h2>
<p>Another thing to note in the timeline above is how the images following the script are downloaded two-by-two. This is because of the restriction of how many components can be downloaded in parallel. In IE &lt;= 7 and Firefox 2, it&#8217;s two components at a time (following the HTTP 1.1 specs), but both IE8 and FF3 increase the default to 6.</p>
<p>You can work around this limitation by using multiple domains to host your components, because the restriction is two components <em>per hostname</em>. For more information of this topic check the article &#8220;<a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2007/04/11/performance-research-part-4/">Maximizing Parallel Downloads in the Carpool Lane</a>&#8221; by Tenni Theurer.</p>
<p>The important thing to note is that <em>JavaScripts block downloads across all hostnames</em>. In fact, in the example timeline above, the script is hosted on a different domain than the images, but it still blocks them.</p>
<h2>Scripts at the bottom to improve user experience</h2>
<p>As <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/rules.html">Yahoo!&#8217;s Performance rules</a> advise, you should put the scripts at the bottom of the page, towards the closing <code>&lt;/body&gt;</code> tag. This doesn&#8217;t really make the page load faster (the script still has to load), but helps with the progressive rendering of the page. The user perception is that the page is faster when they can see a visual feedback that there is progress.</p>
<h2>Non-blocking scripts</h2>
<p>It turns out that there is an easy solution to the download blocking problem: include scripts dynamically via DOM methods. How do you do that? Simply create a new <code>&lt;script&gt;</code> element and append it to the <code>&lt;head&gt;</code>:</p>
<pre>
var js = document.createElement('script');
js.src = 'myscript.js';
var head = document.getElementsByTagName('head')[0];
head.appendChild(js);
</pre>
<p>Here&#8217;s the same test from above, modified to use the script node technique. Note that the third row in the image takes just as long to download, but the other resources on the page are loading simultaneously:</p>
<p><img src="http://yuiblog.com/assets/non-block-yui/2.png" alt="Non-blocking JavaScript timeline" width="325" height="206"/></p>
<p><a rel="nofollow" target="_blank" href="http://yuiblog.com/assets/non-block-yui/after.html">Test example</a></p>
<p>As you can see the script file no longer blocks the downloads and the browser starts fetching the other components in parallel. And the overall response time is cut in half.</p>
<h2>Dependencies</h2>
<p>A problem with including scripts dynamically would be satisfying the dependencies. Imagine you&#8217;re downloading 3 scripts and <code>three.js</code> requires a function from <code>one.js</code>. How do you make sure this works?</p>
<p>Well, the simplest thing is to have only one file, this way not only avoiding the problem, but also improving performance by minimizing the number of HTTP requests (<a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/rules.html#num_http">performance rule #1</a>).</p>
<p>If you do need several files though, you can attach a listener to the script&#8217;s <code>onload</code> event (this will work in Firefox) and the <code>onreadystatechange</code> event (this will work in IE). Here&#8217;s a <a rel="nofollow" target="_blank" href="http://www.phpied.com/javascript-include-ready-onload/">blog post</a> that shows you how to do this. To be fully cross-browser compliant, you can do something else instead: just include a variable at the bottom of every script, as to signal &#8220;I&#8217;m ready&#8221;. This variable may very well be an array with elements for every script already included.</p>
<h2>Using YUI Get utility</h2>
<p>The <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/get/">YUI Get Utility</a> makes it easy for you to use script includes. For example if you want to load 3 files, <code>one.js</code>, <code>two.js</code> and <code>three.js</code>, you can simply do:</p>
<pre>
var urls = ['one.js', 'two.js', 'three.js'];
YAHOO.util.Get.script(urls);
</pre>
<p>YUI Get also helps you with satisfying dependencies, by loading the scripts in order and also by letting you pass an <code>onSuccess</code> callback function which is executed when the last script is done loading. Similarly, you can pass an <code>onFailure</code> function to handle cases where scripts fail to load.</p>
<pre>
var myHandler = { onSuccess: function(){ alert(':))'); }, onFailure: function(){ alert(':(('); }
}; var urls = ['1.js', '2.js', '3.js'];
YAHOO.util.Get.script(urls, myHandler);
</pre>
<p>Again, note that YUI Get will request the scripts in sequence, one after the other. This way you don&#8217;t download all the scripts in parallel, but still, the good part is that the scripts are not blocking the rest of the images and the other components on the page. <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/examples/get/get-script-basic.html">Here&#8217;s a good example and tutorial on using YUI Get to load scripts</a>.</p>
<p>YUI Get can also include stylesheets dynamically through the method<br />
<code>YAHOO.util.Get.css()</code> [<a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/examples/get/get-css-basic.html">example</a>].</p>
<p>Which brings us to the next question:</p>
<h2>And what about stylesheets?</h2>
<p>Stylesheets don&#8217;t block downloads in IE, but they do in Firefox. Applying the same technique of dynamic inserts solves the problem. You can create dynamic link tags like this:</p>
<pre>
var h = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.href = 'mycss.css';
link.type = 'text/css';
link.rel = 'stylesheet';
h.appendChild(link);
</pre>
<p>This will improve the loading time in Firefox significantly, while not affecting the loading time in IE.</p>
<p>Another positive side effect of the dynamic stylesheets (in FF) is that it helps with the progressive rendering. Usually both browsers will wait and show blank screen until the very last piece of stylesheet information is downloaded, and only then they&#8217;ll start rendering. This behavior saves them the potential work of re-rendering when new stylesheet rules come down the wire. With dynamic <code>&lt;link&gt;</code>s this is not happening in Firefox, it will render without waiting for all the styles and then re-render once they arrive. IE will behave as usual and wait.</p>
<p>But before you go ahead and implement dynamic <code>&lt;link&gt;</code> tags, consider the violation of the rule of separation of concerns: your page <em>formatting</em> (CSS) will be dependent on <em>behavior</em> (JS). In addition, this problem is going to be addressed in future Firefox versions.</p>
<h2>Other ways?</h2>
<p>There are other ways to achieve the non-blocking scripts behavior, but they all have their drawbacks.</p>
<table border="1">
<tr>
<th>Method</th>
<th>Drawback</th>
</tr>
<tr>
<td>Using <code>defer</code> attribute of the <code>script</code> tag</td>
<td>IE-only, unreliable even there</td>
</tr>
<tr>
<td>Using <code>document.write()</code> to write a script tag</td>
<td>
<ol>
<li>Non-blocking behavior is in IE-only </li>
<li><code>document.write</code> is not a recommended coding practice</li>
</ol>
</td>
</tr>
<tr>
<td><code>XMLHttpRequest</code> to get the source then execute with <code>eval()</code>.</td>
<td>
<ol>
<li>&#8220;<code>eval()</code> is evil&#8221;</li>
<li>same-domain policy restriction</li>
</ol>
</td>
</tr>
<tr>
<td>XHR request to get the source, create a new script tag and set its content</td>
<td>
<ol>
<li>more complex</li>
<li>same-domain policy</li>
</ol>
</td>
</tr>
<tr>
<td>Load script in an iframe</td>
<td>
<ol>
<li>complex</li>
<li>iframe overhead</li>
<li>same-domain policy</li>
</ol>
</td>
</tr>
</table>
<h2>Future</h2>
<p>Safari and IE8 are already changing the way scripts are getting loaded. Their idea is to download the scripts in parallel, but execute them in the sequence they&#8217;re found on the page. It&#8217;s likely that one day this blocking problem will become negligible, because only a few users will be using IE7 or lower and FF3 or lower. Until then, a dynamic script tag is an easy way around the problem. 
<h2>Summary</h2>
<ul>
<li>Scripts block downloads in FF and IE browsers and this makes your pages load slower.</li>
<li>An easy solution is to use dynamic <code>&lt;script&gt;</code> tags and prevent blocking.</li>
<li><a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/get/">YUI Get Utility</a> makes it easier to do script and style includes and manage dependencies.</li>
<li>You can use dynamic <code>&lt;link&gt;</code> tags too, but consider the separation of concerns first.</li>
</ul>]]></content:encoded>
      </item>
      <item>
         <title>Performance Research, Part 6: Less is More — Serving Files Faster by Combining Them</title>
         <link>http://www.yuiblog.com/blog/2008/07/21/performance-research-part-6/</link>
         <description>This article is the sixth in a series of YUIBlog articles describing experiments conducted to learn more about optimizing web page performance (Part 1, Part 2, Part 3, Part 4, Part 5). In Performance Research Part 1, we discussed how reducing the number of HTTP requests has the biggest impact on improving the response time and [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/07/21/performance-research-part-6/</guid>
         <pubDate>Mon, 21 Jul 2008 09:03:15 -0700</pubDate>
         <content:encoded><![CDATA[<div class="interview">
<div class="intro">
<p><em>This article is the sixth in a series of YUIBlog articles describing experiments conducted to learn more about optimizing web page performance (<a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2006/11/28/performance-research-part-1/">Part 1</a>, <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2007/01/04/performance-research-part-2/">Part 2</a>, <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2007/03/01/performance-research-part-3/">Part 3</a>, <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2007/04/11/performance-research-part-4/">Part 4</a>, <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/02/06/iphone-cacheability/">Part 5</a>).</em></p>
</div>
</div>
<p>In <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2006/11/28/performance-research-part-1/">Performance Research Part 1</a>, we discussed how reducing the number of HTTP requests has the biggest impact on improving the response time and is often the easiest performance improvement to make. One technique without having to simplify the page design is to combine multiple scripts into a single script, and similarly combine multiple stylesheets into a single stylesheet.</p>
<blockquote><p>Combining multiple files reduces the extra bytes from HTTP headers as well as potential transfer latency caused by TCP slow starts, packet losses, etc.</p></blockquote>
<p>Figure 1 shows a graphical view of how time is spent loading a page with six separate scripts. Notice that for every file, the browser makes a separate HTTP request to retrieve the file. The gaps between the scripts indicate the time the browser takes to parse and render each script. Figure 2 shows the how time is spent loading a page with the same six scripts combined into a single script.</p>
<div class="figure">
<h4><strong>Figure 1.</strong> Loading a page with six separate scripts</h4>
<p><img src="http://yuiblog.com/assets/six-separate-scripts.gif" alt="Figure 1. Loading a page with six separate scripts" width="487" height="114" id="six-separate-scripts"/></p>
</div>
<div class="figure">
<h4><strong>Figure 2.</strong> Loading a page with one combined script</h4>
<p><img src="http://yuiblog.com/assets/one-single-script.gif" alt="Figure 1. Loading a page with one combined script" width="484" height="63" id="six-separate-scripts"/></p>
</div>
<p>Combining JavaScript and CSS files as part of the development process can be burdensome. It usually makes sense during development to organize the code into logical modules as separate files. Typically, combining those separate files before product release is either a manual process or part of a build process. Every time one of the individual files is changed, the larger file needs to be re-combined and re-pushed. The cost of this across an organization as large as Yahoo! is significant.</p>
<h3>Serve Files Faster using Combo Handler</h3>
<p>Combo Handler, built in collaboration by <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Yahoo!&#8217;s Exceptional Performance team</a> and the groups that support our CDN, is one solution to combine multiple files into a single, larger file.</p>
<p>Combo Handler provides a way to allow developers to maintain the logical organization of their code in separate files, while achieving the advantages of combining those into a single file as part of the final user experience. It alleviates the need for the time-consuming re-build and re-push processes. In addition, Combo Handler integrates seamlessly into a content delivery network, taking full advantage of the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/rules.html#cdn">benefits of a CDN</a> while reducing the drawbacks of dynamically combining separate files.</p>
<p>We&#8217;ve been using this service across many Yahoo! properties for some time now to help improve end users&#8217; response times. Thanks to the YUI team, it is <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/07/16/combohandler/">now available</a> to all of you that are using the Yahoo!-hosted YUI JavaScript files. (Note: Combo-handling of CSS files is not supported at this time.) <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/articles/hosting/#configure">Head over to the YUI Configurator</a> to generate combo-ready filepaths customized for your specific YUI implementation.</p>
<h3>Combo Handler Best Practices</h3>
<p>When using Combo Handler to combine files, pay special attention to the order in which the files are specified. Not only could there be file dependencies, browsers will only use the cached version of a file if the filename extracted from the URL is identical. For example, suppose the following smaller files (<code>dom.js</code> and <code>event.js</code>) are combined into a single larger file using Combo Handler:</p>
<pre> http://yui.yahooapis.com/combo?event.js&#038;dom.js http://yui.yahooapis.com/combo?dom.js&#038;event.js
</pre>
<p>In the example above, the browser will download and cache both files separately because the filenames are actually different.</p>
<p>Also, you may not always want to combine all files into one single file. Suppose you have one or more scripts that are shared across multiple pages in your site in addition to scripts that are only used on specific pages. By combining everything into one large file and using this file across your entire site, some pages will spend time downloading more than it really needs. Instead, take a look at different types of combinations. You might combine the scripts that are used in every page across your site into one script. Then for each page or group of pages, combine common scripts into another separate script.</p>
<h3>Yahoo! HotJobs Combines and Reduces Response Time by 8%!</h3>
<p>The <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Exceptional Performance</a> team ran an experiment with <a rel="nofollow" target="_blank" href="http://hotjobs.yahoo.com">Yahoo! HotJobs</a> to determine the response time savings our users would benefit from by combining multiple files into a single file. Two real user test buckets were created for this experiment. In one bucket, users visited a page with six JavaScript files left uncombined. In the second bucket, users visited the same page with the six JavaScript files combined into one single file. </p>
<blockquote><p>Combining six JavaScript files into one single JavaScript file improved performance by almost 8% on average for Yahoo! HotJobs&#8217; users on broadband bandwidth speeds and 5% for users on lan. No design or feature changes required!</p></blockquote>
<p>Keep in mind that the page we tested was already highly optimized for performance and had a <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yslow">YSlow</a> &#8220;A&#8221; grade. The response time savings depend on a number of factors including number of files combined, browser caching patterns, etc. This experiment supported our previous research, which indicated that reducing HTTP requests is an effective way to improve response times for our end users.</p>
<h3>Takeaways</h3>
<p>Improve response times by combining multiple JavaScript and CSS files. Yahoo!&#8217;s <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2008/07/16/combohandler/">Combo Handler</a> Service is one solution that provides a way to make fewer HTTP requests for Yahoo!-hosted JavaScript files, and also leverages the benefits of a Content Delivery Network.</p>
<ul>
<li>Combine scripts and stylesheets to reduce HTTP requests.</li>
<li>Look at different types of file combinations.</li>
<li>Avoid users from having to download more than they really need.</li>
<li>Pay special attention to the order in which files are combined.</li>
</ul>]]></content:encoded>
         <category>Performance</category>
      </item>
      <item>
         <title>Combo Handler Service Available for Yahoo-hosted JS</title>
         <link>http://www.yuiblog.com/blog/2008/07/16/combohandler/</link>
         <description>We&amp;#8217;ve been talking for a long time at Yahoo about the importance of minimizing HTTP requests to improve performance. One important technique for YUI users has long been to use the pre-built &amp;#34;rollup&amp;#34; files (like yahoo-dom-event.js, which combines the YUI Core in a single minified HTTP request) and to create custom rollups that aggregate all [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/07/16/combohandler/</guid>
         <pubDate>Wed, 16 Jul 2008 12:16:39 -0700</pubDate>
         <content:encoded><![CDATA[<p>We&#8217;ve been talking for a long time at Yahoo about <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2006/11/28/performance-research-part-1">the importance of minimizing HTTP requests to improve performance</a>. One important technique for YUI users has long been to use the pre-built "rollup" files (like <code><a rel="nofollow" target="_blank" href="http://yui.yahooapis.com/2.5.2/build/yahoo-dom-event/yahoo-dom-event.js">yahoo-dom-event.js</a></code>, which combines the YUI Core in a single minified HTTP request) and to create custom rollups that aggregate all of your YUI JS content in a single file. You&#8217;ll notice that we do a lot of this on our core Yahoo properties. For example, if you go to <a rel="nofollow" target="_blank" href="http://sports.yahoo.com/sc">check on the Tour de France on Yahoo! Sports</a>, you&#8217;ll find that numerous YUI components are aggregated with custom Sports-specific JS resources in a single HTTP request (<a rel="nofollow" target="_blank" href="http://l.yimg.com/img.sports.yahoo.com/static/versioned_asset/v3/minify/js/editorial/js/yui/yuiloader-beta-min_2.5.1.r1.4.js;editorial/js/yui/dom-min_2.5.1.r1.4.js;editorial/js/yui/event-min_2.5.1.r1.4.js;editorial/js/yui/connection-min_2.5.1.r1.4.js;editorial/js/yui/animation-min_2.5.1.r1.4.js;editorial/js/yui/json-min.r1.3.js;editorial/js/constants.r1.15.js;editorial/js/globalsearch.r1.3.js;editorial/js/sports.r1.16.js;editorial/js/tabs.r1.20.js;editorial/js/cookie.r1.3.js;editorial/js/home_modules.r1.4.js;editorial/js/ticker.r1.3.js;editorial/js/window.r1.16.js;editorial/js/scorethin.r1.15.js;editorial/js/manager.r1.3.js;editorial/js/carousel.r1.11.js;editorial/js/player_search.r1.3.js;editorial/js/countdown.r1.5.js;editorial/js/oly.r1.13.js;editorial/js/mlbtv.r1.5.js;editorial/js/flyout_test.r1.20.js;editorial/js/ult.r1.3.js">here&#8217;s the aggregate file</a>).</p>
<p>Thanks to the hard work of the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/performance/">Yahoo Exceptional Performance team</a> and the groups that support our CDN, we&#8217;re now able to offer ad-hoc file aggregation &mdash; "combo handling" &mdash; to file served from <code>yui.yahooapis.com</code>. So, a request for the full <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/examples/editor/cal_editor.html">YUI Rich Text Editor</a>, which previously looked like this&#8230;</p>
<pre>&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/yahoo-dom-event/yahoo-dom-event.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/container/container_core-min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/menu/menu-min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/element/element-beta-min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/button/button-min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/editor/editor-beta-min.js"&gt;&lt;/script&gt; </pre>
<p>&#8230;can now be written this way:</p>
<pre>&lt;script type="text/javascript"
src="http://yui.yahooapis.com/combo?2.5.2/build/yahoo-dom-event/yahoo-dom-event.js&amp;
2.5.2/build/container/container_core-min.js&amp;2.5.2/build/menu/menu-min.js&amp;
2.5.2/build/element/element-beta-min.js&amp;2.5.2/build/button/button-min.js&amp;
2.5.2/build/editor/editor-beta-min.js"&gt;&lt;/script&gt;</pre>
<p>In one step, this eliminates five separate HTTP requests.</p>
<p><a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/articles/hosting/#configure"><img align="right" src="http://yuiblog.com/assets/combo.png" alt="Combo handling is built into the YUI Configurator interface." hspace="10" vspace="5"/></a> <strong>A few notes regarding combo handling on <code>yui.yahooapis.com</code></strong>:</p>
<ul>
<li>If you&#8217;re using the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/articles/hosting/#configure">YUI Configurator</a>, this option ("Combine All JS Files") is enabled by default as long as you&#8217;re using the default base path.</li>
<li>Combo-handling of YUI CSS files is not supported at this time. </li>
<li>In an upcoming release, we&#8217;ll provide built-in combo-handling support in <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/yuiloader/">YUI Loader</a> and restructure filepaths in YUI&#8217;s CSS resources to make them combinable as well.</li>
<li>YUI Configurator will always output the current version of the library, but all YUI JS files from 2.2.0 onward are present on <code>yui.yahooapis.com</code> and can be combined using the same combo-handling syntax.</li>
</ul>
<p>We hope combo handling provides a easy performance win for those of you letting Yahoo serve your YUI files. Discussion of combo handling and all YUI issues takes place <a rel="nofollow" target="_blank" href="http://tech.groups.yahoo.com/group/ydn-javascript/">in our community forum</a> &mdash; please join us there and let us know how this works for you.</p>]]></content:encoded>
      </item>
      <item>
         <title>Twitter, SearchMonkey, and Caching</title>
         <link>http://developer.yahoo.net/blog/archives/2008/07/twitter_searchm_1.html</link>
         <description>&lt;p&gt;Intrepid coder &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://thecodemill.biz/&quot;&gt;Bart Teeuwisse&lt;/a&gt; has written up an &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.360.yahoo.com/blog-nmtCUeQzerRT5iQg31WF0v9VWB1iCQ--?cq=1&amp;p=74&quot;&gt;excellent technical account of creating &quot;Tweet&quot;&lt;/a&gt;, a beautifully designed SearchMonkey app for &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://twitter.com&quot;&gt;Twitter&lt;/a&gt;. From a performance standpoint, writing a Twitter SearchMonkey app is particularly challenging, as &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.360.yahoo.com/blog-nmtCUeQzerRT5iQg31WF0v9VWB1iCQ--?cq=1&amp;p=74&quot;&gt;Bart explains&lt;/a&gt;:&lt;/p&gt; &lt;blockquote&gt;
&lt;p&gt;It turns out that execution speed of a SearchMonkey is key. To make the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gallery.search.yahoo.com&quot;&gt;SearchMonkey Gallery&lt;/a&gt; a presentation monkey such as Tweet has to complete within a fraction of a second. Any call to fetch 3rd party takes too long to satisfy this requirement. Certainly calling Twitter's API whose fluctuating response times are all over the map.&lt;/p&gt; &lt;p&gt;Secondly, Twitter's profile API call takes a user ID, which first has to be extracted from Yahoo!'s indexed data. An additional data SearchMonkey can do that and whose output is the input to Tweet's profile feching data monkey. However, this chaining of data monkeys makes Tweet only slower.&lt;/p&gt;
&lt;/blockquote&gt; &lt;p&gt;Fortunately, Bart hit on a really clever solution: a mashup with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/appengine/&quot;&gt;Google App Engine&lt;/a&gt;, which acts as a simple proxy cache for Twitter data, which SearchMonkey can then consume. The result (after &lt;i&gt;also&lt;/i&gt; adding Bart's own &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gallery.search.yahoo.com/application?smid=vuA&quot;&gt;FriendNet infobar app&lt;/a&gt;):&lt;/p&gt; &lt;p&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2380/2655670495_747f6bbd12_o_d.png&quot; alt=&quot;Example Twitter application from Bart Teeuwisse; shows profile picture, tweets, followers, and more.&quot;/&gt;&lt;/p&gt; &lt;p&gt;Not only is the caching a nifty way to smooth out the API response times, but it also helps reduce the number of (rate-limited) API calls required. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.360.yahoo.com/blog-nmtCUeQzerRT5iQg31WF0v9VWB1iCQ--?cq=1&amp;p=74&quot;&gt;Read more about it at Bart's place&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/07/twitter_searchm_1.html</guid>
         <pubDate>Thu, 10 Jul 2008 12:17:44 -0700</pubDate>
         <category>SearchMonkey</category>
      </item>
      <item>
         <title>So many performance geeks all in one place!</title>
         <link>http://developer.yahoo.net/blog/archives/2008/06/performance_geeks_velocity_conference_oreilly.html</link>
         <description>&lt;h2&gt;O’Reilly’s Velocity Con, of course.&lt;/h2&gt; &lt;p&gt;&lt;img width=&quot;434&quot; height=&quot;224&quot; src=&quot;http://farm4.static.flickr.com/3149/2622054335_24b169a741.jpg&quot; alt=&quot; &quot;&gt;&lt;/p&gt; &lt;p&gt;Kai Hansen, Tony Ralph, Eric Goldsmith, and Artur Bergman during, &lt;em&gt;This is Your Page with Ads&lt;/em&gt;, a panel moderated by Steve Souders.&lt;/p&gt; &lt;p&gt;It turns out I’m not the only person who thinks micro-optimization of CSS files is cool.&amp;nbsp; I learned this lesson a year ago when I joined the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/&quot;&gt;Exceptional Performance&lt;/a&gt; team at Yahoo! and had it reinforced by the quality of both the presentations and the hallway conversations at the O’Reilly Velocity Conference last week.&lt;/p&gt; &lt;p&gt;Attending Velocity Con was fabulous.&amp;nbsp; I was especially impressed that the sessions on web performance were packed.&amp;nbsp; There were a ton of Yahoos at the conference,&amp;nbsp; Julien Lecomte from Yahoo! Search spoke about “&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://assets.en.oreilly.com/1/event/7/High%20Performance%20Ajax%20Applications%20Presentation.ppt&quot; title=&quot;ppt&quot;&gt;&lt;em&gt;High-performance Ajax Applications”&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt; &lt;blockquote&gt;“In the past few years, Ajax has become very popular because it has enabled developers to build more complex web applications. However, in the rush to push the browser to new limits, we have created a monster. “ &amp;#8211; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.julienlecomte.net/blog/&quot;&gt;Julien&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;Julien suggested several detailed strategies and patterns that developers can use to accelerate their applications. Stoyan Stefanov, the lead developer of YSlow, and my colleague in the Exceptional Performance team, spoke about &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://assets.en.oreilly.com/1/event/7/Image%20Optimization_%20How%20Many%20of%20These%207%20Mistakes%20Are%20You%20Making%20Presentation.ppt&quot; title=&quot;ppt&quot;&gt;&lt;em&gt;Image Optimization&lt;/em&gt;&lt;/a&gt;, including the 7 mistakes most sites are making.&amp;nbsp; He showed non-designers how to automate image optimization and reduce image bloat by as much as 30%. After attending the talk, Douglas Crockford shared some love.&lt;/p&gt; &lt;blockquote&gt;“It is good to be able to point with pride at something that Yahoo does that is extremely smart. The Exceptional Performance Team is one of the things that makes me proud to be at Yahoo.” &amp;#8211; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.360.yahoo.com/blog-TBPekxc1dLNy5DOloPfzVvFIVOWMB0li?p=872&quot;&gt;Doug&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;John Allspaw from Flickr joined a panel about Surviving Success by preparing to be TechCrunched, Dugg, Slashdotted, or even “Oprahed”.&amp;nbsp; He also presented &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.oreilly.com/velocity2008/public/asset/attachment/3164&quot; title=&quot;ppt&quot;&gt;&lt;em&gt;Capacity Management&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt; &lt;blockquote&gt;“Your process of capacity planning should be adaptive, adjustable, and include more than just system statistics. Measurement, architecture, and economics are all equally important to having your site perform. Becoming popular doesn’t have to mean being afraid your site will fall over from too much load.” &amp;#8211; John&lt;/blockquote&gt; &lt;p&gt;Adam Bechtel, the chief architect covering network, storage and systems infrastructure at Yahoo! presented “&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.oreilly.com/velocity2008/public/asset/attachment/3090&quot; title=&quot;ppt&quot;&gt;&lt;em&gt;Performance Plumbing”&lt;/em&gt;&lt;/a&gt;. He believes that scale provides unique opportunities to leverage the network to improve performance.&lt;/p&gt; &lt;blockquote&gt;“As your site scales, don’t overlook the performance opportunities that the plumbing creates.” &amp;#8211; Adam&lt;/blockquote&gt; &lt;p&gt;Tony Ralph who works on ad quality and performance for Yahoo! participated in a panel, &lt;em&gt;This is Your Page with Ads&lt;/em&gt;.&amp;nbsp; He made an important point that I hadn’t really thought of before. He indicated that the ad industry and engineers measure performance in very different ways; one via monetization, the other via impact on response time. &amp;nbsp;He emphaiszed how important it is for engineers to understand both points of view, so that we can effectively measure and convey the impact of end user experience on revenue. &lt;/p&gt; &lt;p&gt;Kai Hansen from Google Ireland also mentioned the need to properly advocate this point of view from within our companies so that quality metrics such as keyword relevance and performance are tied to the cost of displaying ads.&lt;/p&gt; &lt;p&gt;I look forward to Velocity Conference 2009.&amp;nbsp; I do hope that it will &lt;em&gt;focus on the front end&lt;/em&gt; with more talks about HTML, CSS, JavaScript, and Ajax.&amp;nbsp; These sessions were the most popular of the conference, and front-end performance is still in its infancy. Douglas Crockford expressed it very well.&lt;/p&gt; &lt;blockquote&gt;“By showing the browser makers how web applications actually perform, the browser makers are now able to make effective changes to the platform. As the platform evolves, we will need new rules and new tools. &lt;strong&gt;There is still much to do.&lt;/strong&gt; (Emphasis mine)” &amp;#8211; Doug&lt;/blockquote&gt; &lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.stubbornella.org/content/&quot;&gt;Nicole Sullivan&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Exceptional Performance Yahoo!&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/06/performance_geeks_velocity_conference_oreilly.html</guid>
         <pubDate>Mon, 30 Jun 2008 08:06:45 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>New YSlow with Firefox 3 support</title>
         <link>http://developer.yahoo.net/blog/archives/2008/06/new_yslow_with.html</link>
         <description>&lt;p&gt;Just in time for the Firefox 3 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.spreadfirefox.com/&quot;&gt;Download Day&lt;/a&gt; (today, June 17th), last night we released a new version of YSlow that works with Firefox 3. You can install it from the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow/&quot;&gt;YSlow page&lt;/a&gt; or the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://addons.mozilla.org/en-US/firefox/addon/5369&quot;&gt;Mozilla add-ons&lt;/a&gt; site.&lt;/p&gt; &lt;p&gt;What's new in this version:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;Firefox 3 and Firebug 1.2 beta support&lt;/li&gt; &lt;li&gt;improved and simplified check for javascript minification&lt;/li&gt; &lt;li&gt;different coloring for inline vs. external CSS and JS (&quot;All CSS&quot; and &quot;All JS&quot; features)&lt;/li&gt; &lt;li&gt;clickable list of resources as a Table of Contents (&quot;All CSS&quot; and &quot;All JS&quot; features)&lt;/li&gt; &lt;li&gt;improved colors and presentation in the &quot;legend&quot; of component pies under Stats&lt;/li&gt; &lt;li&gt;fixed a bug where the same hostname with different port number was counted as a separate DNS lookup&lt;/li&gt; &lt;li&gt;misc bugfixes and style tweaks&lt;/li&gt;
&lt;/ul&gt; &lt;p&gt;In this version, as with the previous one, we aimed at supporting all possible combinations of the different Firefox and Firebug development branches, namely the latest Firefox 2 and 3 and the latest &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://addons.mozilla.org/en-US/firefox/addon/1843&quot;&gt;Firebug&lt;/a&gt; releases: 1.05 (stable), 1.1 (beta) and 1.2 (beta).&lt;/p&gt; &lt;p&gt;Many thanks to everybody who sent kind words of encouragement and questions about the availability of this new release, sorry we didn't reply to all of you, but now your wait is over.&lt;/p&gt; &lt;p&gt;As always, your feedback is welcome and appreciated, feel free to use the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow/feedback.html&quot;&gt;contact form&lt;/a&gt; or join the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tech.groups.yahoo.com/group/exceptional-performance/&quot;&gt;exceptional-performance&lt;/a&gt; mailing list.&lt;/p&gt; &lt;p&gt;Happy download day!&lt;/p&gt; &lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.phpied.com/&quot;&gt;Stoyan Stefanov&lt;/a&gt;&lt;br /&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/&quot;&gt;Exceptional Performance&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/06/new_yslow_with.html</guid>
         <pubDate>Tue, 17 Jun 2008 15:05:32 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>YSlow 0.9.5b1 Release - Addressing Firefox and Firebug Compatibility</title>
         <link>http://developer.yahoo.net/blog/archives/2008/04/yslow_095b1_rel.html</link>
         <description>&lt;p&gt;Committed to keeping up with the latest in Firefox and Firebug development, we’re happy to announce that a new version increment of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow&quot;&gt;YSlow&lt;/a&gt; was released, mainly aiming at addressing compatibility. What’s in this release?&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt; &lt;li&gt;Firefox 3 beta 5 support&lt;br /&gt; &lt;li&gt;Support for the latest versions of the different Firebug branches&lt;br /&gt; &lt;li&gt;Pie chart representation of the components in the Stats tab&lt;br /&gt; &lt;li&gt;Improved display in the expanded CSS expressions rule report in the Performance tab&lt;br /&gt; &lt;li&gt;Support for disabled Firebug Net Panel (default behavior in Firebug 1.2)&lt;br /&gt; &lt;li&gt;Misc fixes for the reports in the Tools section&lt;br /&gt;
&lt;/ul&gt;&lt;/p&gt; &lt;p&gt;Looking at the diversity of Firefox/Firebug versions, these are the current available branches for Firefox and Firebug.&lt;/p&gt; &lt;p&gt;Firefox has two active branches:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt; &lt;li&gt;Firefox 2 - the current version is 2.0.0.14, this is the stable production version&lt;br /&gt; &lt;li&gt;Firefox 3 - the latest is 3.0. beta 5&lt;br /&gt;
&lt;/ul&gt;&lt;/p&gt; &lt;p&gt;Firebug has 3 active branches:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt; &lt;li&gt;Firebug 1 – the latest version being 1.05, this is the stable version&lt;br /&gt; &lt;li&gt;Firebug 1.1 – the latest is 1.1.0 beta 12 &lt;br /&gt; &lt;li&gt;Firebug 1.2 – the latest 1.2.0 alpha 21&lt;br /&gt;
&lt;/ul&gt;&lt;/p&gt; &lt;p&gt;Firebug 1 doesn’t work with Firefox 3, so there are a total of 5 combinations and the YSlow 0.9.5b1 has been successfully tested on all of them:&lt;/p&gt; &lt;table border=&quot;1&quot;&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td&gt;Firebug 1&lt;/td&gt; &lt;td&gt;Firebug 1.1&lt;/td&gt; &lt;td&gt;Firebug 1.2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Firefox 2&lt;/td&gt; &lt;td&gt;Yes&lt;/td&gt; &lt;td&gt;Yes&lt;/td&gt; &lt;td&gt;Yes&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Firefox 3&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;Yes&lt;/td&gt; &lt;td&gt;Yes&lt;/td&gt; &lt;/tr&gt;
&lt;/table&gt; &lt;p&gt;You can download the tool &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://addons.mozilla.org/en-US/firefox/addon/5369&quot;&gt;here&lt;/a&gt;, report bugs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow/feedback.html&quot;&gt;here&lt;/a&gt;, read the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html&quot;&gt;performance rules&lt;/a&gt;, and participate in the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tech.groups.yahoo.com/group/exceptional-performance/&quot;&gt;performance mailing list&lt;/a&gt; discussions. Also make sure you keep an eye on our performance-related postings on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.net/blog/archives/performance/&quot;&gt;YDN&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://yuiblog.com/blog/category/performance/&quot;&gt;YUI Blog&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Enjoy,&lt;/p&gt; &lt;p&gt;Yahoo! Exceptional Performance&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/04/yslow_095b1_rel.html</guid>
         <pubDate>Wed, 23 Apr 2008 11:37:20 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>New Rules for Exceptional Performance</title>
         <link>http://developer.yahoo.net/blog/archives/2008/04/new_rules_for_e.html</link>
         <description>&lt;p&gt;Initially 13, then 14, and now 34 performance best practices have been released. As promised, we've updated our &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html&quot;&gt;pages&lt;/a&gt; to include details on each of these new rules. The rules will gradually find their way into YSlow, at least those that are testable. Huge thanks goes out to all those at Yahoo! who helped identify, validate and test the new best practices, and especially to our very own Stoyan Stefanov who put it all together. Stoyan Stefanov is part of the Exceptional Performance team and also the lead developer for YSlow.&lt;/p&gt; &lt;p&gt;We hope you'll find some interesting ideas to help you accelerate the user experience on your pages today. Any comments and feedback appreciated. Let's make the web a better place!&lt;/p&gt; &lt;p&gt;Tenni Theurer&lt;br /&gt;
Yahoo! Exceptional Performance&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/04/new_rules_for_e.html</guid>
         <pubDate>Fri, 11 Apr 2008 17:44:56 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>Yahoo!'s Latest Performance Breakthroughs</title>
         <link>http://developer.yahoo.net/blog/archives/2008/03/yahoos_latest_p.html</link>
         <description>&lt;p&gt;Stoyan Stefanov made an appearance last week at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://conf.phpquebec.com/en&quot;&gt;PHP Quebec Conference&lt;/a&gt; in Montreal. His &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://conf.phpquebec.com/en/session#high_performance_web_pages&quot;&gt;session&lt;/a&gt; debuts Yahoo!’s latest research results and performance breakthroughs. He covers the existing 14 rules, plus 20 new rules for faster web pages. We’ve categorized the optimizations into: server, content, cookie, JavaScript, CSS, images, and mobile.&lt;/p&gt; &lt;p&gt;&lt;div style=&quot;width:425px;text-align:left;&quot; id=&quot;__ss_319798&quot;&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=high-performance-web-pages-20-new-best-practices-1206389190195598-3&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/iframe&gt;&lt;div style=&quot;font-size:11px;font-family:tahoma, arial;height:26px;padding-top:2px;&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.slideshare.net/?src=embed&quot;&gt;&lt;img src=&quot;http://static.slideshare.net/swf/logo_embd.png&quot; style=&quot;border:0px none;&quot; alt=&quot;SlideShare&quot;/&gt;&lt;/a&gt; | &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.slideshare.net/stoyan/high-performance-web-pages-20-new-best-practices?src=embed&quot; title=&quot;View 'High Performance Web Pages - 20 new best practices' on SlideShare&quot;&gt;View&lt;/a&gt; | &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.slideshare.net/upload?src=embed&quot;&gt;Upload your own&lt;/a&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;&lt;strong&gt;After YSlow &quot;A&quot;?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;If your page isn't getting an &quot;A&quot; in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow&quot;&gt;YSlow&lt;/a&gt;, I recommend that you tackle those recommendations first. However, if you're getting an &quot;A&quot; and looking for more ways to optimize your web pages, here are 20 new recommendations to accelerate the end-user's experience. Stay tuned, you'll be hearing more about YSlow and these rules at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.net/blog/archives/performance/&quot;&gt;Yahoo! Developer Network&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://yuiblog.com/blog/category/performance&quot;&gt;Yahoo! User Interface Blog&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;table border=&quot;0&quot; width=&quot;200px&quot;&gt; &lt;tr&gt; &lt;td&gt;1. Flush the buffer early&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[server]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2. Use GET for AJAX requests&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[server]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3. Post-load components&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[content]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4. Preload components&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[content]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;5. Reduce the number of DOM elements&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[content]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;6. Split components across domains&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[content]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;7. Minimize the number of iframes&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[content]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;8. No 404s&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[content]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;9. Reduce cookie size&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[cookie]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;10. Use cookie-free domains for components&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[cookie]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;11. Minimize DOM access&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[javascript]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12. Develop smart event handlers&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[javascript]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;13. Choose &amp;lt;link&amp;gt; over @import&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[css]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;14. Avoid filters&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[css]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;15. Optimize images&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[images]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;16. Optimize CSS sprites&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[images]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;17. Don't scale images in HTML&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[images]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;18. Make favicon.ico small and cacheable&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[images]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;19. Keep components under 25K&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[mobile]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;20. Pack components into a multipart document&lt;/td&gt; &lt;td align=&quot;right&quot;&gt;[mobile]&lt;/td&gt; &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt; &lt;p&gt;Many thanks to all the developers at Yahoo! that have directly or indirectly contributed to this list - you know who you are (see credits at the end of Stoyan's presentation). We share our findings so that others can join us in accelerating the user experience on the web.&lt;/p&gt; &lt;p&gt;Tenni Theurer&lt;br&gt;
Yahoo! Exceptional Performance&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/03/yahoos_latest_p.html</guid>
         <pubDate>Mon, 17 Mar 2008 17:02:42 -0700</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>YSlow 0.9.3 Release with Firefox 3 Support</title>
         <link>http://developer.yahoo.net/blog/archives/2008/02/yslow_093_relea.html</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow&quot;&gt;YSlow&lt;/a&gt;, the performance lint tool created by the Yahoo! Exceptional Performance team was updated to version 0.9.3. today. This minor version increment contains:&lt;br/&gt;,&lt;br/&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Firefox 3 support (up to and including 3.0b4pre) &lt;li&gt;Sortable table of page components in the Components tab &lt;li&gt;Beacons (1x1 images that are not part of the DOM) excluded from the overall score. If you want them back in the score, use &lt;code&gt;about:config&lt;/code&gt; to set the option &lt;code&gt;extensions.firebug.yslow.excludeBeaconsFromLint&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; &lt;li&gt;Minor bug fixes that caused YSlow to freeze as it peels off the page components (encountering streams, applets, empty URLs)
&lt;/ul&gt; &lt;p&gt;In the spirit of openness and our commitment to a faster experience on the web, we hope you join us in accelerating the user experience.&lt;/p&gt; &lt;p&gt;You can download the tool &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://addons.mozilla.org/en-US/firefox/addon/5369&quot;&gt;here&lt;/a&gt;, report bugs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow/feedback.html&quot;&gt;here&lt;/a&gt;, read the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html&quot;&gt;performance rules&lt;/a&gt;, and participate in the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tech.groups.yahoo.com/group/exceptional-performance/&quot;&gt;performance mailing list&lt;/a&gt; discussions. Also make sure you keep an eye on our performance-related postings on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.net/blog/archives/performance/&quot;&gt;YDN&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://yuiblog.com/blog/category/performance/&quot;&gt;YUI Blog&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/02/yslow_093_relea.html</guid>
         <pubDate>Thu, 14 Feb 2008 17:40:42 -0800</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>Helping the YUI Compressor</title>
         <link>http://www.yuiblog.com/blog/2008/02/11/helping-the-yui-compressor/</link>
         <description>Nicholas Zakas joined Yahoo! in 2006. He is the author of Professional Ajax and Professional JavaScript for Web Developers. He&amp;#8217;s a contributor to our Yahoo! Juku. His Maintainable JavaScript presentation is available on YUI Theater. Julien’s YUI Compressor is an incredibly useful tool for decreasing the size of your JavaScript files. Since it uses Rhino to [...]</description>
         <guid isPermaLink="false">http://yuiblog.com/blog/2008/02/11/helping-the-yui-compressor/</guid>
         <pubDate>Mon, 11 Feb 2008 06:01:10 -0800</pubDate>
         <content:encoded><![CDATA[<div class="interview">
<p> </p>
<div class="intro">
<p><a rel="nofollow" target="_blank" href="http://www.nczonline.net/">Nicholas Zakas</a> joined Yahoo! in 2006. He is the author of <cite><a rel="nofollow" target="_blank" href="http://www.amazon.com/Professional-Ajax-2nd-Programmer/dp/0470109491">Professional Ajax</a></cite> and <cite><a rel="nofollow" target="_blank" href="http://www.amazon.com/Professional-JavaScript-Developers-Wrox-Guides/dp/0764579088/ref=sr_1_2/103-9749654-9772648?ie=UTF8&#038;s=books&#038;qid=1180057873&#038;sr=1-2">Professional JavaScript for Web Developers</a></cite>. He&#8217;s a contributor to our <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2007/12/06/juku/">Yahoo! Juku</a>. His <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2007/05/25/video-zakas/">Maintainable JavaScript</a> presentation is available on <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/theater/">YUI Theater</a>.</p>
</div>
<p> </p>
<p>Julien’s <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a> is an incredibly useful tool for decreasing the size of your JavaScript files. Since it uses <a rel="nofollow" target="_blank" href="http://www.mozilla.org/rhino/" title="Rhino: JavaScript for Java">Rhino</a> to parse your JavaScript code, it can perform all kinds of smart operations to save bytes in a completely safe way:</p>
<ul>
<li>Replacement of local variable names with shorter (one, two, or three character) variable names.</li>
<li>Replacement of bracket notation with dot notation where possible (i.e. <code>foo["bar"]</code> becomes <code>foo.bar</code>).</li>
<li>Replacement of quoted literal property names where possible (i.e. { <code>"foo":"bar"</code> } becomes { <code>foo:"bar"</code> } ).</li>
<li>Replacement of escaped quotes in strings (i.e. <code>'aaa&#92;'bbb'</code> becomes <code>"aaa’bbb"</code>).</li>
</ul>
<p>Running your JavaScript code through YUI Compressor results in tremendous savings by default, but there are things you can do to increase the byte savings even further.</p>
<h3 id="use-constants-for-repeated-values">Use Constants for Repeated Values</h3>
<p>In my talk, <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2007/05/25/video-zakas/">Maintainable JavaScript</a>, I talk about using constants (really, just variables that you have no intention of changing) to store repeating values. The idea is that your code is more maintainable because you have a single place to change a value instead of multiple places. As it turns out, this technique also helps YUI Compressor to remove more bytes. Consider the following function:</p>
<pre><code>function toggle(element){ if (YAHOO.util.Dom.hasClass(element, "selected")){ YAHOO.util.Dom.removeClass(element, "selected"); } else { YAHOO.util.Dom.addClass(element, "selected"); }
}</code></pre>
<p>This simple function is designed to toggle the “<var>selected</var>” class on a given element. If the element has the class, then it’s removed; if the element doesn’t have the class, it’s added. As a result, the string “<var>selected</var>” appears three times in the function. The function takes 212 bytes (including white space). When compressed, the resulting code is as follows:</p>
<pre><code>function toggle(A){if(YAHOO.util.Dom.hasClass(A,"selected")){YAHOO.util.Dom.removeClass(A,"selected")}else{YAHOO.util.Dom.addClass(A,"selected")}}
</code></pre>
<p>This code weighs in at 146 bytes (a savings of 30%), but you can see that the string “<var>selected</var>” still appears three times. Moving the repeated value into a variable makes the code more maintainable and allows YUI Compressor to remove extra space. Here’s the rewritten function:</p>
<pre><code>function toggle(element){ var className = "selected"; if (YAHOO.util.Dom.hasClass(element, className)){ YAHOO.util.Dom.removeClass(element, className); } else { YAHOO.util.Dom.addClass(element, className); }
}</code></pre>
<p>This code is slightly larger than the original (241 bytes versus 212 bytes), but compresses down to the following:</p>
<pre><code>function toggle(A){var B="selected";if(YAHOO.util.Dom.hasClass(A,B)){YAHOO.util.Dom.removeClass(A,B)}else{YAHOO.util.Dom.addClass(A,B)}}
</code></pre>
<p>Note that this compressed code only has one instance of “<var>selected</var>”, resulting in a final byte size of 136 bytes, 10 bytes fewer than the previous version. The savings grow as the instances of the string increase, so if you have 20 places where “<var>selected</var>” was being used, you’d see even greater savings.</p>
<p>Replacing repeated values in your code can lead to greater incremental savings as the number of repeated values increases, as well. It is worthwhile to consider this approach not just for strings, but also for numbers (even Boolean values, if you so desire).</p>
<h3 id="store-local-references-to-objects-and-values">Store Local References to Objects/Values</h3>
<p>The YUI Compressor can’t perform variable replacement for either global variables or multi-level object references, so it’s better to store these in local variables. The previous example has three instances of <var>YAHOO.util.Dom</var> in the source code, and so the compressed version also has three instances. By storing <var>YAHOO.util.Dom</var> in a local variable, you can reduce the number of times that it appears in the compressed code. For example:</p>
<pre><code>function toggle(element){ var className = "selected"; var YUD = YAHOO.util.Dom; if (YUD.hasClass(element, className)){ YUD.removeClass(element, className); } else { YUD.addClass(element, className); }
}</code></pre>
<p>This version of the function is 238 bytes, and when compressed, shows even greater savings than the previous versions of the function:</p>
<pre><code>
function toggle(A){var B="selected";var C=YAHOO.util.Dom;if(C.hasClass(A,B)){C.removeClass(A,B)}else{C.addClass(A,B)}}
</code></pre>
<p>The final weight for this version is 118 bytes, a savings of 28 bytes over the original compressed function and 120 bytes smaller from the uncompressed version. And this is just one function, imagine if you got the same savings for all functions in your script.</p>
<p>Keep in mind that this technique also applies to object properties, so if <var>className</var> were a member of an object, its value should be stored locally as well. For instance:</p>
<pre><code>function toggle(element){ var YUD = YAHOO.util.Dom; if (YUD.hasClass(element, Constants.className)){ YUD.removeClass(element, Constants.className); } else { YUD.addClass(element, Constants.className); }
}</code></pre>
<p>In this function, <var>Constants.className</var> contains the class to use. The variable <var>Constants</var> is global, so its name cannot be replaced. You could set up a reference to <var>Constants</var>, but that is inefficient because you’re only using one property of that object in the function, so set up a reference to <var>Constants.className</var> to save even more bytes:</p>
<pre><code>function toggle(element){ var className = Constants.className var YUD = YAHOO.util.Dom; if (YUD.hasClass(element, className)){ YUD.removeClass(element, className); } else { YUD.addClass(element, className); }
}</code></pre>
<h3 id="avoid-eval">Avoid <code>eval()</code></h3>
<p>By this point, you’ve been told that <code>eval()</code> is evil multiple times and by multiple people. YUI Compressor agrees. The nature of <code>eval()</code> is such that the code executed has access to the variables that are present in the scope in which <code>eval()</code> was called. Because of that, YUI Compressor can’t safely do variable name changing when <code>eval()</code> is present. For example:</p>
<pre><code>function doSomething(code){ var msg = "hi"; eval(code);
} doSomething("alert(msg)"); //”hi”</code></pre>
<p>Even though the string that is being passed to <code>eval()</code> exists outside of the function in which <code>eval()</code> is called, it still has access to the local variables in that function. Since YUI Compressor can’t possibly know that the variable code contains a reference to a variable in the function, it doesn’t change the variable names in the <code>doSomething()</code> function, resulting in a less-than-optimal compression. Remember this: any time you use <code>eval()</code> in a function, that function’s variables cannot be renamed. The best approach is, as often said, to avoid <code>eval()</code> at all costs. If you absolutely must use <code>eval()</code> for some reason, try to isolate it away from other code so that the amount of variable renaming issues are minimal. For example:</p>
<pre><code>function myEval(code){ return eval(code);
} function doSomething(code){ var msg = “hi”; var count= 10; myEval(code);
}</code></pre>
<p>In this code, the call to <code>eval()</code> is isolated away from the main body of the <code>doSomething()</code> function. Now, YUI Compressor is free to replace variables in <code>doSomething()</code>.</p>
<h3 id="avoid-width">Avoid <code>with</code></h3>
<p>The <code>with</code> statement is another that is often <a rel="nofollow" target="_blank" href="http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/">recommended to avoid in JavaScript</a>. For YUI Compressor, the reason is the same for <code>eval()</code>: just the presence of <code>with</code> in a function causes variable renaming to be skipped for the entire function. There is just no way to keep track of variables versus object properties in the context of a <code>with</code> statement, so YUI Compressor rightly leaves the code as-is to avoid breaking the functionality. The best advice here is to avoid using <code>with</code> altogether. If you follow the advice of <a rel="nofollow" href="#store-local-references-to-objects-and-values">storing local copies of objects/properties</a>, you should have no use for <code>with</code>.</p>
<h3 id="use-the-verbose-option">Use the Verbose Option</h3>
<p>YUI Compressor has a “verbose” option (activated by the <code>–v</code> command line switch) that can help in the identification of some of these issues as well as a few others. The verbose option prints out warnings to the console indicating things that are preventing the YUI Compressor from fully doing its job. It will, for instance, tell you that a function contains <code>eval()</code> or the <code>with</code> statement, and therefore cannot be properly compressed. It also does analysis of variables, telling you if a variable was never defined (in which case it becomes global and cannot have its name replaced), if a variable was defined and never used (which just wastes space), and if a variable has been declared multiple times (also a waste of space).</p>
<h3 id="conclusion">Conclusion</h3>
<p>When used alone, the <a rel="nofollow" target="_blank" href="http://developer.yahoo.com/yui/compressor">YUI Compressor</a> achieves an excellent compression rate of your JavaScript code. The greatest byte savings are achieved by taking full advantage of variable replacement. The hints presented here have the primary goal of ensuring the YUI Compressor can do variable replacement whenever possible. Using constants to represent repeated values not only aids in compression, but also aids in the maintainability of your code by limited the number of areas that must be updated to accommodate a change in the value. Using local variables for multi-level object references allows for greater compression through variable replacement as well as providing faster runtime performance (local variable access is faster than global variable access and object property lookup). Perhaps most important is to ensure that you don’t use <code>eval()</code> or <code>with</code> when they’re not necessary, as each causes variable replacement to be turned off in the containing function. The YUI Compressor does a lot for you, but it can’t do everything. You can help it out greatly by following these tips.</p>
<p></p></div>]]></content:encoded>
      </item>
      <item>
         <title>Candidates graded on technical savvy, site performance</title>
         <link>http://developer.yahoo.net/blog/archives/2008/02/candidates_grad.html</link>
         <description>&lt;p&gt;Performance is important to users. It influences click through rates, loyalty, and engagement. Users want fast websites that they can view from anywhere, including phones, wireless connections, laptops, and home computers. Users also want a graphically rich user experience with all the bells and whistles. Multimedia blends of video, images, feeds, and other components can be very slow indeed. Here at Yahoo! we spend a lot of time analyzing and improving the performance of our own sites. In honor of Super Tuesday, we thought it would be fun to take a poke at the Presidential Candidates web sites and share with you what we found.&lt;/p&gt;
&lt;p&gt;How did they do? Overall, atrociously, all the candidates failed the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow&quot;&gt;YSlow&lt;/a&gt; exam except Mike Gravel who earned a &quot;D&quot;. Page weight was a problem for Barack Obama, whose site weighed in at almost 700Kb. It was even worse for Mitt Romney, whose site weighed a whopping 1,531Kb. I hope he doesn't have supporters trying to make contributions on dialup modems!&lt;/p&gt;
&lt;p&gt;Democrats got better grades in almost all performance subjects tested, in particular response times and page weight. They improved user experience for returning visitors by setting an Expires headers and improving the full cache user experience. This helped propel them to a performance GPA of &quot;C&quot; despite their failing YSlow grade. Republicans never managed to overcome the deficit and finished the semester with an &quot;F&quot;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://l.yimg.com/us.yimg.com/i/ydn/blog/dvsr_2.png&quot; alt=&quot;Democrat versus Republican, Performance-U&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: Democrats versus Republicans Performance Report Card&lt;/p&gt;
&lt;p&gt;Performance is one component in a balance of competing goals. These sites are trying to solicit support, donations, and volunteers. They need to provide a rich user experience that keeps people coming back, and engages them with the candidates' progress. Ultimately, they want to do this in a way that is fast, and accessible to as many voters as possible; including those on mobile phones, dialup modems, or low broadband. &lt;/p&gt;
&lt;h2&gt;Democrats&lt;/h2&gt;
&lt;p&gt;Mike Gravel and Hillary Clinton's websites had the two best response times tested. Barack Obama's website came in fourth, after the leading Republican. Response time is all about getting the biggest user-experience bang for your buck. One reason Obama's site might be slower, is the amount of below-the-fold content. Many voters may not see this extra content, we human beings don't seem to like to scroll, but it still impacts performance. &lt;/p&gt;
&lt;p&gt;Clinton, Obama, and Huckabee have graphically rich sites, and yet they are among the fastest. Do these sites succeed in engaging voters, or do they prefer the more serious, austere look of Gravel's site? The idea that a candidates website has a serious impact on his or her chances of being elected is relatively new. The rules and strategies are being invented now; we're living history.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://l.yimg.com/us.yimg.com/i/ydn/blog/belowthefold.png&quot; alt=&quot;Below The Fold Content&quot;&gt; &lt;/p&gt;
&lt;p&gt;Figure 2: Below the fold content might not be visible to voters, but it does affect response times&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://l.yimg.com/us.yimg.com/i/ydn/blog/dems.png&quot; alt=&quot;Democrats Report Card&quot;&gt; &lt;/p&gt;
&lt;p&gt;Figure 3: Democrats Response Time Report Card.&lt;/p&gt;
&lt;p&gt;This graph shows all of the candidates' grades plotted together. Reaching the outside band means the candidate got an A, for instance Obama and Gravel received As in Image Optimization, while Clinton squeaked into a high-B. The closer the candidate got to reaching the edge of the ocatgon, the better their grade. In fact each band is equivalent to one letter grade. From roughly the halfway point to the very center are variations on a failing grade. &lt;/p&gt;
&lt;p&gt;Clinton and Gravel provided two of the best performance-based user experiences recorded. However, Clinton had a large number of HTTP requests, which can slow down a site significantly. She counteracted that by setting an Expires headers so that returning voters would not have to pay the same performance penalty. Clinton also split static content across more than one domain to enable parallel downloads.&lt;/p&gt;
&lt;h2&gt;Republicans&lt;/h2&gt;
&lt;p&gt;Examining Republicans performance offers a clear opportunity to witness the connection between response time and page weight. To deliver a fast site, hard choices have to be made about which features to include, and which to abandon. &lt;/p&gt;
&lt;p&gt;Mike Huckabee's website combined low page weight and fewer http requests to achieve the best response time among Republicans and the third fastest response time overall. He could however trim 20Kb of fat from images with no loss of quality. We tested using lossless compression algorithms to determine how much extra baggage the candidates' pages were carrying. Romney was the real surprise in this category. The extra fat in his home page weighed more than Mike Huckabees entire page! &lt;/p&gt;
&lt;p&gt;Image Optimization is the kind of low hanging fruit that makes your site faster with absolutely no loss for the user. The tool we built to test image formats and compression algorithms determined that John McCain was the master of image optimization; we were only able to remove 1Kb from his images.&lt;/p&gt;
&lt;p&gt;Mitt Romneys site takes almost eight seconds to load even on a broadband connection. He got so many &quot;F&quot;s, our radar chart looks like Pollock on a bad day.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://l.yimg.com/us.yimg.com/i/ydn/blog/reps.png&quot; alt=&quot;Republicans Report Card&quot;&gt; &lt;/p&gt;
&lt;p&gt;Figure 4: Republicans Report Card&lt;/p&gt;
&lt;p&gt;Every one of these sites had outlying data points, that is, random response times of as much as 19 seconds. Romney even had a data point at 1.825 seconds, despite his more typical 5-10 second load times. These bad user experiences are real, and while most users just press reload and forget about it, it is important that we correct what we can, before they get frustrated and simply don't come back.&lt;/p&gt;
&lt;p&gt;Comparing worst-case scenarios, medians, averages, YSlow scores, empty or primed cache experiences, and other measurements can help you get a fuller picture of your user experience. Rather than looking for one magic number, performance requires us to unravel a nuanced puzzle. Try to understand what your users see, and how you can make it better for them, whether they are voters, customers, or people coming to read your blog. &lt;/p&gt;
&lt;p&gt;For those of you who like numbers, here's the data:&lt;/p&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt; &lt;tr&gt; &lt;td&gt; &lt;/td&gt; &lt;td&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.hillaryclinton.com/&quot;&gt;Hillary Clinton&lt;/a&gt;&lt;/td&gt; &lt;td&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.barackobama.com/index.php&quot;&gt;Barack Obama&lt;/a&gt;&lt;/td&gt; &lt;td&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.gravel2008.us/&quot;&gt;Mike Gravel&lt;/a&gt;&lt;/td&gt; &lt;td&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mikehuckabee.com/&quot;&gt;Mike Huckabee&lt;/a&gt;&lt;/td&gt; &lt;td&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.johnmccain.com/&quot;&gt;John McCain&lt;/a&gt;&lt;/td&gt; &lt;td&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ronpaul2008.com/&quot;&gt;Ron Paul&lt;/a&gt;&lt;/td&gt; &lt;td&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mittromney.com/&quot;&gt;Mitt Romney&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;YSlow&lt;/td&gt; &lt;td&gt;59&lt;/td&gt; &lt;td&gt;52&lt;/td&gt; &lt;td&gt;66&lt;/td&gt; &lt;td&gt;50&lt;/td&gt; &lt;td&gt;42&lt;/td&gt; &lt;td&gt;36&lt;/td&gt; &lt;td&gt;33&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Page Weight (K)&lt;/td&gt; &lt;td&gt;300&lt;/td&gt; &lt;td&gt;691&lt;/td&gt; &lt;td&gt;195&lt;/td&gt; &lt;td&gt;185&lt;/td&gt; &lt;td&gt;568&lt;/td&gt; &lt;td&gt;483&lt;/td&gt; &lt;td&gt;1531&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Response Time (S)&lt;/td&gt; &lt;td&gt;2.6077&lt;/td&gt; &lt;td&gt;3.4810&lt;/td&gt; &lt;td&gt;2.3733&lt;/td&gt; &lt;td&gt;3.1148&lt;/td&gt; &lt;td&gt;6.5309&lt;/td&gt; &lt;td&gt;4.2125&lt;/td&gt; &lt;td&gt;7.5352&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;HTTP Requests&lt;/td&gt; &lt;td&gt;96&lt;/td&gt; &lt;td&gt;94&lt;/td&gt; &lt;td&gt;32&lt;/td&gt; &lt;td&gt;56&lt;/td&gt; &lt;td&gt;107&lt;/td&gt; &lt;td&gt;83&lt;/td&gt; &lt;td&gt;77&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Cookie Weight&lt;/td&gt; &lt;td&gt;214&lt;/td&gt; &lt;td&gt;333&lt;/td&gt; &lt;td&gt;281&lt;/td&gt; &lt;td&gt;217&lt;/td&gt; &lt;td&gt;299&lt;/td&gt; &lt;td&gt;203&lt;/td&gt; &lt;td&gt;130&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Primed Cache - Page Weight (Kb)&lt;/td&gt; &lt;td&gt;33&lt;/td&gt; &lt;td&gt;242&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;td&gt;46&lt;/td&gt; &lt;td&gt;237&lt;/td&gt; &lt;td&gt;173&lt;/td&gt; &lt;td&gt;448&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Primed Cache - HTTP Requests&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;93&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;56&lt;/td&gt; &lt;td&gt;107&lt;/td&gt; &lt;td&gt;76&lt;/td&gt; &lt;td&gt;77&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Wasted Image Weight (Kb)&lt;/td&gt; &lt;td&gt;29&lt;/td&gt; &lt;td&gt;6&lt;/td&gt; &lt;td&gt;20&lt;/td&gt; &lt;td&gt;20&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;49&lt;/td&gt; &lt;td&gt;205&lt;/td&gt; &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;All measurements were taken using a MacBook Pro with Firefox, Firebug, and YSlow over a wireless connection. Page weights, cookie weights, and HTTP requests were determined via the YSlow Stats panel. &lt;/p&gt;
&lt;p&gt;Should you choose the next president based on their YSlow score? Probably not, but, it is one of many interesting ways of evaluating how technically savvy they are in an increasingly technical world. Now don't get me wrong, I know the candidates didn't write their own HTML or optimize their own images, but they did choose the person who would do this work for them. That's what makes this game interesting; they have to choose the right people for the right jobs every day. Happy voting!&lt;/p&gt; &lt;p&gt;Nicole Sullivan, Technical Evangelist&lt;br/&gt;
Yahoo!'s Exceptional Performance&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/02/candidates_grad.html</guid>
         <pubDate>Mon, 04 Feb 2008 21:09:19 -0800</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>The 7 Habits for Exceptional Performance</title>
         <link>http://developer.yahoo.net/blog/archives/2008/01/the_7_habits_fo.html</link>
         <description>&lt;p&gt;In July 2007 I took over the reins from Steve Souders (my former boss, performance co-hort, and someone I greatly respect) as manager of Yahoo!’s Exceptional Performance team. I was humbled and excited about the opportunity to lead Yahoo!’s now worldwide effort on accelerating the user experience and making our products faster, better, and more efficient.&lt;/p&gt; &lt;p&gt;Improvements in web site performance are similar to improvements in energy or fuel efficiency. We make good progress yet we continue to consume more, which reverse the results of our improvements. The net effect is that optimizing performance is an on-going battle. To ring in the New Year, the Exceptional Performance team would like to share our 7 Habits for Exceptional Performance:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1. LOFNO&lt;/strong&gt; – Look out for number one, that is, your users. Be an advocate for your users. You do control the user experience, so don’t settle for excuses and don’t make excuses. A lot of people shift the blame towards things they don’t control. The truth is that even if it’s slow ads or the framework that’s slowing down your site, chances are there are still things you can do personally to optimize performance for your users. Has every image been optimized? Have you evaluated whether users really use that feature you pushed so hard for? Did you run YSlow? Have you set the right tone and leadership so that others know performance is a top priority for your product? Focus on what you can do, not what you can’t do. Leave no stone unturned.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2. Harvest the low hanging fruit&lt;/strong&gt; – Find the optimizations that give you the biggest bang for your buck. If your web site has many pages, prioritize the pages. Look first at pages with higher traffic since those are the ones your users visit most. Identify strategic pages, ones that are important for the business. Create a list of performance optimizations and then prioritize that list starting with what will improve performance most. Then prioritize the same list again based on how much effort is required. Remember that removing just one image can often improve the user’s perceived response time by as much as an entire rewrite of the backend. Implement the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/performance/rules.html&quot;&gt;Rules for High Performance Web Sites&lt;/a&gt; (aka YSlow Rules). These rules were identified at Yahoo! as the low hanging fruit for making web sites faster without compromising design or features.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3. Balance features with speed&lt;/strong&gt; – Exceptional performance is a cross-team discipline. Our &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://yuiblog.com/blog/2006/11/28/performance-research-part-1/&quot;&gt;performance golden rule&lt;/a&gt; tells us that 80-90% of the time a user waits for a page to load is spent on the front-end. This makes the decision about what goes into the product (design, features, etc.) a major chunk of the time a user spends waiting for the components (images, JavaScript, CSS, etc.) to come down the wire. Think Yin and Yang, a constant flux of alternating forces. Designers add visual appealing elements. Product managers add functionally rich features. Engineers add flexible frameworks. All this equates to more time a user waits for your page to load. Remove images, eliminate features, compress components – all that equates to less time a user waits. Faster response time reduces site abandonment and increases usability. Less abandonment and better usability increases page views. And hey, you’ll also have a happier, less frustrated user.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;4. Start early and make performance part of the process&lt;/strong&gt; – Don’t wait until right before your product is about to be launched to discover that your product performs badly. By then, it’ll be too late. Incorporate performance into the product roadmap at design time and requirements gathering. Make performance part of the process early in the development cycle. Run performance tests at every major milestone. Every feature has a performance cost associated with it. Develop a test methodology and measure that cost. If your website requires a login, profile your most-valued users and create test accounts with the features you anticipate them to use. If your most-valued users are on dialup or broadband bandwidth speeds, make sure you run performance tests over these types of bandwidth speeds.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;5. Quantify and track results&lt;/strong&gt; – Let’s face it, we all want recognition for good work. There are lots of things we can do to improve the user’s experience. It’s more rewarding when we can quantify those optimizations. Have a portfolio of tools. Quantify performance so that it matches the experience of your users. Understand the differences between the various methodologies and tools your organization uses. If you don’t see an improvement after implementing an optimization, it could be a bad measurement methodology. There are many tools out there and different tools can show you different results. Make sure you are comparing apples to apples. Each tool has its differences, but together they can provide you a complete picture of how your product performs. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;6. Set targets&lt;/strong&gt; – Once you’ve established a methodology to quantify results, set and agree upon a target. Look at your competitors to help you determine a target. Better yet, look at the performance of pages where your users came from. From a quantitative perspective, two pages might take the same amount of time to load but qualitative research has shown us that users’ perception can vary depending on the performance of pages that load right before. Aim high and set a winning target for you, your team, and more importantly, your users. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;7. Ask questions and challenge answers&lt;/strong&gt; – Even smart people make assumptions or repeat incorrect statements. The best thing you can do is ask lots of questions, challenge answers, and if you have time verify the answers yourself. There’s no such thing as a bad question, but there are bad answers. Ask questions that give you the high-level overview. Ask questions that allow you to probe beneath the surface. Where did the information come from? How old is the data? What method was used to obtain the data? What alternative methods were considered and why weren’t they chosen? What assumptions were made? What were the drawbacks to an approach? If there was more time, what else might you have tried? Ask questions before hastily drawing a conclusion.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;8. (Bonus) Run YSlow&lt;/strong&gt; – &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://developer.yahoo.com/yslow/&quot;&gt;YSlow&lt;/a&gt; analyzes web pages and tells you why they’re slow. Download today and run YSlow on all the pages you visit!&lt;/p&gt; &lt;p&gt;Happy Optimizing and Happy New Year!&lt;/p&gt; &lt;p&gt;[Tenni Theurer is a Product Optimization Manager and manages Yahoo!’s Exceptional Performance team. Tenni has spoken at several conferences including Web 2.0 Exp, The Ajax Experience, The Rich Web Experience, AJAXWorld, BlogHer, and CSDN-DrDobbs. She also blogs regularly on Yahoo! Developer Network and Yahoo! User Interface Blog.]&lt;br /&gt;
&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2008/01/the_7_habits_fo.html</guid>
         <pubDate>Mon, 07 Jan 2008 14:01:27 -0800</pubDate>
         <category>performance</category>
      </item>
      <item>
         <title>Performance Draws a Crowd in Beijing</title>
         <link>http://developer.yahoo.net/blog/archives/2007/12/performance_dra.html</link>
         <description>&lt;p&gt;Last week Tenni Theurer, manager of Yahoo!'s Exceptional Performance group and my main performance co-hort, returned from her appearance at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sd2china.cn/english/&quot;&gt;CSDN-Dr.Dobbs Software Developer 2.0 Conference&lt;/a&gt; in Beijing, China. This was a big conference, perhaps the biggest software conference ever in China. I was psyched when Tenni told me her talk drew a crowd and was one of the best talks of the conference! CSDN's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://subject.csdn.net/sd2top10_2.htm&quot;&gt;SD2.0 web site&lt;/a&gt; says, &quot;Based on our SD conference survey result, Tenni Theurer’s session ranked as one of the top 3 sessions and was also selected by our editors as the most popular speaker.&quot; It's great to see interest in fast web pages has spread worldwide. Upcoming performance performances include the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.webguild.org/meetings/web20/2008/&quot;&gt;WebGuild Web 2.0 Conference&lt;/a&gt; in Santa Clara on January 29 and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://conferences.oreillynet.com/velocity&quot;&gt;Velocity&lt;/a&gt;, the web performance conference from O'Reilly on June 23-24 near San Francisco.&lt;/p&gt; &lt;p&gt;Steve Souders&lt;br /&gt;
Chief Performance Yahoo!&lt;/p&gt;</description>
         <guid isPermaLink="false">http://developer.yahoo.net/blog/archives/2007/12/performance_dra.html</guid>
         <pubDate>Tue, 11 Dec 2007 16:28:13 -0800</pubDate>
         <category>performance</category>
      </item>
   </channel>
</rss>
<!-- fe7.pipes.sp1.yahoo.com uncompressed/chunked Tue Nov 24 08:00:05 PST 2009 -->
