<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Performance Calendar</title>
	<atom:link href="http://calendar.perfplanet.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://calendar.perfplanet.com</link>
	<description>The speed geek&#039;s favorite time of the year</description>
	<lastBuildDate>Mon, 14 May 2012 21:45:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>When good back-ends go bad</title>
		<link>http://calendar.perfplanet.com/2011/when-good-back-ends-go-bad/</link>
		<comments>http://calendar.perfplanet.com/2011/when-good-back-ends-go-bad/#comments</comments>
		<pubDate>Sat, 31 Dec 2011 05:51:24 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1438</guid>
		<description><![CDATA[... and a double Dec 31st day with one more post from Pat. Here's to an optimized 2012! Cheers!]]></description>
			<content:encoded><![CDATA[<p>There has been a fair amount of <a href="http://www.yuiblog.com/blog/2006/11/28/performance-research-part-1/">research</a> that tells us that 80-90% of the time spent loading web pages is spent on the &#8220;front-end&#8221; (browser pulling in external resources like css, javascript and images) and only 10-20% of the time for a typical page is spent on the back-end.  While that is true &#8220;in general&#8221;, and there are a lot of tools that focus on giving you suggestions on improving your front-end code (<a href="http://www.webpagetest.org/">WebPagetest</a>, <a href="http://code.google.com/speed/page-speed/">Page Speed</a>, <a href="http://developer.yahoo.com/yslow/">Y-Slow</a>), it is not uncommon to see back-end performance issues, particularly as you move away from the top Internet sites into the long tail of the Internet.</p>
<p>This is not entirely unexpected because the top sites tend to have dedicated developers who custom-built the back-end code for serving pages and have dedicated operations teams that watch the performance of the systems and databases and spend a lot of time focused on the performance and scalability of the back-ends.</p>
<p>As you move out of the top tier of Internet publishers you start running into sites that are running on off-the-shelf content systems (Drupal, WordPress, Joomla, etc) and with owners who either contracted for the site development at one point in time or used and tweaked an available template and then used a collection of plugins to put together their site (often not knowing how the plugins themselves work).  The hosting for these sites also varies wildly from dedicated servers to VPS systems to running on shared hosting (by far the most common) where they have little to no insight on the performance of the actual systems their site is running on.</p>
<p>As a result, it&#8217;s not uncommon to see something like this:</p>
<p><img alt="30 Second TTFB" src="http://images.patrickmeenan.com/perf2011/30sec.png"></p>
<p>Yes, that is a 30+ second time to first byte (TTFB) with all of the time being spent somewhere on the back-end to assemble and produce the page.  This wasn&#8217;t an outlier either.  For this page, EVERY page load takes 30+ seconds before the browser even gets the first bit of HTML to work on.</p>
<p>This isn&#8217;t unique to this site or the Content Management System (CMS) it runs on (though it is an extreme example).  It is not uncommon to see 8-20 second back-end times from virtually all of the different CMS systems.</p>
<p><img alt="12 Second TTFB" src="http://images.patrickmeenan.com/perf2011/12sec.png"></p>
<p>This is really painful for users (assuming any of them actually wait that long for the site) but it also causes scaling problems for the back-end because the application is tied up for a long time processing each request making fewer resources available for other users.</p>
<h3>What is a good back-end time?</h3>
<p>A good target for just the processing time for back-end requests is on the order of 100ms (0.1 seconds).  That doesn&#8217;t mean you should expect a TTFB of 100ms, just that the back-end processing time shouldn&#8217;t take longer than that.  It is important to remember that the user can&#8217;t see ANYTHING at all before the TTFB so any improvements there go directly to the user experience.</p>
<p>When figuring out the back-end time from a front-end tool like WebPagetest, you need to remember to include the network latency.  For that I usually use the socket connect time to the server (orange bar) as the RTT and then use that as a baseline for everything else.</p>
<p><img alt="1.5 Second TTFB" src="http://images.patrickmeenan.com/perf2011/1sec.png"></p>
<p>In this case, the DNS lookup time (teal bar) is taking longer than I would expect but you want to compare the size of the orange bar to the size of the light green bar.  The length of the orange bar is the fastest the server would be able to reply and assumes 0 back-end processing time so if they are reasonably close in size then you&#8217;re in pretty good shape.</p>
<p>Eyeballing waterfalls is good for a general feeling but if you want to see the specifics, you can get the individual component times in a data table below the waterfalls on <a href="http://www.webpagetest.org/">WebPagetest</a>:</p>
<p><img alt="Request Timing Details" src="http://images.patrickmeenan.com/perf2011/timings.png"></p>
<p>In this case you just subtract the initial connection time from the TTFB and you have the amount of time that was spent on the back-end (436ms here).</p>
<h3>Figuring out what is going on</h3>
<p>So, you know you have a back-end issue, how do you figure out what is causing the problem?  </p>
<p>The problem is almost certainly caused by one of these issues:</p>
<ul>
<li>Web server configuration that is out of available clients to process requests</li>
<li>Slow database queries</li>
<li>Back-end calls to external services</li>
</ul>
<p>Unfortunately, most of the performance tools you are used to using don&#8217;t have any visibility into those components and they become a black box.  At this point you need a developer and a sysadmin (or someone with the skillset to do both) because fixing it is going to involve code or site configuration changes.  Even just finding the source of the problem requires a pretty decent skillset.</p>
<p>There are commercial solutions that will identify the issue for you really quickly with minimal work.  Actually, there is a whole sector focused on it (called Application Performance Management or APM).  I&#8217;ll use <a href="http://newrelic.com/">New Relic</a> as an example here because it is what I use on webpagetest.org but <a href="http://www.dynatrace.com/">Dynatrace</a> is another common solution.  All of them require that you install binary code on the server though so if you are on shared hosting these may not be available options (and once you get through the free trial phase most cost more than shared hosting plans anyway).</p>
<p>Once configured, the APM tools will monitor your production systems and tell you how much time your server is spending in the various different tiers:</p>
<p><img alt="New Relic Summary" src="http://images.patrickmeenan.com/perf2011/nr_summary.png"></p>
<p>I&#8217;ve done a fair bit of tuning to WebPagetest so there&#8217;s not a whole lot to see here.  Average response times are ~10ms and the database is only used for the forums so the bulk of the time is spent in the actual application code.</p>
<p>From there you can drill into each band to see exactly where that time is going:</p>
<p><img alt="New Relic Transactions" src="http://images.patrickmeenan.com/perf2011/nr_transactions.png"></p>
<p>In my case, most of the CPU time is spent generating thumbnail images (which includes waterfall thumbnails) for the results pages.  Not completely unexpected since they are all generated dynamically by code.</p>
<p>The thumbnail generation is something I spent a fair amount of time optimizing because it used to be a LOT more resource intensive and took close to 80% of the time.  The tools let you keep drilling in to see what specific functions contribute to the time:</p>
<p><img alt="New Relic Thumbnail Details" src="http://images.patrickmeenan.com/perf2011/nr_thumbnail.png"></p>
<p>They let you do the same for database calls and for particularly slow requests they will provide diagnostics for individual requests instead of just aggregate results so you can also drill into slow outliers easily.</p>
<p>If you aren&#8217;t fortunate enough to be able to use the tools then you have to look into what is available for your platform to see if there are free diagnostic tools or you have to start instrumenting the code yourself.  In WordPress, for example, there are several plugins that will debug the database queries and tell you how long they are taking.</p>
<p>W3 Total Cache is a useful plugin for improving WordPress performance but it also provides debugging information that will help you identify any slow database calls:</p>
<p><img alt="W3 Total Cache Debug Settings" src="http://images.patrickmeenan.com/perf2011/w3tc_options.png"></p>
<p>When you enable the debug information, details about every database query (and cache operation) will be logged into the page HTML as a comment that you can view by visiting the page and viewing the page source:
<p><img alt="W3 Total Cache Debug Data" src="http://images.patrickmeenan.com/perf2011/query_debug.png"></p>
<p>You&#8217;ll get the overall time spent in database queries as well as timings and details for each and every query.</p>
<h3>Fixing it</h3>
<p>Great, so now that you&#8217;ve identified the issues the real hard work starts.  The most common &#8220;solution&#8221; people use is to add caching to hide the problem.  This can be in the form of a plugin like W3 Total Cache that will let you cache all sorts of different operations to custom query caches using memcache.  Caches are absolutely necessary but you should improve the underlying issue as much as possible before enabling caching, that way 100% of the requests will get improved performance.</p>
<h3>Finally</h3>
<p>As they say in carpentry, measure twice, cut once.  Don&#8217;t go optimizing your site until you have measured the user experience and then use the measurements to guide your work, not grades or scores from various tools ñ they may not be relevant to your particular situation.  Just because sites <i>normally</i> spend most of their time on the front end doesn&#8217;t mean that is necessarily the case for yours.</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/when-good-back-ends-go-bad/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Measure twice, cut once</title>
		<link>http://calendar.perfplanet.com/2011/measure-twice-cut-once/</link>
		<comments>http://calendar.perfplanet.com/2011/measure-twice-cut-once/#comments</comments>
		<pubDate>Sat, 31 Dec 2011 05:49:34 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1439</guid>
		<description><![CDATA[Wise words from Tom on approaching performance optimization projects for busy multi-tasking developers. Here's to an optimized 2012!]]></description>
			<content:encoded><![CDATA[<p>There is a famous saying in English, &#8220;Measure twice, cut once&#8221; which is especially important if you do anything with your hands. Once you&#8217;ve cut a piece of wood with a saw and you find you are 5mm too short it&#8217;s pretty hard to fix it. While software is hard to waste in the same way you can waste a raw material like wood, you can certainly waste your time. </p>
<p>A resource like the performance calendar is a really great tool for finding ideas to apply to your own work. Many of the authors of this site are lucky in that they spend a significant amount of their time optimizing large sites for companies like Facebook, Yahoo! and Google (and yours truly, Walmart). However many developers have lots of other responsibilities other than performance.</p>
<p>When you have lots of things on your plate measuring more than pays its way. While it is easy to grab a technique that someone has laid out for you and apply it (and you should) you should make sure you target the issues that affect your site the most. I was at a conference a few years ago about JavaScript and an extremely prominent, talented and altogether smart JavaScript expert gave a talk about performance optimization. He gave a number of in-depth tips including unrolling loops and other micro-optimizations.</p>
<p>Here is the thing; When you are the author of a framework used by many thousands of sites every hour you spend optimizing the code pays off on every one of those sites. If you make helper functions used over and over your work repays itself many fold through each small usage. However, when you only care about the one site you maintain unrolling loops probably won&#8217;t make a significant or obvious a difference to your users. Optimization is all about picking the correct targets.</p>
<p>This is where we come back to measuring again. When you don&#8217;t have a clear understanding of where your bottlenecks are you need to measure before you cut. Measuring performance can be done in many ways and this is also important to consider. Unrolling loops in JavaScript is a very atomic micro optimization. It improves one specific function. However unrolling a loop that loops only twice and is only used by 1% of users is clearly not an important use of time.</p>
<p>The key to measurement is instrumentation. Start at a macro level. What are the most important parts of your site? This might be the ones used the most, or the ones which have the most impact on your business (such as the checkout process). You might find yourself surprised, perhaps you receive a lot of search engine traffic to a page deep in your site that is poorly optimized. Improving that page by 50% might make a much bigger impact than spending the same time getting another 1% improvement on your already optimized homepage. The only way to really know which pages on your site are important are to look at the stats or to discuss priorities with whoever is in charge of the site.</p>
<p> Once you know what&#8217;s important, the next task is to figure out what users do with those pages, or again what you want them to do. It&#8217;s important to note in this process that what customers do now may be an attribute of the current site and not actually what you want them to do. Identify which parts of your site are used the most by finding the most common tasks on the page. Which page level items (menus, search results) do users interact with most?</p>
<p>So here is our formula for optimizing:</p>
<ul>
<li>Step 1. Use instrumentation to pick which pages/sections to optimize</li>
<li>Step 2. Use instrumentation to pick which features to optimize</li>
<li>Step 3. Optimize</li>
</ul>
<p>Measure twice, cut once.</p>
<h3>Identifying Pages/Sections</h3>
<p>How do you go about picking which pages or sections of your site to optimize? This probably one of the easiest tasks because most conventional metrics give you everything you need to know. Start by seeing which pages get the most views. This will give you a short list of obvious targets. Your homepage is almost certainly one them, and then other popular pages on your site. These should be your shortlist.</p>
<p>The next thing to do is talk to your business owner. That might be your project manager, CEO, whoever. The most popular pages are not always the most important to the business. Checkout and shopping cart are very obvious examples here. If you run an e-commerce site many many people will browse many items, but only a small percentage of people will check-out. This doesn&#8217;t mean check-out isn&#8217;t important. On the contrary. Checkout is really important, it&#8217;s just something that metrics many not help you prioritize.</p>
<p>Now you should have a list of the pages or sections of your site which are a mix of the most popular or important ones to the business. This is your hit list. Keep it up to date periodically. Until you&#8217;ve exhausted your hit list don&#8217;t bother with other performance issues.</p>
<h3>Identifying Features</h3>
<p>On modern web sites many pages share the same code on many pages. Look at the code to find these features or use a packet sniffer like <a href="http://www.wireshark.org/">Wireshark</a>, <a href="http://www.charlesproxy.com/">Charles Proxy</a> or the Chrome Inspector or the Chrome Inspector on your hit list pages will help you get a list of the remote resources that were accessed. You can also examine your HTTP logs to look at what secondary web service resources are being requested for those popular pages. Those resources could also be a blocking factor in page rendering.</p>
<p>You should also try to identify what your users are doing on each page. This can be difficult. Unless you have a very rich metrics system you probably don&#8217;t know where the users&#8217; cursors  are, or how much they scroll. What you can probably do, however is look at what where they commonly click to from your hist list pages. This will give you an idea of what is being used the most. For example, on an product description page it might be the &#8220;add to cart&#8221; button. You should also look at timing, things like navigation menu items are going to get clicked a lot sooner after rendering than an &#8220;add to cart&#8221; button in general. This is because when people buy things they normally read the product description first. When they are navigating they aren&#8217;t reading page content, yet. You can instrument your pages with JavaScript or you can compute the time between page loads per user if you want to be a clever-clogs.</p>
<p> In general the goal is to figure out which things the user will need most readily. As an informal rule of thumb consider prioritizing items to load in this order:</p>
<ul>
<li>Items above the fold</li>
<li>Navigation item (Menus, search bar)</li>
<li>Items that provide information (Product description, News stories)</li>
<li>Items to take an action (Add to cart, etc)</li>
<li>Items below the fold</li>
</ul>
<p>You can check how fast various things load on your site using <a href="http://webpagetest.org">WebpageTest</a>&#8216;s film strip feature.</p>
<h3>Optimizing</h3>
<p>The final step is of course optimizing. Remember even within optimizing a feature don&#8217;t spend all your time optimizing something that is already optimized when there is something used 90% as much that isn&#8217;t. That&#8217;s the point of metrics to make good decisions. This goes both for your list of pages and features, and within the code. The goal of optimizing should be to take your measurements and then make the best use of your time to affect the users&#8217; experience. Check out page render and JavaScript profilers and techniques.</p>
<p>There are lots of resources out there, once you know what you need to optimize go and find something to solve your problem, and then measure, measure again.</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/measure-twice-cut-once/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Losing Your Head With PhantomJS and confess.js</title>
		<link>http://calendar.perfplanet.com/2011/losing-your-head-with-phantomjs-and-confess-js/</link>
		<comments>http://calendar.perfplanet.com/2011/losing-your-head-with-phantomjs-and-confess-js/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 09:30:58 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1437</guid>
		<description><![CDATA[James shares confess.js - a tool he built on top of PhantomJS for scripting a headless WebKit and automating performance data collection and cache manifest generation]]></description>
			<content:encoded><![CDATA[<p>We yearn for powerful and reliable ways to judge the performance and user experience of web applications. But for many years, we&#8217;ve had to rely on a variety of approximate techniques to do so: protocol-level synthesis and measurement, cranky browser automation, fragile event scripting &#8211; all accompanied with a hunch that we&#8217;re still not <i>quite</i> capturing the behavior of real users using real browsers.</p>
<p>Enter one of this year&#8217;s most interesting open-source projects: <a href='http://phantomjs.org'>PhantomJS</a>. Thanks to <a href='http://ariya.ofilabs.com/'>Ariya Hidayat</a>, there&#8217;s a valuable new tool for every web developer&#8217;s toolbox, providing a headless, yet fully-featured, WebKit browser that can easily be launched off the command-line, and then scripted and manipulated with JavaScript.</p>
<p>I&#8217;ve used PhantomJS to underpin <a href='https://github.com/jamesgpearce/confess'>confess.js</a>, a small library that makes it easy to analyze web pages and apps for various purposes. It currently has two main functions: to provide simple page performance profiles, and to generate app cache manifests. Let&#8217;s take them for a quick spin.</p>
<h3>Performance summaries</h3>
<p>Once installed, the simplest thing to do with confess.js is generate a simple performance profile of a given page. Using the PhantomJS browser, the URL is loaded, its timings taken, and a summary output emitted &#8211; all with one single command:</p>
<pre style='overflow-x:scroll'>$&gt; phantomjs confess.js http://calendar.perfplanet.com/2011/ performance</pre>
<p>Here, the confess.js script is launched with the PhantomJS binary, directed to go to the PerfPlanet blog page, and then expected to generate something like the following:</p>
<pre style='overflow-x:scroll'>Elapsed load time:   6199ms
   # of resources:       30

 Fastest resource:    408ms; http://calendar.perfplanet.com/wp-content/themes/wpc/style.css
 Slowest resource:   3399ms; http://calendar.perfplanet.com/photos/joshua-70tr.jpg
  Total resources:  69080ms

Smallest resource:    2061b; http://calendar.perfplanet.com/wp-content/themes/wpc/style.css
 Largest resource:    8744b; http://calendar.perfplanet.com/photos/joshua-70tr.jpg
  Total resources:  112661b; (at least)</pre>
<p>Nothing revolutionary about this simple output &#8211; apart from the fact that of course, under the cover, this is coming from a real WebKit browser. We&#8217;re getting solid scriptable access to every request and response that the browser is making and receiving, without having to make any changes to the page under test.</p>
<p>So already you might be able to imagine there&#8217;s a lot more that can be done with this instrumentation. I had some light-hearted fun getting confess.js (with a verbose flag) to emit waterfall charts of a page and its resources, for example &#8211; all in technicolor ASCII-art:</p>
<pre style='overflow-x:scroll'>  1|-------                                                         |
  2|       ------------                                             |
  3|                 -----------                                    |
  4|                 ---------------------                          |
  5|                  -----------                                   |
  6|                  -------                                       |
  7|                  -------                                       |
  8|                  -------                                       |
  9|                  -------                                       |
 10|                                     ----------                 |
 11|                                     ----------------------     |
 12|                                     ----                       |
    ...

  1:   1679ms;       -b; http://cnn.com/
  2:   3115ms;       -b; http://www.cnn.com/
  3:   2716ms;       -b; http://z.cdn.turner.com/...css/hplib-min.css
  4:   5465ms;       -b; http://z.cdn.turner.com/...5/js/hplib-min.js
  5:   2952ms;       -b; http://z.cdn.turner.com/.../globallib-min.js
  6:   1681ms;      21b; http://content.dl-rms.co...r/5721/nodetag.js
  7:   1698ms;       -b; http://icompass.insightexpressai.com/97.js
  8:   1743ms;       -b; http://ad.insightexpress...px?publisherID=97
  9:   1706ms;       -b; http://js.revsci.net/gat...gw.js?csid=A09801
 10:   2494ms;    7732b; http://i.cdn.turner.com/...ader/hdr-main.gif
 11:   5694ms;   44091b; http://i2.cdn.turner.com...quare-t1-main.jpg
 12:   1023ms;     858b; http://i.cdn.turner.com/...earch_hp_text.gif
    ...</pre>
<p>While this might seem a poor alternative to the rich diagnostics that can be gained from, say, the WebKit Web Inspector tools, it does provide a nice way to get a quick overview of the performance profile &#8211; and potential bottlenecks &#8211; of a page. And, of course, and more importantly, it can be easily extended, run from the command-line, automated and integrated as you wish.</p>
<h3>App cache manifest</h3>
<p>Similarly, we can also use a headless browser to analyze the application&#8217;s actual content in order to perform a useful task. Although there&#8217;s a run-time &#8216;chinese wall&#8217; in PhantomJS between the JavaScript of the harness and the JavaScript of the page, it&#8217;s permable enough to allow us to evaluate script functions against the DOM and have simple results structures returned to confess.js.</p>
<p>Why might we want to analyze a page&#8217;s DOM in an automated way? Well, take the app cache manifest mechanism, for example: it provides a way to mandate to a browser which resources should be explicitly cached for a given application, but, despite a deceptively simple syntax, it can be frustrating to keep track of all the assets you&#8217;ve used. To maximize the benefits of using app cache, you want to ensure that every resource is considered: whether it&#8217;s an image, a script, a stylesheet &#8211; or even resources further referred to from inside those.</p>
<p>This is the perfect job for a headless browser: once a document is loaded, we can examine it to identify the resources it actually uses. Doing this against the real DOM in a real browser makes it far more likely to identify dependencies required by the app at run-time than would be possible through statically analyzing web markup.</p>
<p>And again, something like this could easily become part of an automated build and deploy process. For example:</p>
<pre style='overflow-x:scroll'>$&gt; phantomjs confess.js http://calendar.perfplanet.com/2011/ appcache</pre>
<p>&#8230;will result in the following manifest being generated:</p>
<pre style='overflow-x:scroll'>CACHE MANIFEST

# This manifest was created by confess.js, http://github.com/jamesgpearce/confess
#
# Time: Fri Dec 23 2011 13:46:42 GMT-0800 (PST)
# Retrieved URL: http://calendar.perfplanet.com/2011/
# User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.4.0 Safari/534.34

CACHE:
/photos/aaron-70tr.jpg
/photos/alex-70tr.jpg
/photos/alois-70tr.jpg
[...]

http://calendar.perfplanet.com/wp-content/themes/wpc/globe.png

http://calendar.perfplanet.com/wp-content/themes/wpc/style.css

NETWORK:
*</pre>
<p>Depending on your app, there might be a lot of output here. But the key parts, as far as the eventual user&#8217;s browser will be concerned, are the CACHE and NETWORK blocks. The latter is always set to the * wildcard, but the former list of explicit resources is built up automatically from the URL you ran the tool against.</p>
<p>For app cache nirvana, you&#8217;d simply need to pipe this output to a file, link to it from the &lt;html&gt; element of your target document, and of course ensure that the file, when deployed, is generated with a content type of text/cache-manifest.</p>
<p>As an aside, the list of dependant resources itself is harvested by confess.js in four ways. Firstly, once the document is loaded in PhantomJS, the DOM is traversed, and URLs sought in src and href attributes on script, img, and link elements. Secondly, the CSSOM of the document&#8217;s stylesheets is traversed, and property values of the CSS_URI type are sought. Thirdly, the entire DOM is traversed, and the getComputedStyle method picks up any remaining resources. And finally, the tool can be configured to watch for additional network requests &#8211; just in case, say, some additional content request has been made by a script in the page that would not have been predicted by the contents of the DOM or CSSOM.</p>
<p>(Naturally, there are many useful ways to configure the manifest generation as whole. You can filter in or out URLs in order to, say, exclude certain file types or resources from remote domains. You can also wait for a certain period after the document loads before performing the extraction, in case you know that a deferred script might be adding in references to other resources. There&#8217;s information about all this in the <a href='https://github.com/jamesgpearce/confess/blob/master/README.md'>docs</a>.)</p>
<h3>Onwards and upwards</h3>
<p>We&#8217;ve just touched on the two simple examples of what can be done with a headless browser approach in general. The technique provides a powerful way to analyze web applications, and get closer to being able to understand real users&#8217; experience and real apps&#8217; behaviour.</p>
<p>I&#8217;d certainly urge you to check out <a href='http://phantomjs.org'>PhantomJS</a>, try scripting some simple activities, and think about how you can use it to understand and automate web site and application behaviour. (I&#8217;m not even sure I mentioned yet that it has a screen-shotting capability too&#8230;)</p>
<p>And of course, feel free to give <a href='https://github.com/jamesgpearce/confess'>confess.js</a> a try too &#8211; with its humble goal of making it easier to help automate some of those common tasks. I&#8217;m always accepting pull requests!</p>
<p>But whatever your tools of choice&#8230; do have fun on your performance adventures, push the envelope, make the web a wonderful place &#8211; and I hope you all have an excellent 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/losing-your-head-with-phantomjs-and-confess-js/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CSS Selector Performance has changed! (For the better)</title>
		<link>http://calendar.perfplanet.com/2011/css-selector-performance-has-changed-for-the-better/</link>
		<comments>http://calendar.perfplanet.com/2011/css-selector-performance-has-changed-for-the-better/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 09:42:20 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1435</guid>
		<description><![CDATA[Nicole shares Antti Koivisto's CSS efficiency updates to WebKit and shows us how the way we think about CSS selector performance should change accordingly.]]></description>
			<content:encoded><![CDATA[<p>Great articles, like Dave Hyatt’s Writing Efficient CSS, helped developers adapt to a rudimentary selector matching landscape. We learned from Steve Souders (and others) that selectors match from right to left, and that certain selectors were particularly arduous to match and should best be avoided. For example, we were told that descendant selectors were slow, especially when the right-most selector matched many elements on the page. All this was fantastic information when we had none, but as it turns out, times have changed. Thanks to some amazing work by Antti Koivisto there are many selectors we don’t need to worry about anymore.</p>
<p>Antti contributes code to WebKit core and recently spent some time optimizing CSS selector matching. In fact, after finishing his work, he said:</p>
<blockquote><p>&#8220;My view is that authors should not need to worry about optimizing selectors (and from what I see, they generally don&#8217;t), that should be the job of the engine.&#8221;</p></blockquote>
<p> ~ Antti Koivisto</p>
<p>Wow! That sounds fantastic to me. I’d love to be able to use selectors in a way that makes sense for my architecture and let the rendering engine handle selector optimization. So, what did he do? Not just one thing, rather he created multiple levels of optimization &#8212; we’ll take a look at four optimizations in particular:</p>
<ol>
<li>Style Sharing
<li>Rule Hashes
<li>Ancestor Filters
<li>Fast Path
</ol>
<h3>Style Sharing</h3>
<p>Style sharing allows the browser to figure out that one element in the style tree has the same styles as something it has already figured out. Why do the same calculation twice! </p>
<p>For example:</p>
<div class="hl-main">
<pre><span class="hl-brackets">&lt;</span><span class="hl-reserved">div</span><span class="hl-brackets">&gt;</span><span class="hl-code">
  </span><span class="hl-brackets">&lt;</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-code">foo</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-code">
  </span><span class="hl-brackets">&lt;</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-code">bar</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-code">
</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">div</span><span class="hl-brackets">&gt;</span></pre>
</div>
<p>If the browser engine has already calculated the styles for the first paragraph, it doesn’t need to do so again for the second paragraph. A simple but clever change that saves the browser a lot of work.</p>
<h3>Rule Hashes</h3>
<p>By now, we all know that the browser matches styles from right to left, so the rightmost selector is really important. Rule hashes break a stylesheet into groups based on the rightmost selector. For example the following stylesheet would be broken into three groups:</p>
<div class="hl-main">
<pre><span class="hl-identifier">a</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-identifier">div</span><span class="hl-code"> </span><span class="hl-identifier">p</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-identifier">div</span><span class="hl-code"> </span><span class="hl-identifier">p</span><span class="hl-identifier">.legal</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-identifier">#sidebar</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-identifier">#sidebar</span><span class="hl-code"> </span><span class="hl-identifier">p</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-brackets">}</span></pre>
</div>
<style>td,th{border:0;} th code{font-weight: bold; background: transparent; border: 0}</style>
<table>
<tr class="imagemenot">
<th><code>a</code></th>
<th><code>p</code></th>
<th><code>p.legal</code></th>
</tr>
<tr>
<td><code>a {}</code></td>
<td><code>div p {}</code></td>
<td><code>div p.legal {}</code></td>
</tr>
<tr>
<td><code>#sidebar a {}</code></td>
<td><code>#sidebar p {}</code></td>
<td>&nbsp;</td>
</tr>
</table>
<p>When the browser uses rule hashes it doesn’t have to look through every single selector in the entire stylesheet, but a much smaller group of selectors that actually have a chance of matching. Another simple but very clever change that eliminates unnecessary work for every single HTML element on the page!</p>
<h3>Ancestor Filters</h3>
<p>The ancestor filters are a bit more complex. They are <em>Probability filters</em> which calculate the likelihood that a selector will match. For that reason, the ancestor filter can quickly eliminate rules when the element in question doesn’t have required matching ancestors. In this case, it tests for descendant and child selectors and matches based on class, id, and tag. Descendant selectors in particular were previously considered to be quite slow because the rendering engine needed to loop through each ancestor node to test for a match. The bloom filter to the rescue.</p>
<p>A bloom filter is a data structure which lets you test if a particular selector is a member of a set. Sounds a lot like selector matching, right? The bloom filter tests whether a CSS rule is a member of the set of rules which match the element you are currently testing. The cool thing about the bloom filter is that false positives are possible, but false negatives are not. That means that if the bloom filter says a selector doesn’t match the current element, the browser can stop looking and move on the the next selector. A huge time saver! On the other hand, if the bloom filter says the current selector matches, the browser can continue with normal matching methods to be 100% certain it is a match. Larger stylesheets will have more false positives, so keeping your stylesheets reasonably lean is a good idea.</p>
<p>The ancestor filter makes matching descendant and child selectors very fast. It can also be used to scope otherwise slow selectors to a minimal subtree so the browser only rarely needs to handle less efficient selectors.</p>
<h3>Fast Path</h3>
<p>Fast path re-implements more general matching logic using a non-recursive, fully inlined loop. It is used to match selectors that have any combination of:</p>
<ol>
<li>Descendant, child, and sub-selector combinators, and
<li>tag, id, class, and attribute component selectors
</ol>
<p>Fast Path improved performance across such a large subset of combinators and selectors. In fact, they saw a 25% improvement overall with a 2X improvement for descendant and child selectors. As a plus, this has been implemented for querySelectorAll in addition to style matching.</p>
<p>If so many things have improved, what’s still slow?</p>
<h3>What is still slow?</h3>
<p>According to Antti, direct and indirect adjacent combinators can still be slow, however, ancestor filters and rule hashes can lower the impact as those selectors will only rarely be matched. He also says that there is still a lot of room for webkit to optimize pseudo classes and elements, but regardless they are much faster than trying to do the same thing with JavaScript and DOM manipulations. In fact, though there is still room for improvement, he says:</p>
<blockquote><p>&#8220;Used in moderation pretty much everything will perform just fine from the style matching perspective.&#8221;</p></blockquote>
<p>~ Antti</p>
<p>I like the sound of that. The take-away is that if we can <em>keep stylesheet size sane</em>, and <em>be reasonable with our selectors</em>, we don’t need to contort ourselves to match yesterdays browser landscape. Bravo Antti!</p>
<p>Want to learn more? Check out <a href="http://dl.dropbox.com/u/39519/talks/cssperf/index.html">Paul Irish’s presentation on CSS performance</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/css-selector-performance-has-changed-for-the-better/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Beyond Bandwidth: UI Performance</title>
		<link>http://calendar.perfplanet.com/2011/beyond-bandwidth-ui-performance/</link>
		<comments>http://calendar.perfplanet.com/2011/beyond-bandwidth-ui-performance/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 07:12:44 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1434</guid>
		<description><![CDATA[David encourages us to look beyond reducing HTTP requests, file sizes and fast JavaScript.  Let's start focusing more on the UI layer, he suggests, arming us with the tools to do so.]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Traditionally, older performance studies were concerned with speeding up things on the server side, but a few years back Steve Souders famously started research on the idea that the main performance bottleneck happened on the client side.  In particular, in the way bytes were pushed to the client from the server.  &#8220;Reduce HTTP requests&#8221; has become a general maxim for speeding up frontend performance, and that is a concern that&#8217;s even more relevant in today&#8217;s world of mobile browsers (often running on networks that are an order of magnitude slower than broadband connections).</p>
<p>These studies have been concerned with latency and bandwidth, and this still continues to be the focus of performance research today.  You are probably already familiar with the standard HTTP waterfall chart:</p>
<p><img src="/wp-content/uploads/2011/12/google-http-waterfall-chart.png" width="650"></p>
<p>However, we&#8217;re slowly starting to see a shift to other frontend concerns for each component of the frontend stack (HTML/CSS/JS).  In particular, there&#8217;s been a great focus on JavaScript performance, a fact attested to by the popularity of <a href="http://jsperf.com/">jsPerf</a> and the rise of JavaScript profilers.</p>
<h3>After the page loads: the UI layer</h3>
<p>This is all well and good, but we&#8217;re missing something: the presentation (UI) layer.  Ok, that&#8217;s actually a bit of an exaggeration.  UI performance tips have been disseminated throughout the community for years, but often as an aside, with bandwidth and latency concerns much more at the forefront.  For instance, where CSS is even a concern, <a href="http://www.stevesouders.com/blog/2010/07/03/velocity-top-5-mistakes-of-massive-css/">the focus is on reducing CSS filesizes</a>.  But what about expensive selectors?  Or CSS that may cause the page to lag horribly?</p>
<p>One of the reasons UI performance has been downplayed is perhaps because of its inability to be quantified.  As engineers, it&#8217;s a bit disconcerting to say that as a result of many hours of improvements, a website &#8220;feels&#8221; more responsive, or scrolls more smoothly.  We would rather say &#8220;this site was originally rated at a 6/10 for responsiveness, but now it&#8217;s rated 8/10 for responsiveness!&#8221;  But how on earth can we do gauge that?  Well, now we can!</p>
<h3>UI Profilers</h3>
<p>Recently we&#8217;ve been given the tools to measure UI performance.  A new CSS profiler is available in Opera&#8217;s developer tools, and one is on the way for WebKit browsers.  Here&#8217;s the new face of performance profiling:</p>
<p><img src="/wp-content/uploads/2011/12/opera-css-profiler.png"></p>
<p>Here&#8217;s a few tools that should come in handy when testing UI performance:</p>
<h4>CSS Stress Test</h4>
<p><a href="http://andy.edinborough.org/CSS-Stress-Testing-and-Performance-Profiling">CSS Stress Test</a> (by Andy Edinborough) is a bookmarklet that figures out which CSS declarations are slowing down the page by selectively removing each one, then timing the scroll speed performance.  The result is a bookmarklet that&#8217;s a bit jarring to watch, but seems quite useful in tracking down rogue CSS bottlenecks.  Note to self: apparently applying border-radius to a ton of elements isn&#8217;t a very good idea, performance-wise.</p>
<h4>CSS Profilers</h4>
<p>A <a href="http://bricss.net/post/13884376788/the-css-profilers-are-coming">CSS profiler</a> is coming to a browser near you, which will give us much more insight into the actual speed of the CSS we write, moving us forward from vague and mysterious rules.  Is the universal selector (*) really that expensive?  Are border-radius, box shadow, and rgba values really performance drains?  Now we have ways to measure those concerns!</p>
<h4>CSS Lint</h4>
<p><a href="http://csslint.net/">CSS Lint</a> (by Nicole Sullivan and Nicholas Zakas) is a set of <a href="https://github.com/stubbornella/csslint/wiki/Rules">best practices</a> (you may not agree with them all, but that&#8217;s ok), including a few helpful rules that target UI performance specifically.  Run your stylesheets through and it&#8217;ll give you some helpful tips on what to improve.</p>
<h4>DOM Monster</h4>
<p><a href="http://mir.aculo.us/dom-monster/">DOM Monster</a> (by Amy Hoy and Thomas Fuchs) is intended as a JavaScript profiler companion, but remember that the complexity of the DOM (Document Object Model) will also affect UI repaints and reflows.  Reducing that bloat is better for data down the wire, as well as UI rendering and JavaScript DOM access.</p>
<h3>Perception of Speed</h3>
<p>If you think about it, all of performance is concerned with how performance is perceived by the user.  While we&#8217;re mostly concerned with real performance improvements, we have to recognize the limitations and realize that we don&#8217;t always have control over bandwidth, latency, or the speed of a user&#8217;s browser.  Where we&#8217;ve already done our best elsewhere, here we sometimes have to fake it.  Fake it &#8217;till you make it!</p>
<p>What do I mean by faking it?  This might mean preloading content where possible, which is what Gmail mobile does before the user clicks on the &#8220;Show more messages&#8230;&#8221; button.  After the user clicks, the content has already been loaded &#8211; it only needs to change the UI to show the new content, and this happens extremely fast.  It doesn&#8217;t really matter how long it took to make the original HTTP request, because either way the experience is the same for the user, and their <i>perception</i> is that the interface is extremely fast.  This is an example of a great marriage of good user experience design with good engineering.</p>
<p>&#8220;Faking it&#8221; might also mean simply being responsive and quickly showing the user a visual indicator after they take an action.  It doesn&#8217;t matter how well you optimize HTTP requests or how fast the connection is &#8211; if you don&#8217;t give an indication after the user performs an action, they will likely repeat their action (a click or another tap on the touchscreen) and come away with the impression that it&#8217;s a sluggish interface.</p>
<p>UI responsiveness also <a href="http://www.youtube.com/watch?v=05C0GQPKA4g">became a concern for Flickr when they switched to YUI3</a> &#8211; though they took advantage of combining HTTP requests, the initial unprimed cache page load meant that a user might start taking actions before the JavaScript was fully loaded, parsed, and executed.  Because Flickr progressively enhances their webpages, this means that without JavaScript ready, the user gets taken to pages that were put in place for users with JavaScript disabled.  Their solution was to load a mini-library in the page to capture all events on the page and queue them back to be replayed later.  Most importantly, this small library also provides a UI (a loading spinner) to give the user feedback after taking actions, even if it means nothing had happened, short of the event being queued up to be replayed later when the JavaScript is ready.  Fake it &#8217;till you make it!</p>
<h3>Tidbits</h3>
<p>As I mentioned before, UI performance tips have been circulating for quite a while, but they have been somewhat downplayed compared to latency and bandwidth issues.</p>
<p>Here&#8217;s a collection of tidbits to give you an idea of some of the concerns that are out there:</p>
<ul>
<li><a href="http://blog.vlad1.com/2009/06/22/to-sprite-or-not-to-sprite/">Sprites save HTTP requests, but large sprites hog up memory</a></li>
<li><a href="http://calendar.perfplanet.com/2011/pure-css3-images-hmm-maybe-later/">Pure CSS3 images? Hmm, maybe later (Marcel Duran)</a> &#8211; pure CSS3 images are awesome but perhaps impractical, as they trade less bandwidth for decreased rendering speed (it turns out that images render faster)</li>
<li>Microsoft&#8217;s <a href="http://www.microsoft.com/taiwan/promo/ie9/bow/fish_demo/FishTank_demo.html">FishIE Tank</a> is a nice benchmark to test Canvas rendering speed, measured in frames per second.  You may even find that <a href="http://29a.ch/2011/5/27/fast-html5-canvas-on-iphone-mobile-safari-performance">tweaking the viewport tag on mobile devices may speed up rendering times</a></li>
<li><a href="http://lea.verou.me/2011/08/css-gradients-are-much-faster-than-svg/">CSS gradients are faster than SVG backgrounds</a></li>
<li>Older WebKit browsers had <a href="https://bugs.webkit.org/show_bug.cgi?id=22102">scrolling/rendering lag with large box shadows</a> &#8211; not all CSS3 stuff is ready for prime time, and sometimes images might be the way to go &#8211; better UI performance at the expense of more data down the wire</li>
<li>CSS radial gradients may be awesome and save the request of an image, but they might have rendering problems in some browsers, <a href="http://code.google.com/p/android/issues/detail?id=767">particularly Android</a>.  We save bandwidth by not requesting an image, but the user experience suffers</li>
<li>Avoid IE CSS filters, as they have a performance hit</li>
<li>Use hardware-accelerated CSS animations over JavaScript animations where possible, but be aware of limitations (<a href="http://joehewitt.com/2011/10/05/fast-animation-with-ios-webkit">maximum sizes of 1024x1024px in WebKit</a>).  If you do end up needing to animate from JavaScript, try using <a href="http://hacks.mozilla.org/2011/08/animating-with-javascript-from-setinterval-to-requestanimationframe/">requestAnimationFrame</a> as opposed to setTimeout/setInterval</li>
</ul>
<h3>Call for a focus on UI performance</h3>
<p>Performance is more than pushing bytes over a fence into a browser!  Much of the user&#8217;s experience happens after a page loads, so we should still be concerned about the performance of a &#8220;loaded page&#8221; experience.  This applies to our JavaScript, but equally as important is our CSS and its impact on scroll speed and overall UI responsiveness.</p>
<p>This might mean that we are sometimes better off using images instead of new CSS fanciness that&#8217;s not yet ready for primetime, and it&#8217;s up to us to weigh the cost and understand the tradeoff!  It also helps us appreciate new CSS features or fancy demos while remaining skeptical of their practical use.</p>
<p>More than anything, if you struggled with a UI performance issue and overcame it, the world could learn from your experience!  When you blog about it, you save other folks some time &#8211; time that could be spending with their families, which is definitely more important.  We need more articles from folks like <a href="http://calendar.perfplanet.com/2011/pure-css3-images-hmm-maybe-later/">Marcel</a> and <a href="http://calendar.perfplanet.com/2011/mobile-ui-performance-considerations/">Estelle</a>, who understand that performance goes beyond saving bytes.</p>
<p>So get to it!  But first, enjoy your time off.  Happy holidays and merry Christmas!</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/beyond-bandwidth-ui-performance/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A Simple Way to Measure Website Performance</title>
		<link>http://calendar.perfplanet.com/2011/a-simple-way-to-measure-website-performance/</link>
		<comments>http://calendar.perfplanet.com/2011/a-simple-way-to-measure-website-performance/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 05:13:52 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1433</guid>
		<description><![CDATA[Pavel shows how to collect and track performance data over time using Selenium and BrowserMob and posting the results to HARStorage.com]]></description>
			<content:encoded><![CDATA[<p>About a half year ago folks from Neustar demonstrated at <a href="http://velocityconf.com/velocity2011/public/schedule/detail/18282">Velocity Conference</a> possibility of effective client-side performance testing using only free, open-source solutions. They introduced bundle of tools, such as <a href="http://code.google.com/p/selenium/">Selenium</a> and <a href="http://opensource.webmetrics.com/browsermob-proxy/">BrowserMob Proxy</a>. The first one is intended to automate emulation of user interactions, the second one is a good for metric capturing. That was really inspiring presentation.</p>
<p>The greatest feature of their approach was the fact that all performance data are consolidated into single container &#8211; HTTP Archive (<a href="http://www.softwareishard.com/blog/har-12-spec/">HAR</a>). It makes further processing of test results more controlled and predictable due to strict format standardization.</p>
<p>However, there were no advanced tools for dealing with HAR files at that moment. HAR Viewer is wonderful but is not suitable for common testing workflow. ShowSlow is instead a perfect example of repository for automated performance measurement. Unfortunately handling of HAR files is not the strongest trait of it. So new project <a href="http://code.google.com/p/harstorage/">HAR Storage</a> appeared.</p>
<h3>Concept</h3>
<p>Testing process is rather straightforward. All you need is to create Selenium script which describes common user actions. Then you arm your script with methods to control proxy server via its API. It not only means capturing and storing stream of HTTP requests but also customization of network characteristics (e.g., bandwidth and latency) and traffic filtering. The last point is extremely important for analysis of impact of third-party components on overall site performance.</p>
<p>Finally you can send HAR of each page or asynchronous event to local repository &#8211; HAR Storage. Actually, <a href="http://harstorage.com/">HAR Storage</a> is a simple web application built on Pylons and MongoDB. It allows extracting detailed metrics from HAR files, storing test results and visualizing all gathered data.</p>
<h3>Advantages</h3>
<p>The key advantage is high flexibility. With BrowserMob Proxy use can test website in any modern browser that supports custom proxy settings. You can even deal with mobile browsers.</p>
<p>Selenium in turn makes it possible to simulate any sophisticated user scenario. Therefore you can analyze both speed of single page and performance of complex business transactions.</p>
<p>HAR Storage has cool features too. For instance, you can compare results of different tests. This is a great help for analysis of third-party party content or for investigation of relationship between site speed and network quality.</p>
<p><img src="http://img543.imageshack.us/img543/5407/performancetrends.png" alt="Performance Trends" /></p>
<p>At least with HAR Storage you can continuously track performance of your web site or application at any development phase.</p>
<h3>Limitation</h3>
<p>Nothing is perfect in this world. BrowserMob proxy runs outside the browser and on the one hand has minimal impact on its performance; on the other hand, internal browser events are inaccessible. Thus you can&#8217;t estimate performance of rendering or JavaScript parsing. Tools like <a href="http://ajax.dynatrace.com/ajax/en/">dynaTrace AJAX Edition</a> is more suitable for such tasks.</p>
<p>This approach may seem too complicated to some people. In fact it isn&#8217;t <a href="http://www.webpagetest.org/">WebPagetest.org</a> where you can simply put the URL and enjoy the result. But if you need real cross-browser testing, measurements over time and implementation of complex use cases &#8211; this method will work for you.</p>
<h3>Conclusion</h3>
<p>Web performance is still critical aspect, and performance testing is still a challenge. Frameworks based on Selenium, BrowserMob Proxy and HAR Storage may become an ultimate solution for many growing projects.</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/a-simple-way-to-measure-website-performance/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Performance testing with Selenium and javascript</title>
		<link>http://calendar.perfplanet.com/2011/performance-testing-with-selenium-and-javascript/</link>
		<comments>http://calendar.perfplanet.com/2011/performance-testing-with-selenium-and-javascript/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 06:10:25 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1432</guid>
		<description><![CDATA[JP shows us hot to build a performance test suite using open source tools]]></description>
			<content:encoded><![CDATA[<p>Nowadays many websites employ real user monitoring tools such as <a href="http://newrelic.com/features/real-user-monitoring">New Relic</a> or <a href="http://www.compuware.com/application-performance-management/real-user-monitoring.html">Gomez</a> to measure performance of production applications. Those tools provide a great value by giving real time metrics and allow engineers to identify and address eventual performance bottlenecks.</p>
<p>This works well for live deployed applications, but what about a staged setup? Engineers might want to look at the performance before deploying to production, perhaps while going through a QA process. They may want to find possible performance regressions or make sure a new feature is fast. The staged setup could reside on a corporate network however restricting the use of RUM tools mentioned earlier.</p>
<p>And what about an application hosted in a firewalled environment? Not all web applications are publicly hosted on the Internet. Some are installed in private data centers for internal use only (think about an intranet type of setup).</p>
<p>How can you watch application performance in these types of scenarios? In this blog post, I&#8217;ll explain how we leveraged open source software to build our performance test suite.</p>
<h3>Recording data</h3>
<p>The initial step is to record data. For that purpose we use a bit of custom code that records time spent on multiple layers: front end, web tier, backend web services and database.</p>
<p>Our web tier is a traditional server side MVC application that generates an HTML page for the browser (we use PHP and the Zend Framework, but this could apply to any other technology stack). First, we store the time at which the server side script started, right before we invoke the MVC framework:</p>
<div class="hl-main">
<pre><span class="hl-inlinetags">&lt;?php</span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> store script start time in microseconds</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-reserved">define</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">START_TIME</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">microtime</span><span class="hl-brackets">(</span><span class="hl-reserved">TRUE</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-inlinetags">?&gt;</span></pre>
</div>
<p>Secondly when the MVC framework is ready to buffer the page back to the browser, we insert some inline javascript code which includes:</p>
<ul>
<li>the captured start time (&#8220;request time&#8221;)</li>
<li>the current time (&#8220;response time&#8221;)</li>
<li>the total time spent doing backend calls (How do we know this information? Our web service client keeps track of the time spent doing webservice calls; and with each webservice response, the backend include the time spent doing database calls).</li>
</ul>
<p>In addition to those metrics, we include some jquery code to capture:</p>
<ul>
<li>the document ready event time</li>
<li>the window onload event time</li>
<li>the time of the last click (which we store in a cookie for the next page load)</li>
</ul>
<p>In other words, in in our HTML document (somewhere towards the end) we have a few lines of javascript that look like this:</p>
<div class="hl-main">
<pre><span class="hl-code">&lt;</span><span class="hl-identifier">script</span><span class="hl-code">&gt;
</span><span class="hl-identifier">Perf</span><span class="hl-code"> = </span><span class="hl-identifier">Perf</span><span class="hl-code"> || </span><span class="hl-brackets">{</span><span class="hl-brackets">}</span><span class="hl-code">;
</span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">requestTime</span><span class="hl-code"> = &lt;?= </span><span class="hl-identifier">START_TIME</span><span class="hl-code"> ?&gt;;
</span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">responseTime</span><span class="hl-code"> = &lt;?= </span><span class="hl-identifier">microtime</span><span class="hl-brackets">(</span><span class="hl-identifier">TRUE</span><span class="hl-brackets">)</span><span class="hl-code"> ?&gt;;
</span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">wsTime</span><span class="hl-code"> = &lt;?= $</span><span class="hl-identifier">wsTime</span><span class="hl-code"> ?&gt;;
</span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">dbTime</span><span class="hl-code"> = &lt;?= $</span><span class="hl-identifier">soapTime</span><span class="hl-code"> ?&gt;;
$</span><span class="hl-brackets">(</span><span class="hl-builtin">document</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">ready</span><span class="hl-brackets">(</span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-brackets">{</span><span class="hl-code">
  </span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">readyTime</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-builtin">Date</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">getTime</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">/</span><span class="hl-number">1000</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-brackets">)</span><span class="hl-code">;
$</span><span class="hl-brackets">(</span><span class="hl-builtin">window</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">bind</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">load</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-brackets">{</span><span class="hl-code">
  </span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">renderTime</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-builtin">Date</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">getTime</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">/</span><span class="hl-number">1000</span><span class="hl-code">;
  </span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">clickTime</span><span class="hl-code"> = </span><span class="hl-identifier">getLastClickTime</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-brackets">)</span><span class="hl-code">;
$</span><span class="hl-brackets">(</span><span class="hl-builtin">window</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">bind</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">unload</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-brackets">{</span><span class="hl-code">
  </span><span class="hl-identifier">storeLastClickTime</span><span class="hl-brackets">(</span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-builtin">Date</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">getTime</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">/</span><span class="hl-number">1000</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-brackets">)</span><span class="hl-code">;
&lt;/</span><span class="hl-identifier">script</span><span class="hl-code">&gt;</span></pre>
</div>
<p>Finally we insert a couple more javascript lines in the head tag, so that we can record an approximate time at which the page was received by the browser. As Alois Reitbauer pointed out in <a href="http://calendar.perfplanet.com/2011/timing-the-web/">Timing the Web</a>, this is an approximation as it does not account for things like DNS lookups.</p>
<div class="hl-main">
<pre><span class="hl-code">&lt;</span><span class="hl-identifier">head</span><span class="hl-code">&gt;
&lt;</span><span class="hl-identifier">script</span><span class="hl-code">&gt;
</span><span class="hl-identifier">Perf</span><span class="hl-code"> = </span><span class="hl-identifier">Perf</span><span class="hl-code"> || </span><span class="hl-brackets">{</span><span class="hl-brackets">}</span><span class="hl-code">;
</span><span class="hl-identifier">Perf</span><span class="hl-code">.</span><span class="hl-identifier">receivedTime</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-builtin">Date</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">getTime</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">/</span><span class="hl-number">1000</span><span class="hl-code">;
&lt;/</span><span class="hl-identifier">script</span><span class="hl-code">&gt;
</span><span class="hl-brackets">[</span><span class="hl-code">...</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-identifier">more</span><span class="hl-code"> </span><span class="hl-identifier">code</span><span class="hl-code"> </span><span class="hl-brackets">[</span><span class="hl-code">...</span><span class="hl-brackets">]</span><span class="hl-code">
&lt;/</span><span class="hl-identifier">head</span><span class="hl-code">&gt;</span></pre>
</div>
<p>Now that we have some metrics for a given request in the browser, how do we retrieve them so that we can examine them?</p>
<h3>Collecting and analyzing the data</h3>
<p>This is where Selenium comes into play. We use Selenium to simulate a person using our web application. Again this is technology agnostic as you can control Selenium from various languages (we use PHP and PHPUnit, but you could do the same with python or ruby).</p>
<p>Selenium has an API which you can call to invoke some javascript snippet and get back the output of the executed code. This API is called <code>getEval</code>.</p>
<p>Within our test code, we first open a page we want to analyze, then use the <code>getEval</code> API to retrieve the metrics we recorded and finish with storing the metrics for later consumption.</p>
<div class="hl-main">
<pre><span class="hl-reserved">class</span><span class="hl-code"> </span><span class="hl-identifier">ExampleSeleniumTest</span><span class="hl-code"> </span><span class="hl-reserved">extends</span><span class="hl-code"> </span><span class="hl-identifier">PHPUnit_Extensions_SeleniumTestCase</span><span class="hl-code">
</span><span class="hl-brackets">{</span><span class="hl-code">
  </span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-identifier">testLoadSomePage</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">
  </span><span class="hl-brackets">{</span><span class="hl-code">
    </span><span class="hl-comment">//</span><span class="hl-comment"> Open our web application</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-var">$this</span><span class="hl-code">-&gt;</span><span class="hl-identifier">open</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">/</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-comment">//</span><span class="hl-comment"> Click a link to load the page we want to analyze</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-var">$this</span><span class="hl-code">-&gt;</span><span class="hl-identifier">clickAndWait</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">Some Page</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">
    </span><span class="hl-comment">//</span><span class="hl-comment"> Use getEval API to retrieve the metrics we recorded</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-var">$metrics</span><span class="hl-code"> = </span><span class="hl-var">$this</span><span class="hl-code">-&gt;</span><span class="hl-identifier">getEval</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">window.Perf</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-comment">//</span><span class="hl-comment"> Call our internal method that will store the metrics for later use</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-comment">//</span><span class="hl-comment"> </span><span class="hl-inlinedoc">Note:</span><span class="hl-comment"> we include a reference to the page or to what use case we are testing</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-var">$this</span><span class="hl-code">-&gt;</span><span class="hl-identifier">saveMetrics</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">some-page</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-var">$metrics</span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-brackets">}</span></pre>
</div>
<p>We use this pattern for multiple use cases in our application. Also note that while I used the example of a full page load, our framework also supports collecting metrics for AJAX interactions, which we do quite a lot (for instance remotely loading content triggered by a user click).</p>
<p>One of the great things about using Selenium is multiple browser support. We have a set of virtual machines running various versions of Internet Explorer and Firefox. This enables our performance test suite to run across multiple platforms.</p>
<p>The last piece of the puzzle is analyzing the data we collected. For this purpose we built a small database driven application which reads the metrics we collected and plot them. We can apply filters such as specific browser vendor or version, specific use case, specific version of our software, etc. We can then look at the complete data over time.</p>
<p>Here is the logic we use to plot the data we collected:</p>
<p><img src="/wp-content/uploads/2011/12/jp-web-request.png" alt="Web request times"></p>
<h3>Sample results</h3>
<p>This is an example of chart generated after collecting data:</p>
<p><img src="/wp-content/uploads/2011/12/jp-web-timings-sample.png" alt="Web timings sample"></p>
<p>In the above sample, we can observe a client side performance issue in Sample 1, some inefficient code in the backend web services in Sample 2 and a slow database query in Sample 3.</p>
<h3>Benefits</h3>
<p>When we built this framework in 2009 we had multiple goals in mind:</p>
<ul>
<li>Monitor performance between our software release and catch eventual regressions</li>
<li>Monitor performance of upcoming features</li>
<li>Monitor the scalability of the software as we add more users/more data</li>
</ul>
<p>Looking back, this tool yielded some great results and here are a few examples:</p>
<ul>
<li>Discovery of bugs in our javascript code that would result in much higher load times in IE</li>
<li>Found issues in the way we were manipulating HTML with javascript and were able to improve the responsiveness of the impacted user interactions</li>
<li>Eliminated bottlenecks in our backend web services as we raised the amount of data: we were able to pin point exactly where the problem was (inefficient backend code, slow database queries, etc.)</li>
</ul>
<h3>Closing words</h3>
<p>In conclusion, I&#8217;d like to look into some ideas we have in mind to improve our setup.</p>
<p>I&#8217;d like to use the tool more often. We currently run the test suite several times during our development process and before each releases, but this is a manual process. It would be great to tie in the test suite with our Jenkins CI builds. A different idea would be to ship the tool as part of our product and run it in production providing us with some analytics on real world usage of our platform.</p>
<p>As I mentioned, we are using virtual machines to test on multiple platforms. This adds a bit of overhead in terms of maintenance. Maybe we should look at the hosted Selenium solution from <a href="http://saucelabs.com/ondemand">Sauce labs</a>?</p>
<p>When we built the product, the performance landscape was a bit different and there are tools today that were not available back then. Would we see any benefits if we were to leverage <a href="http://code.google.com/p/webpagetest/">Webpagetest</a>, <a href="https://github.com/yahoo/boomerang">boomerang</a>, etc.?</p>
<h3>Credits</h3>
<p>I&#8217;d like to acknowledge <a href="http://billwscott.com/">Bill Scott</a> for his <a href="http://billwscott.com/share/presentations/2008/stanford/HPWP-RealWorld.pdf">presentation on RUM at Netflix</a> which inspired us to build our framework.</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/performance-testing-with-selenium-and-javascript/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Lossy Image Compression</title>
		<link>http://calendar.perfplanet.com/2011/lossy-image-compression/</link>
		<comments>http://calendar.perfplanet.com/2011/lossy-image-compression/#comments</comments>
		<pubDate>Sun, 25 Dec 2011 01:18:32 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[images]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1431</guid>
		<description><![CDATA[Images on our websites are the largest payload sent back and forth across the wires of the net taking big part in slowing down user experience. Do you do the <i>lossless</i> image optimization with tools like jpegtran and pngout? How about <i>lossy</i> optimizations?]]></description>
			<content:encoded><![CDATA[<p>Images are the one of the oldest items on the web (right after HTML) and still so little has changed since we started to use them. Yes, we now got JPEG and PNG in addition to original GIF, but other then that there were not many improvements to make them better.</p>
<p>That if you don&#8217;t count lots of creative talent that went into creating them, so much in fact that it created the web as we know now, reach, shiny and full of marketing potential! Without images we wouldn&#8217;t have the job of building the web, and without images we wouldn&#8217;t worry about web performance because there would be no users to care about experience and no business people to pay for improvements.</p>
<p>That being said, images on our websites are the largest payload sent back and forth across the wires of the net taking big part in slowing down user experience.</p>
<p><a href="http://httparchive.org/interesting.php#bytesperpage" target="_blank">According to HTTPArchive</a>, JPEGs, GIFs and PNGs account for <b>63% of overall page size</b></p>
<p><a href="http://httparchive.org/interesting.php#bytesperpage" target="_blank"><img width="400" height="225" src="http://chart.apis.google.com/chart?chs=400x225&#038;cht=p&#038;chco=007099&#038;chd=t:42,598,172,33,90,30&#038;chds=0,598&#038;chdlp=b&#038;chdl=total%20965%20kB&#038;chl=HTML+-+42+kB%7CImages+-+598+kB%7CScripts+-+172+kB%7CStylesheets+-+33+kB%7CFlash+-+90+kB%7COther+-+30+kB&#038;chma=|5&#038;chtt=Average+Bytes+per+Page+by+Content+Type" border="0"/></a></p>
<p>and overall image size has <a href="http://httparchive.org/interesting.php#onLoad" target="_blank">0.64 correlation with overall page load time</a>.</p>
<p><a href="http://httparchive.org/interesting.php#onLoad" target="_blank"><img width="500" height="225" src="http://chart.apis.google.com/chart?chxl=1:|Total+Xfer+Size%7CTotal+Reqs%7CImage+Xfer+Size%7CImage+Reqs%7CJS+Reqs&#038;chxr=0,0,1&#038;chxs=1,676767,11.5,0,lt,67676700&#038;chxtc=1,5&#038;chxt=y,x&#038;chbh=60,30,30&#038;chs=500x225&#038;cht=bvg&#038;chco=80C65A&#038;chds=0,1&#038;chd=t:0.73,0.66,0.64,0.62,0.42&#038;chm=N,676767,0,,12,,::4&#038;chtt=Highest+Correlation+to+Load+Time" border="0"/></a>
</p>
<p>Still we can safely assume that <b>we are going to have only more images and they will only grow bigger</b>, along with the screen resolutions on desktop computers.</p>
<h2>Lossy compression</h2>
<p>There are a few different ways to optimize images including compression, spriting, picking appropriate format, resizing and so on. There are many other aspects of handling images that include postloading, caching, URL versioning, CDNs and etc.</p>
<p>In this article I wanted to concentrate on <b>lossy compression</b> where <b>quality characteristics of the images are changed</b> without significant visual differences for the user, but <b>with significant changes to performance</b>.</p>
<p>By now most of us are familiar with loss-less compression, thanks to <a href="http://www.phpied.com/" target="_blank">Stoyan</a> and <a href="http://www.stubbornella.org/">Nicole</a> who first introduced us to image optimization for web performance with an awesome on-line tool called <a href="http://www.smushit.com/ysmush.it/" target="_blank">Smush.it</a> (now ran by Yahoo). There are a few other tools now that have similar functionality for PNG, for example.</p>
<p>With smush.it and alike image quality is preserved as is with only unnecessary meta-data removed, it often saves up to 30-40% of file size. It is a safe choice and images will be intact when you do that. This seems the only way to go, especially for your design department who believe that once image comes out of their computers it is sacred and must be preserved absolutely the same.</p>
<p>In reality, quality of the image is not set in stone &#8211; JPEG was invented as a format that allowed for size reduction at a price of quality. Web got popular because of images, it wouldn&#8217;t be here if they were in BMP, TIFF or PCX formats that were dominating prior to JPEG.</p>
<p><img src="http://www.sergeychernyshev.com/lossy/photoshow_export_for_web_and_devices.png" width="373" height="205" style="float: right; margin: 0.5em 0 0.5em 0.5em"/></p>
<p>This is why we need to actually start using this feature of JPEG where quality is adjustable. You probably even saw it in settings if you used export functionality of photo editors &#8211; here&#8217;s the screenshot of quality adjusting section of &#8220;export for web and devices&#8221; screen in Adobe Photoshop.</p>
<p>Quality setting ranges from 1 to 100 with 75 usually being enough for all of the photos with some of them looking good enough even with the value of 30. In Photoshop and other tools you can usually see the differences using your own eyes and adjust appropriately making sure quality never degrades below certain point that mainly depends on the image.</p>
<p>Resulting image size heavily depends on the original source of the image and visual features of the picture sometimes saving up to 80% of the size without significant degradation.</p>
<p>I know these numbers sound pretty vague, but that is exactly the problem that all of us faced when <b>we needed to automate image optimization</b>. All images are different and without having a person looking at them, it&#8217;s <b>impossible to predict</b> if fixed quality setting will be damaging the images or not saving enough. Unfortunately having a human editor in the middle of the process is costly, time consuming and sometimes simply impossible, for example when UGC (user-generated content) is used on the site.</p>
<p>I was bothered by this problem since I saw smush.it doing great job for lossless compression. Luckily, this year two tools emerged that allow for automation of lossy image compression: one open source tool was developed specifically for WPO purposes by my former co-worker, Ryan Flynn and called <a href="https://github.com/rflynn/imgmin" target="_blank">ImgMin</a> and another is a commercial tool called <a href="http://www.jpegmini.com" target="_blank">JPEGmini</a> which came out of consumer photo size reduction.</p>
<p>I can&#8217;t talk for JPEGmini, <a href="http://www.jpegmini.com/main/technology">their technology</a> is private with patents pending, but ImgMin uses a simple approach of trying different quality settings and then picking the result that has the picture difference within a certain threshold. There are a few other simple heuristics, for more details you can read <a href="https://github.com/rflynn/imgmin#readme" target="_blank">ImgMin&#8217;s documentation on Github</a>.</p>
<p>Both of the tools work pretty well providing different results with ImgMin in it&#8217;s simplicity being less precise. JPEGmini offers dedicated server solution with cloud service coming soon.</p>
<p>In this table you can see my twitter userpic and how it was <b>automatically</b> optimized using loss-less (smush.it) and loss-y (JPEGmini) compression:</p>
<table border="0" cellpadding="5" cellspacing="0">
<tr>
<td><img src="http://www.sergeychernyshev.com/lossy/sergey_reasonably_small.jpg" width="128" height="128"/></td>
<td><img src="http://www.sergeychernyshev.com/lossy/sergey_reasonably_small_smushit.jpg" width="128" height="128"/></td>
<td><img src="http://www.sergeychernyshev.com/lossy/sergey_reasonably_small_jpegmini.jpg" width="128" height="128"/></td>
</tr>
<tr valign="top">
<td>Original:</br>10028 bytes</td>
<td>Lossless:</br>9834 bytes</br>2% savings</td>
<td><b>Lossy:</br>4238 bytes</br>58% savings</b></td>
</tr>
</table>
<p>Notice no perceivable quality degradation between original and optimized images. Results are astonishingly similar on larger photos as well.</p>
<p>This is great news as <b>it will finally allow us to automate lossy compression</b> which was always a manual process &#8211; now you can rely on a tool and reliably build it into your image processing pipeline!</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/lossy-image-compression/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Why you’re probably reading your performance measurement results wrong (but at least you’re in good company)</title>
		<link>http://calendar.perfplanet.com/2011/good-company/</link>
		<comments>http://calendar.perfplanet.com/2011/good-company/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 02:30:48 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1430</guid>
		<description><![CDATA[Measuring performance is one thing, actually looking at the data we collect is another. And just as important is looking at how we look at data and how we judge the results and takeaways. Otherwise all else goes to waste. Josh Bixby has tips for reading performance data and avoiding jumping to quick conclusions which could often be wrong.]]></description>
			<content:encoded><![CDATA[<p>One of my favourite books of 2011 was <a href="http://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374275637">Thinking, Fast and Slow</a> by the Nobel Prize-winning psychologist Daniel Kahneman. In his book, Kahneman identifies the two systems of thought that are constantly warring inside our heads:</p>
<ul>
<li>System 1, which is fast and intuitive, and
<li>System 2, which is slow and logical.
</ul>
<p>Almost invariably, System 1 is flawed, yet we helplessly rely on it. We also have a painful tendency to think we’re applying System 2 to our thinking, when in fact it’s just an intellectually tarted up version of System 1.</p>
<p>Kahneman offers a nifty little test of this thinking:</p>
<p>“A certain town is served by two hospitals. In the larger hospital about 45 babies are born each day, and in the smaller hospital about 15 babies are born each day. As you know, about 50% of all babies are boys. However the exact percentage varies from day to day. Sometimes it may be higher than 50%, sometimes lower. For a period of 1 year, each hospital recorded the days on which more than 60% of the babies born were boys. Which hospital do you think recorded more such days?”</p>
<ol>
<li style="list-style: upper-alpha">The larger hospital
<li style="list-style: upper-alpha">The smaller hospital
<li style="list-style: upper-alpha">About the same (that is, within 5% of each other)
</ol>
<p>The correct answer is B, the smaller hospital. But as Kahneman notes, “When this question was posed to a number of undergraduate students, 22% said A; 22% said B; and 56% said C. <strong>Sampling theory entails that the expected number of days on which more than 60% of the babies are boys is much greater in the small hospital than in the large hospital, because the large sample is less likely to stray from 50%.</strong> This fundamental notion of statistics is evidently not part of people’s repertoire of intuition.”</p>
<p>But these are just a bunch of cheese-eating undergrads, right? This doesn’t apply to our community, because we’re all great intuitive statisticians? What was the point of that computer science degree if it didn’t allow you a powerful and immediate grasp of stats?</p>
<p>Thinking about Kahneman’s findings, I decided to conduct a little test of my own, to see how well your average friendly neighbourhood web performance expert is able to analyze statistics. (Identities have been hidden to protect the innocent.) <a href="#foot" id="footback">*</a></p>
<h3>The methodology</h3>
<p>I asked 10 very senior and well-respected members of our community to answer the hospital question, above. I also asked them to comment on the results of this little test:</p>
<p>The following RUM results capture one day of activity on a specific product page for a large e-commerce site for IE9 and Chrome 16. What conclusions would you draw from this table?</p>
<p><img src="/wp-content/uploads/2011/12/josh1.png"></p>
<h3>The results</h3>
<p>If you had to summarize this table, you would probably conclude “Chrome is faster than IE9.” That&#8217;s the story you take away from looking at the table, and you intuitively are drawn to it because that&#8217;s the part that&#8217;s interesting to you. The fact the study was done using a specific product page, captures one day of data, or contains 45 timing samples for Chrome is good background information, but isn’t relevant to the overall story. Your summary would be the same regardless of the size of the sample, though an absurd sample size (i.e. results captures from 2 data points or 6 million data points) would probably grab your attention.</p>
<p><strong>Hospital question results:</strong><br />
On the hospital question, we were better than the undergrads… but not by much. 5 out of 10 people I surveyed got the question wrong.</p>
<p><strong>RUM results:</strong><br />
I was amazed at the lack of focus on the source of the data. Only 2 people pointed out that the sample size was so low that no meaningful conclusions could be drawn from the results, and that averages were useless for this type of analysis. The other 8 all focused on the (assumed) fact that Chrome is faster than IE9, and they told me stories about the improvements in Chrome and how the results are representative of these improvements.</p>
<h3>Conclusions</h3>
<p>The table and description contain information of two kinds: the story and the source of the story. Our natural tendency is to focus on the story rather than on the reliability of the source, and ultimately we trust our inner statistical gut feel. I am continually amazed at our general failure to appreciate the role of sample size. As a species, we are terrible intuitive statisticians. We are not adequately sensitive to sample size or how we should look at measurement.</p>
<h3>Why does this matter?</h3>
<p>RUM is being adopted in the enterprise at an unprecedented speed. It is becoming our measurement baseline and the ultimate source of truth. For those of us who care about making sites faster in the real world, this is an incredible victory in a long protracted <a href="http://www.webperformancetoday.com/2011/07/05/web-performance-measurement-island-is-sinking/">battle against traditional synthetic tests</a>.</p>
<p>I now routinely go into enterprises that use RUM. Although I take great satisfaction in winning the war, an important battle now confronts us.</p>
<h3>Takeaways</h3>
<p><strong>1. We need tools that warn us when our sample sizes are too small.</strong><br />
We all learned sampling techniques in high school or university. The risk of error can be calculated for any given sample size by a fairly simple procedure. Don’t use your judgement because it is flawed. Not only do we need to be vigilant but we need to lobby for the tool vendors to help us. Google, Gomez, Keynote and others should notify us when sample sizes are too small – especially given how prone we are to error.</p>
<p><strong>2. Averages are a bad measure for RUM results.</strong><br />
RUM results can suffer from significant outliers, which make averages a bad measure in most instances. Unfortunately, averages are used in almost all of the off-the-shelf products I know. If you need to look at one number, look at medians or 95th percentile numbers.</p>
<p><strong>3. Histograms are the best way to graph data.</strong><br />
With histograms you can see the distribution of performance measurements and, unlike averages, you can spot outliers that would otherwise skew your results. For example, I took a dataset of 500,000 page load time measurements for the same page. If I went with the average load time across all those samples, I&#8217;d get a page load time of ~6600msec. Now look at the histogram for all the measurements for the page, below. Visualizing the measurements in a histogram like this is much much more insightful and tells us a lot more about the performance profile of that page.</p>
<p><img src="/wp-content/uploads/2011/12/josh2.png"></p>
<p>(If you&#8217;re wondering, the median page load time across the data set is ~5350msec. This is probably a more accurate indicator of the page performance and much better than the average, but is not as telling as the histogram that lets us properly visualize the performance profile. As a matter of fact, here at Strangeloop, we usually look at both median and the performance histogram to get the full picture.)</p>
<p><a href="footback" id="foot">*</a> Of course, you’re allowed to call into question the validity of my test, given its small sample size. I’d be disappointed if you didn’t. <img src='http://calendar.perfplanet.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/good-company/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Advice on Trusting Advice</title>
		<link>http://calendar.perfplanet.com/2011/advice-on-trusting-advice/</link>
		<comments>http://calendar.perfplanet.com/2011/advice-on-trusting-advice/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 10:13:45 +0000</pubDate>
		<dc:creator>stoyan</dc:creator>
				<category><![CDATA[performance]]></category>
		<category><![CDATA[wpo]]></category>

		<guid isPermaLink="false">http://calendar.perfplanet.com/?p=1428</guid>
		<description><![CDATA[Eloquent as always, Billy Hoffman shares his thoughts on 3rd party content and 3rd party performance advice]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/2011/12/trust-no-one.jpg"></p>
<p>We all know that 3rd party content means you no longer control all the factors which affect page load time. A sleek, well-tuned, and optimized site can still deliver a poor user experience because of problems with 3rd party content. Steve Souders even used to publish <a href="http://stevesouders.com/p3pc/">a series of blog posts</a> where he <a href="http://www.stevesouders.com/blog/2010/02/17/performance-of-3rd-party-content/">analyzed and rated the performance of 3rd party content snippets</a>. (<em>Dear Steve, please bring this back, it was awesome</em>). <a href="http://twitter.com/mathias/">Mathias Bynens</a> took this one step further, showing how to <a href="http://mathiasbynens.be/notes/async-analytics-snippet">additionally  optimize Google&#8217;s markup and JavaScript snippets</a>.</p>
<p>The surprising lesson to learn from Steve and Mathias is that if you want a fast site <strong>and</strong> 3rd party widgets, then you need to examine the 3rd party content for performance problems, <strong>even when a snippet comes from a trusted authority on web performance</strong>. So this post isn&#8217;t really going to be about 3rd party content. It&#8217;s going to be about trusting advice. </p>
<p>Last week a Zoompf customer, the online precious metal exchange <a href="http://goldmoney.com">GoldMoney</a>, contacted Support about an issue our technology flagged on their site. We had detected an issue with Google&#8217;s JavaScript library for their Google+ button. Zoompf WPO was suggesting the customer do something which was contradicting Google&#8217;s advice. And that was enough to give GoldMoney pause.</p>
<p> The specific issue that Zoompf was flagging was that Google&#8217;s <code>plusone.js</code> library was being referenced using <a href="http://zoompf.com/blog/2010/03/zoompf-check-300-or-gateways-got-a-problem">SSL from a non-SSL page</a>. SSL is important because,  <a href="https://www.owasp.org/images/4/40/Ivan_Ristic_-_Breaking_SSL_-_OWASP.pdf">if used properly</a>, it provides communications privacy and integrity. However, a CSS file, or JavaScript library, or even a Favicon that is referenced using a SSL-enabled hyperlink from an HTML page which is not served over SSL most likely does not contain information that needs protecting. Since SSL provides these security features with a cost of a decrease in web performance (as discussed below), it is important to only use SSL when you have to.</p>
<p>In this case, the Google <code>plusone.js</code> button library does not contain personal or private information. Zoompf&#8217;s suggestion was to instead retrieve the Google+ library using <code>http://</code> instead of <code>https://</code>. Here is what Google&#8217;s documentation has to say (emphasis added):</p>
<blockquote><p>
The +1 button code requires a script from Google&#8217;s servers. You may get this error by including the script via <code>http://</code> on a page that&#8217;s loaded via <code>https://</code>. <strong>We recommend using <code>https://</code> to include the script</strong>:<br />
<code>&lt;script type=&quot;text/javascript&quot; src=&quot;https://apis.google.com/js/plusone.js&quot;&gt;&lt;/script&gt;</code><br />
If your web page uses <code>https://</code>, some browsers and verification tools will show an error when any assets on the page are called via http://. If your site serves pages via https://, make sure that the +1 button code on those pages also uses https://. (<strong>In fact, it&#8217;s fine to use <code>https://</code> in the button code for all pages, even if they are only served via <code>http://</code></strong>.)
</p></blockquote>
<p>The &#8220;error&#8221; that Google is trying to avoid is a mixed content warning. It looks like this:</p>
<p><img src="/wp-content/uploads/2011/12/mixed-content-warning.jpg"></p>
<p>A mixed content warning happens when an HTML page served with HTTPS references resources using HTTP. Due to some <a href="http://code.google.com/p/browsersec/wiki/Part2">serious design flaws</a> in modern browsers, mixed content can allow privileged  information like the DOM, cookies, referrer URLs, session IDs, and more to be access by untrusted parties. Browsers usually display a confusing dialog box or just fail to render the page, depending on its security settings. Google&#8217;s solution to avoid all is to just always request the <code>plusjone.js</code> file using SSL, even when SSL is not needed.</p>
<p>But using SSL, just for the fun of it, is not a good idea. SSL impacts web performance negatively in several ways:</p>
<ul>
<li><a href="http://www.semicomplete.com/blog/geekery/ssl-latency.html">HTTPS connections take longer to create than regular HTTP connections</a>. Additional requests may need to be sent to different servers to <a href="http://www.belshe.com/2011/04/20/certificate-validation-example-facebook/">validate the X.509 certificate chain</a> before the SSL connection can begin, causing all pending HTTPS connections to that server to block.</li>
<li>Establishing an HTTPS connection is computationally expensive. The browser and server must do <a href="http://www.bsc.es/media/389.pdf">a large amount of work during the SSL handshake</a> and more <a href="http://www.eecs.umich.edu/~taustin/papers/ASPLOS00-crypto.pdf">work encrypting and decrypting data</a> as it is sent. While computers are always getting faster SSL overhead is still sufficiently large that an entire market for <a href="http://en.wikipedia.org/wiki/SSL_acceleration">SSL acceleration</a> products exists.</li>
<li>Because HTTPS runs on a separate TCP/IP port than HTTP, your browser cannot use an existing HTTP connection as an HTTPS connection, even if you are talking to the same hostname.</li>
<li>Using SSL means inline devices like shared caching servers will not see the traffic and cannot be used to improve performance.</li>
<li>Browser <a href="http://blogs.msdn.com/b/ieinternals/archive/2010/04/21/internet-explorer-may-bypass-cache-for-cross-domain-https-content.aspx">caching of content served over SSL is more complicated than content over HTTP</a>. Depending on the browser and configuration, content may only be cached in RAM and discarded quickly, or require conditional requests not usually needed.</li>
</ul>
<p>In short, SSL is great but it&#8217;s not free. Don&#8217;t use it if you don&#8217;t have to.</p>
<p>
The solution here is to actually use a <a href="http://blog.httpwatch.com/2010/02/10/using-protocol-relative-urls-to-switch-between-http-and-https/">protocol relative URL</a>. A protocol relative URL is a way of referencing a resource on a different host name without specifying what protocol to use to retrieve. So instead of <code>src="https://apis.google.com/js/plusone.js"</code> you can use <code>src="//apis.google.com/js/plusone.js"</code>. Consider an HTML page which uses a protocol relative URL to reference <code>plusone.js</code>. If the page was served using <code>https://</code>, then <code>plusone.js</code> is requested using <code>https://</code>. Security is maintained and no mixed content security warning will appear. If the page was served using <code>http://</code>, then the library will be served using HTTP. No performance hit happens and no caching issues come up either.
</p>
<p>
Now, I know what you might be thinking. <em>&#8220;Did Stoyan seriously allow some guy a spot on the Performance Calendar to talk about protocol relative URLs for eleven paragraphs?&#8221;</em> Well yes, I did talk about something cool that many people are not familiar with and which provides an elegant solution to a surprising common problem. (If fact there tons of other stuff to talk about with protocol relative URLs, like <a href="http://paulirish.com/2010/the-protocol-relative-url/">a non-standard IE6 configuration which causes a weird certificate error</a>, or the <a href="http://www.stevesouders.com/blog/2010/02/10/5a-missing-schema-double-download/">double downloading bug</a> in IE7 and IE8. So count yourself lucky!) But as I said earlier, the magic of protocol relative URLs is not the point of this post.
</p>
<p>
The point of post is that you need to be careful about performance advice. Not just where you get it, but what it says to do. Google is awesome. They are one of the strongest supporters of web performance in the industry today. But no one is perfect. Mathias improved upon their Google Analytics snippet. Their Google Doodles are always <a href="https://twitter.com/zoompf/status/144920292446306305">ludicrously high quality JPEGs that needlessly waste bandwidth</a>. And sometimes, like in this case, their advice is not just right. As the Buddha once said:
</p>
<blockquote><p>
Believe nothing, no matter where you read it, or who has said it, not even if I have said it, unless it agrees with your own reason and your own common sense.
</p></blockquote>
<p>
You should always examine a code snippet from a 3rd party before including it in your site, regardless of who wrote it, even if Steve Souders or Douglas Crockford or John Resig wrote it, to make sure it does not violate any best practices that you already know.</p>
]]></content:encoded>
			<wfw:commentRss>http://calendar.perfplanet.com/2011/advice-on-trusting-advice/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

