<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

  <title><![CDATA[Andy Davies]]></title>
  
  <link href="http://andydavies.me/" />
  <updated>2013-04-30T21:06:23+01:00</updated>
  <id>http://andydavies.me/</id>
  <author>
    <name><![CDATA[Andy Davies]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/andydavies" /><feedburner:info uri="andydavies" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title type="html"><![CDATA[Adding iOS agents to a WebPagetest Instance]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/wXIf7kVElLM/" />
    <updated>2013-03-05T07:49:00+00:00</updated>
    <id>http://andydavies.me/blog/2013/03/05/adding-ios-test-agents-to-a-webpagetest-instance</id>
    <content type="html">&lt;p&gt;Back in September I explained how to create a private instance of Web Page Test running IE, Firefox and Chrome on Windows 7.&lt;/p&gt;

&lt;p&gt;Recently I needed to add some iOS agents, after a bit of trial and error this is the approach I used.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;I&amp;#8217;ve added the mobile agents to my existing &amp;#8216;all-in-one&amp;#8217; WebPageTest instance so if you&amp;#8217;ve not read the original post it&amp;#8217;s worth having a quick scan first: &lt;a href="http://andydavies.me/blog/2012/09/18/how-to-create-an-all-in-one-webpagetest-private-instance/"&gt;Configuring an ‘all-in-one’ WebPageTest Private Instance&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At a minimum you&amp;#8217;ll need access to a Mac with Xcode and iOS Simulator installed. If you want to use a real device as a test agent you will need an iPhone or iPad and an iOS developer account.&lt;/p&gt;

&lt;h1&gt;Building the Mobitest Agent&lt;/h1&gt;

&lt;p&gt;Confusingly there&amp;#8217;s some source code for a mobile agent in the WebPageTest SVN respository but as I discovered that&amp;#8217;s not the source we want!&lt;/p&gt;

&lt;p&gt;We want the code for the Mobiletest agent that &lt;a href="https://twitter.com/guypod"&gt;Guy Podjarny&lt;/a&gt; &amp;amp; Co created at Blaze (now part of Akamai).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the Mobitest source &lt;code&gt;https://code.google.com/p/mobitest-agent/source/checkout&lt;/code&gt; and build it using Xcode.&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Install and Configure the Agent&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Using Xcode launch the Mobitest App on the iOS Simulator or a physical device.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Mobitest has a set of default settings that need updating to match the WebPageTest instance, for example:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/mobitest-settings.png" title="'Default and configured Mobitest settings'" &gt;&lt;br&gt;
Default settings on left, settings for my install on right.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Update &lt;em&gt;Jobs URL 1&lt;/em&gt; to match the URL of your WebPageTest instance, and set the &lt;em&gt;Unique Agent Name&lt;/em&gt; and &lt;em&gt;Location&lt;/em&gt; (location must match the location you configure in WebPageTest).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unless you are using using keys you&amp;#8217;ll need to remove the default &lt;em&gt;Location Key&lt;/em&gt; too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I also enable &lt;em&gt;Restart After Each Job&lt;/em&gt; and &lt;em&gt;Auto-Poll&lt;/em&gt; (scroll down for these settings)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go back to the iOS home screen, launch Mobitest, press &lt;em&gt;Poll Now&lt;/em&gt; and the agent should now poll the server for jobs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Add the agent to WebPageTest&lt;/h1&gt;

&lt;p&gt;Once the test agent is up and running we need to update WebPageTest&amp;#8217;s configuration so jobs can be scheduled for the new agent.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit &lt;code&gt;settings\locations.ini&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Add the new agent under the relevant location section (&lt;code&gt;[Local]&lt;/code&gt; and &lt;code&gt;3=Local-iPhone&lt;/code&gt; in the example below)&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;[Local]
&lt;/span&gt;&lt;span class='line'&gt;1=Local-URLBlast
&lt;/span&gt;&lt;span class='line'&gt;2=Local-WPTDriver
&lt;/span&gt;&lt;span class='line'&gt;3=Local-iPhone
&lt;/span&gt;&lt;span class='line'&gt;label=Local&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;ul&gt;
&lt;li&gt;Add a section for the agent itself.&lt;/li&gt;
&lt;/ul&gt;


&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;[Local-iPhone]
&lt;/span&gt;&lt;span class='line'&gt;browser=iPhone
&lt;/span&gt;&lt;span class='line'&gt;connectivity=3G
&lt;/span&gt;&lt;span class='line'&gt;label="Local"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;&lt;strong&gt;N.B. Section name must match the name set in &lt;code&gt;[Local]&lt;/code&gt; and the Location field of Mobitest Agent settings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save &lt;code&gt;locations.ini&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Check it&amp;#8217;s working&lt;/h1&gt;

&lt;p&gt;I find getLocations.php to be the easiest way of checking agents are configured correctly and requesting jobs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;code&gt;http://192.168.0.12/getLocations.php&lt;/code&gt; (replace IP address with your WebPageTest URL) in your browser and you should see a list of all the current test agents, their status, and the number of jobs in their queues e.g.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/getlocations.png" title="'Status of WebPageTest agents'" &gt;&lt;br&gt;
List of test agents and their current status (priorities 2-8 omitted from table)&lt;/p&gt;

&lt;p&gt;If either &lt;em&gt;Idle Testers&lt;/em&gt; or &lt;em&gt;Being Tested&lt;/em&gt; columns are greater than zero then the test agent is successfully communicating with the WebPageTest instance.&lt;/p&gt;

&lt;p&gt;You should now be able to use the normal WebPageTest interface to run tests on the device you&amp;#8217;ve just configured.&lt;/p&gt;

&lt;h1&gt;Shaping the Connection&lt;/h1&gt;

&lt;p&gt;On &lt;a href="http://webpagetest.org"&gt;http://webpagetest.org&lt;/a&gt;, the mobile agents connect via WiFi to a Linux bridge that shapes the network connection.&lt;/p&gt;

&lt;p&gt;For my testing I use the Network Link Conditioner that&amp;#8217;s available on iOS devices registered for development (&lt;em&gt;Settings&lt;/em&gt; &gt; &lt;em&gt;Developer&lt;/em&gt; &gt; &lt;em&gt;Network Link Conditioner&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re using the iOS Simulator for testing then unfortunately the Network Link Conditioner isn&amp;#8217;t installed. You can use the OSX version of the Network Link Condition instead but that will shape the connection for the whole of OSX.&lt;/p&gt;

&lt;p&gt;In either situation you can force the WebPageTest connection dropdown to only show a single label by adding a &lt;code&gt;connectivity&lt;/code&gt; entry to the location in &lt;code&gt;settings.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the example below I&amp;#8217;ve added a label that matches the Network Link Conditioner settings for 3G.&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;[Local-iPhone]
&lt;/span&gt;&lt;span class='line'&gt;browser=iPhone
&lt;/span&gt;&lt;span class='line'&gt;connectivity=3G (780/330 Kbps 100ms RTT)
&lt;/span&gt;&lt;span class='line'&gt;label="Local"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Unlike the PC based agents this setting doesn&amp;#8217;t have any influence over the actual connection settings used and they will always need to be configured separately.&lt;/p&gt;

&lt;h1&gt;Some other things to note&lt;/h1&gt;

&lt;p&gt;The Mobitest Agent uses a UIWebView rather than Safari, so any JavaScript on the page won&amp;#8217;t use the JIT and this may be an issue on Javascript heavy pages. This blog gets roughly the same number of visitors inApp on iOS i.e. UIWebView, as it does from iOS Safari so the UIWebView experience matters.&lt;/p&gt;

&lt;p&gt;The Mobitest Agent ignores the physical orientation of the device and works in portrait only.&lt;/p&gt;

&lt;p&gt;Pat Meenan reports that an Airport Express seems to be the most reliable base station for iOS devices. He also has a monitor reboots the Mobitest App via SSH when it stops responding.&lt;/p&gt;

&lt;h1&gt;Questions or Comments?&lt;/h1&gt;

&lt;p&gt;If you’ve got any questions or spot any mistakes feel free to leave a comment or drop me an email.&lt;/p&gt;

&lt;p&gt;If you want to discuss private instances further or need help WebPageTest &lt;a href="http://www.webpagetest.org/forums/forumdisplay.php?fid=12"&gt;Forum for Private Instances&lt;/a&gt; is the place to go.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/wXIf7kVElLM" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2013/03/05/adding-ios-test-agents-to-a-webpagetest-instance/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Generating HAR files for iOS Safari]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/BnG654b2MKg/" />
    <updated>2013-02-07T01:04:00+00:00</updated>
    <id>http://andydavies.me/blog/2013/02/07/generating-har-files-for-ios-safari</id>
    <content type="html">&lt;p&gt;If you want to generate page load waterfalls for iOS Safari the current options are &lt;a href="http://mobitest.akamai.com/m/index.cgi"&gt;Mobitest&lt;/a&gt; / &lt;a href="http://webpagetest.org/"&gt;WebPageTest&lt;/a&gt; or Safari on OSX.&lt;/p&gt;

&lt;p&gt;Mobitest and WebPageTest are great tools (essentially the same tool underneath) that I often use but they have a few limitations:&lt;br/&gt;
- there&amp;#8217;s a limited number of test locations so latency can complicate testing&lt;br/&gt;
- uses a UIWebView so any javascript in the pages doesn&amp;#8217;t have access to the JIT&lt;/p&gt;

&lt;p&gt;Safari on OSX is OK but there seems to be no way of generating a HAR file from the waterfall view in developer tools.&lt;/p&gt;

&lt;p&gt;These limitations sometimes frustrate me so I decided to write a generator that creates HAR files from Safari running on the iOS Simulator (actual physical iPhones and iPad support will hopefully come too).&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;The generator is a node application that uses the Safari remote debugging protocol to talk to Safari running on the iOS simulator.&lt;/p&gt;

&lt;p&gt;Although the &lt;a href="https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/"&gt;debugging commands&lt;/a&gt; for Safari are essentially the same as Chrome&amp;#8217;s they&amp;#8217;re wrapped up as binary plists in an undocumented RPC protocol.&lt;/p&gt;

&lt;p&gt;If you want to know more about the communications side &lt;a href="https://github.com/andydavies/node-iosdriver"&gt;node-iosdriver&lt;/a&gt; is the repository you need.&lt;/p&gt;

&lt;h1&gt;Installation&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Clone &lt;a href="https://github.com/andydavies/ios-har-builder"&gt;ios-har-builder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Run npm install to install dependencies&lt;/li&gt;
&lt;/ol&gt;


&lt;h1&gt;Usage&lt;/h1&gt;

&lt;p&gt;Load the iOS Simulator, launch Safari and then run the HAR builder from the OSX command line e.g.&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;bin/ios-har-builder -o example.har http://m.guardian.co.uk&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;There should now be a HAR file ready for import into HAR viewer etc.&lt;/p&gt;

&lt;h1&gt;Issues&lt;/h1&gt;

&lt;p&gt;It&amp;#8217;s fresh code, and a bit rough and ready in places so I doubt these are the only issues, if you come across any more feel free to raise an issue on GitHub or better still send me a pull request!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cookies aren&amp;#8217;t currently supported in the exported HAR file (this is just a matter of writing the code)&lt;/li&gt;
&lt;li&gt;Code needs cleaning up and refactoring in several places, particularly around the network events in client.js&lt;/li&gt;
&lt;li&gt;Host and Port parameters don&amp;#8217;t work&lt;/li&gt;
&lt;li&gt;Only works on iOS Simulator (for now)&lt;/li&gt;
&lt;li&gt;Validation needs to be disabled to display the watefalls in the HAR viewer&lt;/li&gt;
&lt;li&gt;Limited timing information due to the lack of resource timing in Safari&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Credits&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://twitter.com/phuunet"&gt;Tom Ashworth&lt;/a&gt; and &lt;a href="https://twitter.com/rem"&gt;Remy Sharp&lt;/a&gt; at &lt;a href="http://leftlogic.com/"&gt;Left Logic&lt;/a&gt; did a lot of the work involved with being able to communicate with Safari on iOS.&lt;/p&gt;

&lt;p&gt;I was going to start from the netsniff.js example included with phantomjs but then &lt;a href="cyrus-and.github.com"&gt;Andrea Cardaci&lt;/a&gt; released &lt;a href="https://github.com/cyrus-and/chrome-har-capturer"&gt;chrome-har-capturer&lt;/a&gt; which saved me some time.&lt;/p&gt;

&lt;p&gt;For now ios-har-builder is a separate fork as there are some differences in behaviour between Chrome and Safari e.g. lack of navigation / resource timing in Safari, Safari wraps the WebKit debug protocol in RPC etc.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/BnG654b2MKg" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2013/02/07/generating-har-files-for-ios-safari/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Implementing Sparkicons]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/GDt7DoIyaw4/" />
    <updated>2013-01-14T03:00:00+00:00</updated>
    <id>http://andydavies.me/blog/2013/01/14/implementing-sparkicons</id>
    <content type="html">&lt;p&gt;A few days ago, &lt;a href="https://twitter.com/markboulton"&gt;Mark Boulton&lt;/a&gt; bounced around the idea of &lt;a href="http://www.markboulton.co.uk/journal/sparkicons"&gt;Sparkicons&lt;/a&gt;, small inline icons at the end of links, that indicate what&amp;#8217;s on the end of a hyperlink.&lt;/p&gt;

&lt;p&gt;Based on meta-data attached to a link, the Sparkicon could indicate the link is to a PDF, or a video, or a discussion thead. It could also include addition information such as how long a video is or how many comments there are in a discussion thread.&lt;/p&gt;

&lt;p&gt;This is one way they could be implemented&amp;#8230;&lt;/p&gt;

&lt;!--more--&gt;


&lt;h1&gt;Adding meta-data to &amp;lt;a&amp;gt; element&lt;/h1&gt;

&lt;p&gt;As there aren&amp;#8217;t any suitable standard attributes to store Sparkicon meta data in, I used data- attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;data-sparkicon&lt;/code&gt; - content type e.g. video, music, pdf, comments&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data-sparkicon-plus&lt;/code&gt; - optional extra detail to display e.g. length, size, number of comments&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Displaying the Sparkicon&lt;/h1&gt;

&lt;p&gt;The Sparkicon is inserted using the CSS &lt;code&gt;:after&lt;/code&gt; pseudo selector, so it should degrade gracefully in browsers that don&amp;#8217;t have CSS content support:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-sparkicon&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;media&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sparkicon&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="k"&gt;xx-small&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;vertical-align&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="k"&gt;top&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;font-family&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sparkicons&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="nt"&gt;font-family&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;sparkicons&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data:font/truetype;base64, base64 font data goes here, &lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="s2"&gt;      but you don&amp;#39;t have to use a dataURI...&amp;quot;&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;WARNING: Supporting webfonts across all browsers isn&amp;#8217;t as simple as it might be so while a dataURI is great for demo purposes slightly more complex syntax will be need in real life!&lt;/p&gt;

&lt;p&gt;The HTML is straightforward, with the data- attributes added to the anchor element:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.youtube.com/watch?v=9sSc5ZPK7P8&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="na"&gt;data-sparkicon=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;media&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;data-sparkicon-plus=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;12:02&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Rugby World Cup Highlights&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The font used has just numbers, a colon and an icon for video (mapped to &amp;gt;).&lt;/p&gt;

&lt;h1&gt;Ta Da and Boo!&lt;/h1&gt;

&lt;p&gt;The final result looks pretty good:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/sparkicons-original.png" title="'Sparkicon in Chrome'" &gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;The combination of &lt;code&gt;font-size: xx-small&lt;/code&gt; and &lt;code&gt;vertical-align: top&lt;/code&gt; results in the underline on link under the Sparkicon being disjointed in WebKit browsers (&lt;code&gt;vertical-align: super&lt;/code&gt; doesn&amp;#8217;t improve things). Firefox 12 and IE9 don&amp;#8217;t suffer from this issue.&lt;/p&gt;

&lt;p&gt;If you want to look at the result or play with the code it&amp;#8217;s on jsFiddle: &lt;a href="http://jsfiddle.net/andydavies/GKdDy/"&gt;http://jsfiddle.net/andydavies/GKdDy/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;DRYing Out and Fixing the Baseline Problem&lt;/h1&gt;

&lt;p&gt;Another issue with the example above is that each Sparkicon type requires its own CSS selector and as the number of Sparkicons rises so does the number of CSS selectors.&lt;/p&gt;

&lt;p&gt;CSS pre-processors can help manage this and make it maintainable but font ligatures provide another alternative.&lt;/p&gt;

&lt;p&gt;Using ligatures for each Sparkicon type e.g. chat, video, music, allows &lt;code&gt;data-sparkicon&lt;/code&gt; to be used directly.&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-sparkicon&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sparkicon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sparkicon&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;font-family&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sparkicons&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Creating a superscript font based on &lt;a href="http://blog.ggshow.com/resources/download_free_truetype_fonts"&gt;GG Superscript Sans&lt;/a&gt; simplifies the CSS further and fixes the underline issue in WebKit too.&lt;/p&gt;

&lt;p&gt;Using a single CSS selector we can now specify different Sparkicons for multiple links:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/sparkicons-dry.png" title="'Sparkicon in Chrome'" &gt; &lt;br&gt;&lt;/p&gt;

&lt;p&gt;Again the code is on jsFiddle &lt;a href="http://jsfiddle.net/andydavies/Cg5RQ/"&gt;http://jsfiddle.net/andydavies/Cg5RQ/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Final Thoughts&lt;/h1&gt;

&lt;p&gt;I like the idea of Sparkicons, I guess what we need now is real world usage to understand how it affects visitor experience.&lt;/p&gt;

&lt;p&gt;This is a prototype, so if you&amp;#8217;re planning to take this approach further there&amp;#8217;s a few things to keep in mind.&lt;/p&gt;

&lt;p&gt;It needs a thorough test across multiple browsers, some browsers don&amp;#8217;t support the CSS content pseudo selectors e.g. IE8 but can be polyfilled (or left to degrade gracefully). I tested in on Chrome, Safari and Firefox on OSX and IE9 on Windows (dataURI definition isn&amp;#8217;t correct for IE9 though.)&lt;/p&gt;

&lt;p&gt;I could&amp;#8217;t find any way to keep the underline on the main link but remove it from the Sparkicon, &lt;code&gt;text-decoration: none&lt;/code&gt; seemed to have no effect. Somewhat confusingly I could specify a different colour for the Sparkicon though!&lt;/p&gt;

&lt;p&gt;In the future it might be possible to use normal fonts and do away with the superscript font. &lt;a href="http://dev.w3.org/csswg/css3-fonts/"&gt;CSS3 Fonts&lt;/a&gt; specifies &lt;code&gt;font-variant-position: super&lt;/code&gt; for superscript but it&amp;#8217;s not implemented by any browser yet.&lt;/p&gt;

&lt;p&gt;Finally, icons are really not my forte so it&amp;#8217;d be great if someone could produce a demo with decent icons!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/GDt7DoIyaw4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2013/01/14/implementing-sparkicons/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Think Twice Before Using matchMedia to Conditionally Load Stylesheets]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/KINbMR52gZI/" />
    <updated>2012-12-29T21:30:00+00:00</updated>
    <id>http://andydavies.me/blog/2012/12/29/think-twice-before-using-matchmedia-to-conditionally-load-stylesheets</id>
    <content type="html">&lt;p&gt;&lt;a href="https://twitter.com/codepo8"&gt;Christian Heilmann&lt;/a&gt; recent started exploring how matchMedia could be used to conditionally load resources based on viewport size and other mediaqueries - &lt;a href="http://christianheilmann.com/2012/12/19/conditional-loading-of-resources-with-mediaqueries/"&gt;Conditional Loading of Resources With MediaQueries&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve experimented with using matchMedia to restrict the loading of social media buttons to larger viewports so I think using matchMedia to conditionally load content is a great idea but I was less convinced by the benefits of Christian&amp;#8217;s example of conditionally loading CSS.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;&lt;a href="https://twitter.com/igrigorik"&gt;Ilya Grigorik&lt;/a&gt; had &lt;a href="http://www.igvita.com/2012/06/14/debunking-responsive-css-performance-myths/"&gt;similar concerns&lt;/a&gt; when &lt;a href="https://twitter.com/scottjehl"&gt;Scott Jehl&lt;/a&gt; created &lt;a href="https://github.com/scottjehl/eCSSential"&gt;eCSSential&lt;/a&gt;, a loader that attempts to optimise the loading of CSS based on viewport size and other factors.&lt;/p&gt;

&lt;p&gt;The question is what impact, if any, does conditionally loading CSS have on the performance of sites in real life?&lt;/p&gt;

&lt;p&gt;For testing I used a static copy of &lt;a href="http://www.enochs.co.uk/"&gt;Enoch&amp;#8217;s Fish and Chip Shop&lt;/a&gt; as built by &lt;a href="https://twitter.com/mattwilcox/"&gt;Matt Wilcox&lt;/a&gt;, hosted on an EC2 micro-instance in Dublin.&lt;/p&gt;

&lt;p&gt;Enoch&amp;#8217;s is typical of many of the sites showcased on &lt;a href="http://mediaqueri.es/"&gt;mediaqueri.es&lt;/a&gt; as it uses separate CSS files for each breakpoint.&lt;/p&gt;

&lt;p&gt;Other than changes to the CSS outlined below, the only other change made was enabling gzip using the configuration from &lt;a href="https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess"&gt;HTML5 Boilerplate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Three scenarios were tested:&lt;br&gt;
1.  Multiple stylesheets with browser determining load order&lt;br&gt;
2.  Multiple stylesheets with matchMedia used to load only those that apply&lt;br&gt;
3.  Single stylesheet containg all stylesheets merged into one&lt;/p&gt;

&lt;p&gt;Each scenario was tested using the iPhone agent on &lt;a href="http://webpagetest.org/"&gt;WebPageTest&lt;/a&gt; with the median of 9 runs used for comparison.&lt;/p&gt;

&lt;h2&gt;Default iPhone Behaviour&lt;/h2&gt;

&lt;p&gt;Webkit based browsers prioritise the loading of CSS. Stylesheets whose mediaqueries match the current viewport as loaded first and any others deferred until later in the page.&lt;/p&gt;

&lt;p&gt;The waterfall below demonstrates this split (highlighted in green) between the loading of CSS needed to render Enoch&amp;#8217;s homepage and other CSS files.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/iphone-original.jpg" title="'Original iPhone Waterfall'" &gt; &lt;br&gt;
Waterfall of network activity for &lt;a href="http://www.enochs.co.uk/"&gt;Enoch&amp;#8217;s Fish and Chip Shop&lt;/a&gt; on iPhone produced via &lt;a href="http://webpagetest.org/"&gt;webpagetest.org&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Conditional Loading of Stylesheets with matchMedia&lt;/h2&gt;

&lt;p&gt;Unfortunately other browsers don&amp;#8217;t behave in the same way as webkit and attempt to load all stylesheets before starting to render the page, so using matchMedia to conditionally load the stylesheets might offer a way to reduce the number of requests and so speed up page load times.&lt;/p&gt;

&lt;p&gt;One drawback of using javascript to load CSS is the order resources are retrieved might be altered - the browser isn&amp;#8217;t aware of the CSS resources until the script updates the HTML link elements and while the script is executing the lookahead preloader will schedule other resources for download, so the download of these resources may delay downloading the CSS.&lt;/p&gt;

&lt;p&gt;This behaviour can be seen in the waterfall below, where other resources (highlighted in red) start to download before &lt;em&gt;screen.320.css&lt;/em&gt;, and so delay its download.&lt;/p&gt;

&lt;p&gt;Overall the loading pattern Christian proposes results in the page starting to render marginally later (1.80s vs 1.63s) but reaching document complete sooner (7.62s vs 10.94s).&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/iphone-matchmedia.jpg" title="'iPhone Waterfall with conditional loading of stylesheets'" &gt; &lt;br&gt;
Waterfall of network activity for &lt;a href="http://www.enochs.co.uk/"&gt;Enoch&amp;#8217;s Fish and Chip Shop&lt;/a&gt; on iPhone with stylesheets conditionally loaded using matchMedia.&lt;/p&gt;

&lt;p&gt;There are other disadvantages to this approach too:&lt;/p&gt;

&lt;p&gt;The sample code needs to be enhanced to allow for changes in viewport size or orientation so mediaqueries on the elements can be re-evaluated and appropriate resources loaded when necessary.&lt;/p&gt;

&lt;p&gt;Browsers are continually trying to improve the way they load pages so it&amp;#8217;s likely other browsers will adopt the same approach as Webkit and may not even load stylesheets that don&amp;#8217;t apply or defer them until after DOMContentLoaded.&lt;/p&gt;

&lt;p&gt;Finally not all browsers support matchMedia so some will need to use &lt;a href="https://twitter.com/paul_irish"&gt;Paul Irish&amp;#8217;s&lt;/a&gt; &lt;a href="https://github.com/paulirish/matchMedia.js/"&gt;matchMedia polyfill&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Merged Stylesheets&lt;/h2&gt;

&lt;p&gt;Merging all the stylesheets together into a single downlaod is perhaps the simplest optimisation that could be applied. In this case it also results in the fastest start render (1.57s vs 1.63) and document complete (7.21s vs 7.62s) times.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/iphone-merged.jpg" title="'iPhone Waterfall with all stylesheets merged into one'" &gt; &lt;br&gt;
Waterfall of network activity for &lt;a href="http://www.enochs.co.uk/"&gt;Enoch&amp;#8217;s Fish and Chip Shop&lt;/a&gt; on iPhone with stylesheets merged into one.&lt;/p&gt;

&lt;h2&gt;Comparison of Tests&lt;/h2&gt;

&lt;p&gt;Raw timings don&amp;#8217;t always give a complete picture, so I always compare tests visually too.&lt;/p&gt;

&lt;p&gt;Comparing the tests side-by-side demonstrates the test with the merged stylesheets is both first to start displaying &amp;#8216;real&amp;#8217; content and also the first to complete.&lt;/p&gt;

&lt;p&gt;The test using matchMedia completes before the original site most likely due to a lower number of requests but it is the last to start rendering &amp;#8216;real&amp;#8217; content.&lt;/p&gt;

&lt;p&gt;N.B. Watch out for the unequal timescale!&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/comparison-filmstrip.jpg" title="'Visual comparison of three scenarios'" &gt;
Filmstrip comparison of the three test scenarios.&lt;/p&gt;

&lt;p&gt;WebPageTest also provides a comparison of visual progress and this re-inforces the matchMedia test is the slowest to start displaying &amp;#8216;real&amp;#8217; content.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/visual-progress.jpg" title="'Illustration of progress towards visual completion for each scenario'" &gt; &lt;br&gt;
Illustration of progress towards visual completion for each test scenario.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this case the simplest optimisation i.e. merging the stylesheets in one, produces the fastest result.&lt;/p&gt;

&lt;p&gt;The combination of less requests and most likely the availability of all styles earlier in the pageload allows the page with the merged stylesheet to start rendering sooner, even though the combined stylesheet (14KB) is slightly larger than the two stylesheets downloaded by the matchMedia test (10.1KB).&lt;/p&gt;

&lt;p&gt;Even the original page starts to render before the one that uses matchMedia, with DOMContentLoaded being delayed by the download of stylesheets that aren&amp;#8217;t applicable. The WHATWG spec allows for the loading of stylesheets that aren&amp;#8217;t applicable to be &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/#the-link-element"&gt;deferred until they are are needed&lt;/a&gt; so further optimisations may be possible.&lt;/p&gt;

&lt;p&gt;Based on these tests and the likelihood of other browsers adopting behaviour similar to Webkit&amp;#8217;s, I wouldn&amp;#8217;t advocate approaches that use matchMedia to determine which stylesheets should be loaded.&lt;/p&gt;

&lt;h2&gt;Other Considerations&lt;/h2&gt;

&lt;p&gt;We should &amp;#8216;poke holes&amp;#8217; in all tests and examine them for weaknesses, this test is no different and there are some areas for further exploration.&lt;/p&gt;

&lt;p&gt;CSS is very repetitive (IDs, class names and CSS syntax itself) so it compresses well, dataURIs are the exception to this. The CSS on Enochs doesn&amp;#8217;t contain any dataURIs so sites using dataURIs may see different results.&lt;/p&gt;

&lt;p&gt;The iPhone test agent uses a UIWebView and execution of the javascript is impacted by the lack of a JIT. Delays in the download of &lt;em&gt;screen.320.css&lt;/em&gt; were also seen when the matchMedia test was repeated in Safari on both an iPhone and the iOS simulator. The delays were not a great as those on the WebPageTest agent but they were long enough to allow other resources to start downloading.&lt;/p&gt;

&lt;p&gt;The tests need repeating in other mobile browsers e.g. Firefox, Internet Explorer, Opera etc., and for other sites. I attempted to repeat the tests using Android 2.3 but even with a polyfill the test using matchMedia failed (a similar test using eCSSential works, so it&amp;#8217;s not quite clear where the issue is at the moment).&lt;/p&gt;

&lt;p&gt;Scott has seen performance improvements when eCSSential is used so we need more detail to be able to understand the cases where it makes a difference.&lt;/p&gt;

&lt;h2&gt;Raw Test Results&lt;/h2&gt;

&lt;p&gt;If you want to take a look at the raw results yourself, here&amp;#8217;s the relevant tests on WebPageTest:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default iPhone Behaviour&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://www.webpagetest.org/result/121228_66_a9708983b3a994bc3345e4f66858c59c/"&gt;webpagetest.org/result/121228_66_a9708983b3a994bc3345e4f66858c59c/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conditional Loading of Stylesheets with matchMedia&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://www.webpagetest.org/result/121228_BA_52d204278ed082e081c4cdffac110358/"&gt;webpagetest.org/result/121228_BA_52d204278ed082e081c4cdffac110358/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Merged Stylesheets&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://www.webpagetest.org/result/121228_JZ_c100646a583ed1d3789db3d4e37629c5/"&gt;webpagetest.org/result/121228_JZ_c100646a583ed1d3789db3d4e37629c5/&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/KINbMR52gZI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2012/12/29/think-twice-before-using-matchmedia-to-conditionally-load-stylesheets/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Visualising Webpage Resource Dependencies]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/7A1m-GMdDpw/" />
    <updated>2012-10-24T14:37:00+01:00</updated>
    <id>http://andydavies.me/blog/2012/10/24/visualising-webpage-resource-dependencies</id>
    <content type="html">&lt;p&gt;Waterfall charts are great but they show a timeline rather than the relationships between the resources on a page and I often want to understand what triggered a resource to load.&lt;/p&gt;

&lt;p&gt;At Velocity EU, &lt;a href="https://twitter.com/vrajivk"&gt;Rajiv Vijayakumar&lt;/a&gt; of Qualcomm demonstrated a tool they&amp;#8217;re building to map the resource dependencies in webpages highlighting blocking paths etc.&lt;/p&gt;

&lt;p&gt;Currently it&amp;#8217;s not clear whether Qualcomm are going to opensource the tool, or run it as a service (like WebPageTest), so during a moment of curiosity I attempted to produce something similar using WebKit dev tools and Mike Bostock&amp;#8217;s &lt;a href="http://d3js.org/"&gt;D3.js&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;The results are interesting but unfortunately not quite right, as this chart for &lt;a href="http://www.guardian.co.uk/"&gt;The Guardian&lt;/a&gt; demonstrates:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/resource-dependency-tree-guardian.png" title="'Resource Dependencies for guardian.co.uk'" &gt;&lt;/p&gt;

&lt;p&gt;The green nodes in the above chart are CSS files which include some definitions with background images but you might notice there&amp;#8217;s no images (purple nodes) linked to them.&lt;/p&gt;

&lt;p&gt;This is due to Chrome reporting the initiator as the HTML line that uses the selector and so triggers the download e.g. in the example below the &lt;em&gt;a&lt;/em&gt; element would be reported as the initiator.&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;#logo { background: url('/content/images/web/logo.png')' }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;&amp;lt;a href="http://andydavies.me/" title="Logo" id="logo"&amp;gt;Logo&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;&lt;a href="https://twitter.com/marco_tolk"&gt;Marco Tolk&lt;/a&gt; has found other scenarios where Chrome reports the initiator incorrectly so we&amp;#8217;re putting together a set of test cases to determine what works and what doesn&amp;#8217;t (for our needs).&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve got lots of ideas on how the charts could be enhanced but I&amp;#8217;m holding off until the data is right, in the meantime I&amp;#8217;m back in C++ land debugging and exploring what information Chrome can give me.&lt;/p&gt;

&lt;p&gt;If you want to try it out for yourself the code I used to generate the charts is on &lt;a href="https://github.com/andydavies/kensho"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/7A1m-GMdDpw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2012/10/24/visualising-webpage-resource-dependencies/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Configuring an ‘all-in-one’ WebPageTest Private Instance]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/-x4A6x11ryM/" />
    <updated>2012-09-18T12:51:00+01:00</updated>
    <id>http://andydavies.me/blog/2012/09/18/how-to-create-an-all-in-one-webpagetest-private-instance</id>
    <content type="html">&lt;p&gt;WebPageTest (WPT) is a great tool and the public instances cover many scenarios but sometimes I need a private instance, for example when testing sites that aren&amp;#8217;t publicly accessible yet or debugging a script.&lt;/p&gt;

&lt;p&gt;Setting up a private instance is reasonably straightforward but there are a few gotchas and some settings aren’t always obvious the first time around.&lt;/p&gt;

&lt;p&gt;I’ve been asked by a few people how I set up instances, so these notes explain the steps I follow to create an ‘all in one’ installation with the server and test agents on same machine.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;The notes are based on &lt;a href="https://sites.google.com/a/webpagetest.org/docs/private-instances"&gt;WPT install guide&lt;/a&gt; and can also be used as a guide to creating separate a server and agents, although I’d use a Linux variant for the server in that case.&lt;/p&gt;

&lt;h1&gt;Base Windows Configuration&lt;/h1&gt;

&lt;p&gt;Start with a fresh Windows 7 install (I used 32-bit Professional, the virtual machines Microsoft make available for browser testing are another option but stick with 32bit)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a user with local administrator rights and set them to log in automatically when the machine starts up. (this has security implications and some network managers may not like it)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Turn off UAC&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Turn off any screensaver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the power saving settings choose never as the options for turning off the display and putting the computer to sleep&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set firewall rules to allow port 80 &amp;amp; 443 TCP inbound&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add shortcuts for Shutdown and Restart&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;When accessed via Remote Desktop (RDP), Windows 7 doesn’t display the Restart and Shutdown options on the Start menu, so I add shortcuts for them:&lt;/p&gt;

&lt;p&gt;   Shutdown :       &lt;code&gt;shutdown -f -s -t 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;   Restart :        &lt;code&gt;shutdown -f -r -t 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I also add Notepad++ and 7zip so I have a decent text editor and archiving tool&lt;/p&gt;

&lt;h1&gt;Server Installation&lt;/h1&gt;

&lt;h2&gt;Install Apache&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Download and install Apache. &lt;a href="http://httpd.apache.org/download.cgi#apache22"&gt;Apache 2.2&lt;/a&gt; is currently the most recent version with a Windows binary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edit &lt;code&gt;C:\Program Files\Apache Software Foundation\Apache2.2\conf\httpd.conf&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the configuration to include the following:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;DocumentRoot "C:/wpt-www/"
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&amp;lt;Directory /&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;    Options FollowSymLinks
&lt;/span&gt;&lt;span class='line'&gt;    AllowOverride None
&lt;/span&gt;&lt;span class='line'&gt;    Order deny,allow
&lt;/span&gt;&lt;span class='line'&gt;    Deny from all
&lt;/span&gt;&lt;span class='line'&gt;&amp;lt;/Directory&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&amp;lt;Directory "C:/wpt-www/"&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;        AllowOverride all
&lt;/span&gt;&lt;span class='line'&gt;        Order allow,deny
&lt;/span&gt;&lt;span class='line'&gt;        Allow from all
&lt;/span&gt;&lt;span class='line'&gt;&amp;lt;/Directory&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&amp;lt;IfModule dir_module&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;    DirectoryIndex index.html index.php
&lt;/span&gt;&lt;span class='line'&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Uncomment these modules&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;LoadModule expires_module modules/mod_expires.so
&lt;/span&gt;&lt;span class='line'&gt;LoadModule headers_module modules/mod_headers.so
&lt;/span&gt;&lt;span class='line'&gt;LoadModule rewrite_module modules/mod_rewrite.so&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Add the PHP module (installed in next step)&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;LoadModule php5_module "C:\Program Files\PHP\php5apache2_2.dll"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Install PHP&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Download PHP from &lt;a href="http://windows.php.net/download"&gt;http://windows.php.net/download&lt;/a&gt; (I used the zip of 5.4.7 VC9 Threadsafe)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract and copy contents to &lt;code&gt;c:\program files\php&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy &lt;code&gt;c:\program files\php\php.ini-production&lt;/code&gt; to &lt;code&gt;c:\windows\php.ini&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edit &lt;code&gt;c:\windows\php.ini&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Update the extension_dir path, and uncomment the php_gd2 extension&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;extension_dir = "C:\program files\php\ext"
&lt;/span&gt;&lt;span class='line'&gt;extension=php_gd2.dll&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;(zip and zlib are on by default in 5.4.7)&lt;/p&gt;

&lt;h2&gt;Install WPT server&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Download the latest version (2.7.2 at time of writing) of WPT from &lt;a href="https://sites.google.com/a/webpagetest.org/docs/private-instances/releases"&gt;https://sites.google.com/a/webpagetest.org/docs/private-instances/releases&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract the contents of the www folder from webpagetest.2.7.2.zip into &lt;code&gt;c:\wpt-www&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy &lt;code&gt;c:\wpt-www\settings\connectivity.ini.sample&lt;/code&gt; to &lt;code&gt;c:\wpt-www\settings\connectivity.ini&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add test agent locations / configurations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Editing locations.ini is the probably the area I make the most errors and it can be confusing until you grasp it’s hierarchical nature.&lt;/p&gt;

&lt;p&gt;The browser configuration labels must match the labels used in urlblast.ini and wptdriver.ini in the test agent configurations.&lt;/p&gt;

&lt;p&gt;I name my labels as &lt;em&gt;location&lt;/em&gt;-&lt;em&gt;testdriver&lt;/em&gt; pairs e.g. local-urlblast (for IE) or local-wptdriver (for Chrome and Firefox)&lt;/p&gt;

&lt;p&gt;copy &lt;code&gt;c:\wpt-www\settings\locations.ini.sample&lt;/code&gt; to &lt;code&gt;c:\wpt-www\settings\locations.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;edit &lt;code&gt;c:\wpt-www\settings\locations.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is a sample config that matches the test agents below, more locations can be added:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;span class='line-number'&gt;27&lt;/span&gt;
&lt;span class='line-number'&gt;28&lt;/span&gt;
&lt;span class='line-number'&gt;29&lt;/span&gt;
&lt;span class='line-number'&gt;30&lt;/span&gt;
&lt;span class='line-number'&gt;31&lt;/span&gt;
&lt;span class='line-number'&gt;32&lt;/span&gt;
&lt;span class='line-number'&gt;33&lt;/span&gt;
&lt;span class='line-number'&gt;34&lt;/span&gt;
&lt;span class='line-number'&gt;35&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;[locations]
&lt;/span&gt;&lt;span class='line'&gt;1=Local
&lt;/span&gt;&lt;span class='line'&gt;default=Local
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;;
&lt;/span&gt;&lt;span class='line'&gt;; These are the top-level locations that are listed in the location dropdown
&lt;/span&gt;&lt;span class='line'&gt;; Each one points to one or more browser configurations
&lt;/span&gt;&lt;span class='line'&gt;;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;[Local]
&lt;/span&gt;&lt;span class='line'&gt;1=Local-URLBlast
&lt;/span&gt;&lt;span class='line'&gt;2=Local-WPTDriver
&lt;/span&gt;&lt;span class='line'&gt;label=Local
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;;
&lt;/span&gt;&lt;span class='line'&gt;; These are the browser-specific configurations that match the configurations
&lt;/span&gt;&lt;span class='line'&gt;; defined in the top-level locations.  Each one of these MUST match the location
&lt;/span&gt;&lt;span class='line'&gt;; name configured on the test agent (urlblast.ini or wptdriver.ini)
&lt;/span&gt;&lt;span class='line'&gt;;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;[Local-URLBlast]
&lt;/span&gt;&lt;span class='line'&gt;browser=IE 9
&lt;/span&gt;&lt;span class='line'&gt;latency=0
&lt;/span&gt;&lt;span class='line'&gt;label="Local - IE 9"
&lt;/span&gt;&lt;span class='line'&gt;;browserExe=pagetest.exe
&lt;/span&gt;&lt;span class='line'&gt;;key=TestKey123
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;;
&lt;/span&gt;&lt;span class='line'&gt;; For a wptdriver configuration (chrome, firefox), the browser labels here 
&lt;/span&gt;&lt;span class='line'&gt;; MUST match the labels used in wptdriver.ini
&lt;/span&gt;&lt;span class='line'&gt;;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;[Local-WPTDriver]
&lt;/span&gt;&lt;span class='line'&gt;browser=Chrome,Firefox
&lt;/span&gt;&lt;span class='line'&gt;label="Local"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Restart Apache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fire up a browser and navigate to 127.0.0.1 and you should see the Web Page Test Private Instance home page.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Test-Agent Configuration&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Extract the contents of the www folder from webpagetest.2.7.2.zip into &lt;code&gt;c:\wpt-agent&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install Chrome and Firefox (if you want them of course)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install ffmpeg (&lt;a href="http://ffmpeg.zeranoe.com/builds/"&gt;http://ffmpeg.zeranoe.com/builds/&lt;/a&gt;) and add its bin folder to the path. I tend to install it in &lt;code&gt;c:\program files\ffmpeg&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install AVISynth using the installer in c:\wpt-agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install the DUMMYNET ipfw driver&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;WPT 2.10 introduced a 64bit version of dummynet. Depending on your platform choose the version of dummynet you require and copy the contents of the 32bit or 64bit folder into c:\wpt-agent\dummynet.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the properties of the Network Adapter used for Internet access&lt;/li&gt;
&lt;li&gt;Click &amp;#8220;Install&amp;#8221;&lt;/li&gt;
&lt;li&gt;Select &amp;#8220;Service&amp;#8221; and click &amp;#8220;Add&amp;#8221;&lt;/li&gt;
&lt;li&gt;Click &amp;#8220;Have Disk&amp;#8221; and navigate to c:\wpt-agent\dummynet&lt;/li&gt;
&lt;li&gt;Select the ipfw+dummynet service (and click through any warnings about the driver being unsigned)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;If you’re connected via RDP you may lose the connections while installing ipfw plus dummynet and need to re-connect.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the startup folder, create shortcuts to &lt;code&gt;c:\wpt-agent\dummynet\ipfw.cmd&lt;/code&gt;, &lt;code&gt;c:\wpt-agent\urlblast.exe&lt;/code&gt; and &lt;code&gt;c:\wpt-agent\wptdriver.exe&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure IE&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Copy &lt;code&gt;c:\wpt-agent\urlblast.ini.sample&lt;/code&gt; to &lt;code&gt;c:\wpt-agent\urlblast.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;c:\wpt-agent\urlblast.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The Location entry must match the location label for the IE section of locations.ini&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;[Configuration]
&lt;/span&gt;&lt;span class='line'&gt;Startup Delay=30
&lt;/span&gt;&lt;span class='line'&gt;Log File=c:\wpt-agent\agent\urlblast
&lt;/span&gt;&lt;span class='line'&gt;Timeout=120
&lt;/span&gt;&lt;span class='line'&gt;use current account=1
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;; Where to get work from
&lt;/span&gt;&lt;span class='line'&gt;Url Files Url=http://127.0.0.1/work/
&lt;/span&gt;&lt;span class='line'&gt;Location=Local-URLBlast
&lt;/span&gt;&lt;span class='line'&gt;;Location Key=TestKey123&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;ul&gt;
&lt;li&gt;Configure Chrome and Firefox&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Copy &lt;code&gt;c:\wpt-agent\wptdriver.ini.sample&lt;/code&gt; to &lt;code&gt;c:\wpt-agent\wptdriver.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;c:\wpt-agent\wptdriver.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Again the location entry name must match the revelant section in the server locations.ini&lt;/p&gt;

&lt;p&gt;I update the software paths to retrieve updates from the local machine rather than webpagetest.org but that&amp;#8217;s a personal preference&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;[WebPagetest]
&lt;/span&gt;&lt;span class='line'&gt;url=http://127.0.0.1/
&lt;/span&gt;&lt;span class='line'&gt;location=Local-WPTDriver
&lt;/span&gt;&lt;span class='line'&gt;browser=chrome
&lt;/span&gt;&lt;span class='line'&gt;;key=TestKey123
&lt;/span&gt;&lt;span class='line'&gt;;Automatically install and update support software (Flash, Silverlight, etc)
&lt;/span&gt;&lt;span class='line'&gt;software=http://127.0.0.1/installers/software.dat
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;[chrome]
&lt;/span&gt;&lt;span class='line'&gt;exe="C:\Program Files\Google\Chrome\Application\chrome.exe"
&lt;/span&gt;&lt;span class='line'&gt;options='--load-extension="%WPTDIR%\extension" --user-data-dir="%PROFILE%" --no-proxy-server'
&lt;/span&gt;&lt;span class='line'&gt;installer=http://127.0.0.1/installers/browsers/chrome.dat
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;[Firefox]
&lt;/span&gt;&lt;span class='line'&gt;exe="C:\Program Files\Mozilla Firefox\firefox.exe"
&lt;/span&gt;&lt;span class='line'&gt;options='-profile "%PROFILE%" -no-remote'
&lt;/span&gt;&lt;span class='line'&gt;installer=http://127.0.0.1/installers/browsers/firefox.dat
&lt;/span&gt;&lt;span class='line'&gt;template=firefox&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;ul&gt;
&lt;li&gt;Clearing prompts and warnings&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Launch each browser and clear the prompts e.g. should it load extensions, should it be the default browser etc.&lt;/p&gt;

&lt;p&gt;From the startup folder launch urlBlast,  wptdriver and ipfw.cmd manually. Give each of them permission to run even though they’re unsigned, and check the ‘always do this box’&lt;/p&gt;

&lt;h1&gt;Restart the machine&lt;/h1&gt;

&lt;p&gt;Whenever you RDP into a WPT test agent, you should always restart the machine as the Window lock screen is displayed when disconnecting RDP.&lt;/p&gt;

&lt;p&gt;You should now have a working ‘all in one’ install of Web Page Test, point your browser at the WPT machine and launch tests for IE, Firefox and Chrome just to check they work.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;ve got any questions or spot any mistakes feel free to leave a comment or drop me an email.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s also a troubleshooting guide for the most common problems at the foot of the main WPT installation instruction (&lt;a href="https://sites.google.com/a/webpagetest.org/docs/private-instances"&gt;https://sites.google.com/a/webpagetest.org/docs/private-instances&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If you want to discuss private instances further or need help &lt;a href="http://www.webpagetest.org/forums/forumdisplay.php?fid=12"&gt;WebPageTest Forum for Private Instances&lt;/a&gt; is the place to go.&lt;/p&gt;

&lt;h1&gt;Updates&lt;/h1&gt;

&lt;p&gt;30 Apr 2013 - Added 32bit / 64bit dummynet details&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/-x4A6x11ryM" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2012/09/18/how-to-create-an-all-in-one-webpagetest-private-instance/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[What if we could use CSS to alter HTML attributes?]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/yB2Y2fUxmHc/" />
    <updated>2012-08-13T09:34:00+01:00</updated>
    <id>http://andydavies.me/blog/2012/08/13/what-if-we-could-use-css-to-manipulate-html-attributes</id>
    <content type="html">&lt;p&gt;As the ideas behind responsive web design mature, and our skills and experience with them
grow, we&amp;#8217;re faced with a gap between what the tools and technologies can do and what we&amp;#8217;d
like them to do.&lt;/p&gt;

&lt;p&gt;We often end up trying to fill the gap with javascript and using it not just for
behaviour but to change appearance and content too.&lt;/p&gt;

&lt;p&gt;Javascript might be the right tool for many things, but should we really be embedding
attributes that control appearance in our scripts, or might a declarative approach that
uses CSS to change HTML attributes be clearer?&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;Syntax&lt;/h2&gt;

&lt;p&gt;A syntax that allows HTML attributes to be changed via CSS might look something like this:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;HTMLattribute : [operator] value
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;e.g.
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;HTMLattribute :  value        // set value
&lt;/span&gt;&lt;span class='line'&gt;HTMLattribute : +value        // add value e.g. to lists such as class, rel
&lt;/span&gt;&lt;span class='line'&gt;HTMLattribute : -value        // remove value from list
&lt;/span&gt;&lt;span class='line'&gt;HTMLattribute : ^value        // toggle value - remove if there, add if not&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The syntax needs improving, for example the HTML attributes probably need prefixing to
prevent clashes with CSS properties that share the same name.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m also not sure about the list operators, but the syntax is good enough to illustrate
some of the ways the idea might be useful.&lt;/p&gt;

&lt;h2&gt;Classes as hooks for javascript e.g. conditional loading&lt;/h2&gt;

&lt;p&gt;The class and rel attributes sometimes get used as hooks for javascript but what if we want
to add a hook that depends on viewport size?&lt;/p&gt;

&lt;p&gt;We could use matchMedia(), but as &lt;a href="https://twitter.com/adactio"&gt;Jeremy Keith&lt;/a&gt; points
out in &lt;a href="http://adactio.com/journal/5414/"&gt;Conditionally loading content&lt;/a&gt;, using matchMedia()
requires maintaining breakpoints in more than one place.&lt;/p&gt;

&lt;p&gt;Jeremy eventually chose the option of generating a hidden marker on the body element using
:after (see &lt;a href="http://adactio.com/journal/5429/"&gt;Conditional CSS&lt;/a&gt;), it works but it&amp;#8217;s a bit
of a hack.&lt;/p&gt;

&lt;p&gt;What if we could just add a class directly using CSS and use that as the hook for our
javascript?&lt;/p&gt;

&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;/* add class big-screen to html element */&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="nt"&gt;all&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;1024px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;big-screen&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Data- attributes for configuration of widgets e.g. tweet buttons etc.&lt;/h2&gt;

&lt;p&gt;jQuery mobile, social media buttons and other widgets are increasingly using HTML5 data-
attributes for configuration.&lt;/p&gt;

&lt;p&gt;The tweet button has options such as big buttons vs little buttons, counts, count position
etc., all controlled via data- attributes.&lt;/p&gt;

&lt;p&gt;In smaller viewports we might want to make the tweet button larger so it&amp;#8217;s easier to touch,
and free up some room by hiding the count.&lt;/p&gt;

&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;/* set the data- attributes that makes button bigger and removes tweet count */&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="nt"&gt;all&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;max-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;480px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nc"&gt;.twitter-share-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;large&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Swapping content&lt;/h2&gt;

&lt;p&gt;The srcset / picture proposals will help resolve the responsive images problem, so we
probably don&amp;#8217;t need another solution but as a use-case it shows how updating HTML attributes
could be used to swap content, while still keeping all the content in HTML.&lt;/p&gt;

&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;lt;!-- img element that uses data- attributes to declare images, keeping content in HTML --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;small.jpg&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;data-src-med=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;medium.jpg&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;data-src-lge=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;large.jpg&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;/* use media queries and attr() function to replace the small image if appropriate */&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="nt"&gt;all&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;321px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;max-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;800px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;med&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="nt"&gt;all&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;801px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lge&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This is just an illustration as an approach like this for responsive images wouldn&amp;#8217;t
enable the UA to use network connection throughput to pick the most appropriate image
that the other proposals do.&lt;/p&gt;

&lt;h2&gt;Feedback&lt;/h2&gt;

&lt;p&gt;At the moment this is just an idea, an idea which almost certainly has plenty of issues,
so what I&amp;#8217;m really looking for is feedback.&lt;/p&gt;

&lt;p&gt;Is it a useful idea, how would you use it, how could it be improved, what issues are there
implementing it etc. or have I just been drinking too much coffee?&lt;/p&gt;

&lt;h2&gt;Cascading Attribute Sheets&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Added: 24 Aug 2012&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/tabatkins"&gt;Tab Atkins&lt;/a&gt; and &lt;a href="https://twitter.com/fantasai"&gt;Fantasai&lt;/a&gt; have
come out with a similar proposal for &lt;a href="http://www.xanthir.com/b4K_0"&gt;Cascading Attribute Sheets&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The syntax is pretty similar but Tab and Fantasai suggested another way of adding to an existing
property, so with their syntax my first example would look like this:&lt;/p&gt;

&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;/* add class big-screen to html element */&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="nt"&gt;all&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;1024px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The proposal and comment are well worth a read.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/yB2Y2fUxmHc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2012/08/13/what-if-we-could-use-css-to-manipulate-html-attributes/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Rebooting my blog]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/KoT1e5fyYWY/" />
    <updated>2012-08-08T14:41:00+01:00</updated>
    <id>http://andydavies.me/blog/2012/08/08/rebooting-my-blog</id>
    <content type="html">&lt;p&gt;I&amp;#8217;ve haven&amp;#8217;t written a post in ages, partly because I&amp;#8217;m really bad at finishing posts,
and partly because I&amp;#8217;ve never really like typepad and so haven&amp;#8217;t paid for it this year.&lt;/p&gt;

&lt;p&gt;Twitter is great for short conversations but it&amp;#8217;s not up to longer posts and I&amp;#8217;ve got some
ideas I want to share so that others can kick the tyres.&lt;/p&gt;

&lt;p&gt;So I&amp;#8217;ve switched domains, fired up Octopress, and with the help of &lt;a href="http://johnmacfarlane.net/pandoc/"&gt;pandoc&lt;/a&gt; ported the old blog
content across. Once I&amp;#8217;ve got the redirects in place I will be killing off the old blog.&lt;/p&gt;

&lt;p&gt;Octopress was really pretty easy to get going, but I&amp;#8217;m not quite sure if I&amp;#8217;m going to stay
with it as I want to experiment with some &lt;a href="http://www.lukew.com/ff/entry.asp?1392"&gt;RESS&lt;/a&gt; type things.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve still got some pages to write, some tweaks to the theme I want to make but it&amp;#8217;s good
enough for now.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/KoT1e5fyYWY" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2012/08/08/rebooting-my-blog/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Web Performance - A Whistlestop Tour]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/Kfh7fvqUCQE/" />
    <updated>2012-01-24T00:00:00+00:00</updated>
    <id>http://andydavies.me/blog/2012/01/24/web-performance-a-whistlestop-tour</id>
    <content type="html">&lt;p&gt;The slides from my recent talk at &lt;a href="http://lanyrd.com/2012/digitalkschelt-january/" title="DigiTalks Cheltenham"&gt;DigiTalks Cheltenham&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.slideshare.net/AndyDavies/web-performance-a-whistlestop-tour-10995825" title="Web Performance - A Whistlestop Tour"&gt;Web Performance - A Whistlestop Tour&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;iframe frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/10995825" width="425"&gt;&lt;/iframe&gt;



&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/Kfh7fvqUCQE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2012/01/24/web-performance-a-whistlestop-tour/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Increasing the TCP Initial Congestion Window on Windows 2008 Server R2]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/-U__cYN52Ik/" />
    <updated>2011-11-21T00:00:00+00:00</updated>
    <id>http://andydavies.me/blog/2011/11/21/increasing-the-tcp-initial-congestion-window-on-windows-2008-server-r2</id>
    <content type="html">&lt;p&gt;In November 2010, Ben Strong highlighted how &lt;a href="http://blog.benstrong.com/2010/11/google-and-microsoft-cheat-on-slow.html"&gt;Google and Microsoft were cheating on TCP Slow-Start&lt;/a&gt;
by setting the initial congestion window higher than the RFC value.&lt;/p&gt;

&lt;p&gt;Since then there’s been quite a few articles discussing the performance
benefits of increasing the TCP initial congestion window (initcwnd).
Most of the articles showed how to make the changes on Linux but there
was no coverage on whether and how it could be increased on a Windows
Server.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;In one of their recent posts, &lt;a href="http://www.cdnplanet.com/blog/tune-tcp-initcwnd-for-optimum-%20performance/"&gt;Tuning initcwnd for optimum performance&lt;/a&gt;,
the guys at CDN planet mentioned they didn’t know how to
change the settings on Windows either.&lt;/p&gt;

&lt;p&gt;Having trawled through the various options in &lt;em&gt;netsh&lt;/em&gt;, I was coming to
the conclusion it wasn’t possible but &lt;a href="https://twitter.com/#!/dritans"&gt;Drit Suljoti&lt;/a&gt; of Catchpoint
pointed me in the direction of MS Hotfix KB2472264 “You cannot customize
some TCP configurations by using the netsh command in Windows Server
2008 R2”.&lt;/p&gt;

&lt;p&gt;After installing this hotfix I was able to change the initial congestion
window to 10 (it can be adjusted up to 16 * MSS).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing and configuring&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Request the Hotfix via &lt;a href="http://support.microsoft.com/kb/2472264"&gt;http://support.microsoft.com/kb/2472264&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download and install the relevant version - it’s available in x32,
x64 and ia64 flavours&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the hotfix is installed ok&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Type:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;c:\netsh interface tcp show supplemental&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;and you should see:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;The TCP global default template is internet
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;TCP Supplemental Parameters
&lt;/span&gt;&lt;span class='line'&gt;----------------------------------------------
&lt;/span&gt;&lt;span class='line'&gt;Minimum RTO (msec)                  : 300
&lt;/span&gt;&lt;span class='line'&gt;Initial Congestion Window (MSS)     : 2
&lt;/span&gt;&lt;span class='line'&gt;Delayed Ack Timeout (msec)          : 200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;If you get the following then the hotfix hasn’t been installed:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;The following command was not found: interface tcp show supplemental.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;ol&gt;
&lt;li&gt;Update the initial congestion window settings and switch to the custom template&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;First set the initial congestion window in the custom template:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;c:\netsh interface tcp set supplemental template=custom icw=10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Then tell Windows to use the custom template instead of the standard
internet one:&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;c:\netsh interface tcp set supplemental template=custom&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;ol&gt;
&lt;li&gt;Your server should now be running with the new initcwnd value, so pull
out your favourite packet sniffer - Wireshark, tcpdump etc., and test.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So far I’ve only tested this configuration on an EC2 instance and
haven’t deployed it in live production environment yet.&lt;/p&gt;

&lt;p&gt;Cursory performance tests show a great improvement downloading the
default welcome.png that comes with IIS 7.5 - from 11.7s to 2.5s with a
server in Singapore and a client in the UK.&lt;/p&gt;

&lt;p&gt;I’m not sure I quite believe the 11.7s time so over the next week I’ll
try some more tests with various size files and post the results.&lt;/p&gt;

&lt;p&gt;Before (icw=2):&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;$ time curl ec2-175-41-175-250.ap-southeast-1.compute.amazonaws.com/welcome.png &amp;gt; /dev/null
&lt;/span&gt;&lt;span class='line'&gt;  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
&lt;/span&gt;&lt;span class='line'&gt;                                 Dload  Upload   Total   Spent    Left  Speed
&lt;/span&gt;&lt;span class='line'&gt;100  180k  100  180k    0     0  15912      0  0:00:11  0:00:11 --:--:-- 20785
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;real    0m11.706s
&lt;/span&gt;&lt;span class='line'&gt;user    0m0.008s
&lt;/span&gt;&lt;span class='line'&gt;sys     0m0.015s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;After (icw=10):&lt;/p&gt;

&lt;figure class='code'&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class=''&gt;&lt;span class='line'&gt;$ time curl ec2-175-41-175-250.ap-southeast-1.compute.amazonaws.com/welcome.png &amp;gt; /dev/null
&lt;/span&gt;&lt;span class='line'&gt;  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
&lt;/span&gt;&lt;span class='line'&gt;                                 Dload  Upload   Total   Spent    Left  Speed
&lt;/span&gt;&lt;span class='line'&gt;100  180k  100  180k    0     0  75765      0  0:00:02  0:00:02 --:--:-- 93690
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;real    0m2.532s
&lt;/span&gt;&lt;span class='line'&gt;user    0m0.007s
&lt;/span&gt;&lt;span class='line'&gt;sys     0m0.015s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;&lt;strong&gt;Final Notes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re thinking of deploying the fix to a production server it’s
probably worth reading the &lt;a href="http://datatracker.ietf.org/doc/draft-ietf-tcpm-initcwnd/"&gt;proposal submitted to the IETF on increasing the default value to 10&lt;/a&gt;
as it covers both the advantages and potential drawbacks with an increased default.&lt;/p&gt;

&lt;p&gt;Jim Gettys also &lt;a href="http://tools.ietf.org/html/draft-gettys-iw10-considered-harmful-00"&gt;points out some of the potential issues&lt;/a&gt; particularly in relation to
the possible effects on network equipment.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/-U__cYN52Ik" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2011/11/21/increasing-the-tcp-initial-congestion-window-on-windows-2008-server-r2/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Testing how slow third party components affect your page load times]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/-wL33TN_WQE/" />
    <updated>2010-10-01T00:00:00+01:00</updated>
    <id>http://andydavies.me/blog/2010/10/01/testing-how-slow-third-party-components-affect-your-page-load-times</id>
    <content type="html">&lt;p&gt;Both &lt;a href="http://www.stevesouders.com/blog/2010/06/01/frontend-spof/"&gt;Steve Souders&lt;/a&gt; and &lt;a href="http://www.webperformancetoday.com/2010/08/17/the-3-biggest-performance-problems-with-third-party-content/"&gt;Joshua Bixby&lt;/a&gt; have highlighted the effect
slow third party components can have on  overall page load time.&lt;/p&gt;

&lt;p&gt;Third party components have become common e.g. ads, links for
bookmarking, sharing, widgets that pull in content from other sites etc,
and the impact on our page load times depends on the quality of service
they offer (both how the component is implemented and the
reliability/speed of their service)&lt;/p&gt;

&lt;p&gt;Steve and Joshua have highlighted approaches that can be used to
decouple the components and reduce their impact on the performance of
our pages but it’s early days and only some providers have implemented
them (&lt;a href="http://www.sergeychernyshev.com/blog/slo-js-and-how-to-speed-up-widgets/"&gt;Sergey Chernyshev&lt;/a&gt; has a some thoughts too).&lt;/p&gt;

&lt;p&gt;The challenge for web developers is understanding what the effect on
page load times could be, when most of the time the providers’ networks
remain reliable.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;&lt;strong&gt;Charles - a bandwidth limiting proxy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To test the impact providers can have if they perform poorly we need to
make the network connections to them unreliable and my tool of choice
for this sort of situation is Charles (&lt;a href="http://www.charlesproxy.com/"&gt;http://www.charlesproxy.com/&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Charles allows both low bandwidth and high latency to be simulated,
either on an all sites or individual site basis.&lt;/p&gt;

&lt;p&gt;To enable throttling choose &lt;em&gt;Proxy&lt;/em&gt; -&gt; &lt;em&gt;Throttle Settings&lt;/em&gt; and
check the first box, the same dialog also enables configuration of
bandwidth and latency constraints, and the URLs they apply to.&lt;/p&gt;

&lt;p&gt;On the sites I tested, I throttled using high latency for each provider
individually - as an example here’s one for addthis.com with the latency
set to ten seconds.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://andydavies.me/blog/images/charles-throttle-settings.png"&gt;&lt;/p&gt;

&lt;p&gt;I also used the normal waterfall tools (Firebug and WebKit inspector) to
see when onload was being fired at, so I could experiment with
asynchronous loading to mitigate the effect of the latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Look out for subtle failures!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One webapp I tested used the widgets from addthis.com and even with long
latencies set, the pages appeared to load quickly, but further testing
found the tour was broken - clicking the button just replaced the
current page with an image&lt;/p&gt;

&lt;p&gt;The tour used lightbox to display a series of images, the delay in
downloading the javascript from addthis prevented the onload event from
being fired and so the lightbox code wasn’t being inserted into the
page.&lt;/p&gt;

&lt;p&gt;Charles works on Windows, Mac and Linux, and has a free trial, so give
it a try. Find the components that cause problems for you and raise the
issue with their providers.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/-wL33TN_WQE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2010/10/01/testing-how-slow-third-party-components-affect-your-page-load-times/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[The Need For Speed... why slow page load times matter]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/AVU189Uqu48/" />
    <updated>2010-09-20T00:00:00+01:00</updated>
    <id>http://andydavies.me/blog/2010/09/20/the-need-for-speed-dot-dot-dot-why-slow-page-load-times-matter</id>
    <content type="html">&lt;p&gt;About a week ago, I did a presentation at &lt;a href="http://www.barcampstroud.co.uk/" title="BarCamp Stroud"&gt;BarCamp Stroud&lt;/a&gt; on why page
load times matter and things that can be done to improve them.&lt;/p&gt;

&lt;p&gt;It was fun to present and share what I’d learnt on a topic I’d spent a
lot of time investigating and implementing for a WebApp I run (got quite
a few things still left to do)&lt;/p&gt;

&lt;p&gt;Here’s the presentation for anyone who’s interested, and there will
probably more as I’ve already made some notes on other things to cover.&lt;/p&gt;

&lt;iframe src="http://www.slideshare.net/slideshow/embed_code/5191931?rel=0" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen&gt; &lt;/iframe&gt;


&lt;p&gt; &lt;div style="margin-bottom:5px"&gt; &lt;strong&gt; &lt;a href="http://www.slideshare.net/AndyDavies/the-need-for-speed-5191931" title="The Need For Speed" target="_blank"&gt;The Need For Speed&lt;/a&gt; &lt;/strong&gt; from &lt;strong&gt;&lt;a href="http://www.slideshare.net/AndyDavies" target="_blank"&gt;Andy Davies&lt;/a&gt;&lt;/strong&gt; &lt;/div&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/AVU189Uqu48" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2010/09/20/the-need-for-speed-dot-dot-dot-why-slow-page-load-times-matter/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[.net and ISA Server - reducing bandwidth consumption]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/1xm3-cR-GwA/" />
    <updated>2010-07-18T00:00:00+01:00</updated>
    <id>http://andydavies.me/blog/2010/07/18/dot-net-and-isa-server-reducing-bandwidth-consumption</id>
    <content type="html">&lt;p&gt;Earlier this year I came across some problems with some .net resources
not being cached by ISA Server (&lt;a href="http://andydavies.me/blog/2010/01/19/dot-net-and-isa-server-a-match-made-in-hell/"&gt;.net and ISA Server - a match made in hell?&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The problem in a nutshell is that by default ISA Server doesn’t cache
URLs that have query parameters, and the method .net uses to serve
static resources that are bundled in .dlls relies on query parameters.&lt;/p&gt;

&lt;p&gt;When .net uses the Microsoft AJAX framework, script elements like the
one below are inserted into the page&lt;/p&gt;

&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ScriptResource.axd?d=ki7GLYn2P5z-CEtE0SsvKYJhnTEkD13edwjg24cmxWe4aD03WzKyGXQD45nYCFy70&amp;amp;t=633178683580000000&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;After looking at some of the lastest developments in .net 4.0 I discovered that ScriptManager
could be used to serve out static versions of the AJAX framework (even in versions of
.net before 4.0).&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;After a few attempts I came up with this code that takes the
ScriptResource.axd references in the page and replaces them with static
scripts instead, which are of course generally cachable by ISA
Server&lt;/p&gt;

&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;asp:ScriptManager&lt;/span&gt; &lt;span class="na"&gt;ID=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Script&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;runat=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;EnablePartialRendering=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;&amp;lt;Script&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nt"&gt;&amp;lt;asp:ScriptReference&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;MicrosoftAjax.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;Assembly=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;System.Web.Extensions&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;Path=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/js/ms/MicrosoftAjax.js&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nt"&gt;&amp;lt;asp:ScriptReference&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;MicrosoftAjaxWebForms.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;Assembly=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;System.Web.Extensions&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;Path=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/js/ms/MicrosoftAjaxWebForms.js&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;&amp;lt;/Scripts&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;/asp:ScriptManager&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;(the release i.e. minified, versions of the scripts within the MS AJAX
framework have been placed in /js/ms)&lt;/p&gt;

&lt;p&gt;By default the scripts won’t be served gzipped, or with the long expiry
times that ScriptResource normally serves them with but this can be
addresses by configuring IIS (which is how it should be in my view)&lt;/p&gt;

&lt;p&gt;We’re still measuring how much this improves our page load times
and how much it reduces our bandwidth consumption but it looks to make a
significant difference.&lt;/p&gt;

&lt;p&gt;If you’re interested Dave Reed has written more on what’s possible
with ScriptManager in .net 4.0 - &lt;a href="http://weblogs.asp.net/infinitiesloop/archive/2009/11/23/asp-net-4-0-scriptmanager-improvements.aspx"&gt;ASP.NET 4.0 ScriptManager Improvements&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/1xm3-cR-GwA" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2010/07/18/dot-net-and-isa-server-reducing-bandwidth-consumption/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[.net and ISA Server - a match made in hell?]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/r-S8anr0vvE/" />
    <updated>2010-01-19T00:00:00+00:00</updated>
    <id>http://andydavies.me/blog/2010/01/19/dot-net-and-isa-server-a-match-made-in-hell</id>
    <content type="html">&lt;p&gt;I’ve been looking at the bandwidth consumption of a .net based webapp
and working with the developers to implement many of the common
recommendations for improving front-end performance - minifying,
gzipping, cache-control headers etc - we’ve noticed some improvements in
performance but we’ve also noticed some oddities.&lt;/p&gt;

&lt;p&gt;.net has the ability to embed static resources e.g. javascript, css
etc., in a .dll and then these can be served to the browser using a
special handler - ScriptResource.axd for the Microsoft AJAX framework
and WebResource.axd for others.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;Typically these appear in a web page looking something like this:&lt;/p&gt;

&lt;figure class='code'&gt; &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;“/WebResource.axd?d=D_qnz75P-Xnx_WWFT0nC0A2&amp;amp;t=633926346394042220”&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;“text/javascript”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;“/ScriptResource.axd?d=ki7GLYn2P5z-CEtE0SsvKYJhnTEkD13edwjg24cmxWe4aD03WzKyGXQD45nYCFy70&amp;amp;t=633178683580000000&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;”text/javascript&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;(The d in the query string uniquely identifies the resource, and t is a
timestamp)&lt;/p&gt;

&lt;p&gt;The WebForms javascript that’s served via WebResource.axd, hasn’t been
minified or gzipped but at least it has some cache-control headers. The
scripts served out but ScriptResource.axd are somewhat better, the
release versions are minified, gzipped if the browser supports it, and
served with a long expiry time, so should be ideal for caching.&lt;/p&gt;

&lt;p&gt;Why Microsoft chose URL handlers instead of nice plain and simple static
files is beyond me (but then most of the .net framework seems to be
about over complicating simple things)&lt;/p&gt;

&lt;p&gt;The traffic to our production servers is monitored via Oracle REUI which
allows us to slice and dice the information in it’s cubes so we can see
response times, which URLs are requested most frequently, what’s
consuming the most bandwidth etc.&lt;/p&gt;

&lt;p&gt;After making several changes to try to reduce bandwidth consumption,
ScriptResource.axd was still at the top of the pile of URLs by bandwidth
and it wasn’t clear why until we started looking at our users
environments in a bit more details.&lt;/p&gt;

&lt;p&gt;Most of our customers are schools and they generally have a gateway
cache of some form, increasingly this appears to be ISA Server.&lt;/p&gt;

&lt;p&gt;By default ISA Server removes the accept-encoding header so users will
get the uncompressed versions of scripts and other compressible
resources (Steve Souders covers this in &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0596522304/andsnot-20"&gt;Even Faster Websites&lt;/a&gt; ).
There are some scripts around that will change this setting but it
appears not many people have implemented them.\
&lt;span&gt;\
&lt;span&gt;Also ISA Server doesn’t cache URLs with query string parameters (I
can see the point of this) but it means that by default all those .net
resources that are served using WebResource.axd and ScriptResource.axd
aren’t being cached.&lt;/p&gt;

&lt;p&gt;There are ways of using the asp:ScriptManager control to replace the
ScriptResource.axd URLs with references to static files but there
appears to be no way of doing that for WebResource.axd&lt;/p&gt;

&lt;p&gt;It appears Microsoft have managed to develop a web framework and a proxy
caching product that don’t work well together… the words arse and elbow
spring to mind…&lt;/p&gt;

&lt;p&gt;(Over the next few weeks I’ll be spending some time looking further into
this and also comparing the ISA Server behaviour with the Squid based
proxies that some of the other schools in the UK have. I’ll report back
when I know more)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/r-S8anr0vvE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2010/01/19/dot-net-and-isa-server-a-match-made-in-hell/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[From RSS to delicious via ping.fm and twitterfeed]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/YJiYfsbdgYE/" />
    <updated>2009-01-29T00:00:00+00:00</updated>
    <id>http://andydavies.me/blog/2009/01/29/from-rss-to-delicious-via-ping-dot-fm-and-twitterfeed</id>
    <content type="html">&lt;p&gt;One of my continuing frustrations in the love/hate relationship I have
with delicious is there’s no easy way of getting items from an RSS feed
into delicious.&lt;/p&gt;

&lt;p&gt;I’ve got stuff I’ve ‘liked’ in FriendFeed, starred items in Google
reader, favourites on Slideshare, Twitter etc,  that I want to pull
directly into one place and that place is delicious, but it seems
delicious aren’t interested in making my life easy.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;Apart from bitching on the delicious forums, I’ve been fiddling with
various ways of filling the gap for a while and finally I think I’ve
found a way of partially filling it using &lt;a href="http://ping.fm"&gt;ping.fm&lt;/a&gt; and
&lt;a href="http://twitterfeed.com"&gt;twitterfeed&lt;/a&gt;. It’s got a few limitations but it may be good enough
for now.&lt;/p&gt;

&lt;p&gt;Here’s a list of the steps needed to get things up and working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you don’t have a &lt;a href="http://ping.fm"&gt;ping.fm&lt;/a&gt; account already, head over and
create one&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add your delicious account so that ping.fm can post to it (warning
you have to give them your delicious password)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add some form of micro-blogging/blogging account too. This is needed
for the link from twitterfeed to work, I used tumblr (but again I
have to give my tumblr password, has no-one heard of OAuth?)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now head over to &lt;a href="http://twitterfeed.com"&gt;twitterfeed&lt;/a&gt;, and create an account if you need
one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new feed for ping.fm&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;You’ll need your ping.fm API key which you can get from &lt;a href="http://ping.fm/key"&gt;ping.fm/key&lt;/a&gt;,
and you’ll also need to pick a posting method - I chose ‘microblogging’
( but I wasn’t able to make any choice until I added the tumblr account)&lt;/p&gt;

&lt;p&gt;Add in the details of the feed you want to push into delicious along
with how often the feed should be checked - I choose to have the feeds
checked as often as possible and have as many items as I can pushed
across.&lt;/p&gt;

&lt;p&gt;By default twitterfeed shortens URLs using tinyurl, you can either stick
with this or choose an alternative (I used bit.ly, but that’s just a
personal preference)&lt;/p&gt;

&lt;p&gt;Finally in the field ‘Prefix each tweet with’ add ‘@de’, this tells
ping.fm to forward the item to delicious&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeat the above step for as many feeds as you want to pull into
delicious&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Hopefully, if everything is right you should soon have items arriving in
your delicious account.&lt;/p&gt;

&lt;p&gt;The approach does have a few drawbacks though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;twitterfeed shortens the URLs, and delicious has no way of expanding
them, so the tags from other users can’t be applied to bookmark. The
original URL being destroyed will also be a problem for people who
use delicious to keep track of others who bookmark their blog posts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first time twitterfeed does it’s thing it only collects the most
recent RSS item so all the other items remain uncollected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;twitterfeed only collects five items at time from each feed so it
may be possible to build up a backlog if you added a lot of items to
your feed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have to give ping.fm your delicious login details and probably
login details for another service too&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The bookmarks bypass my delicious inbox and I’m not sure whether
this is a good thing or not - I don’t always want to keep all the
items I like of Friendfeed, or star in Google Reader so having them
arrive in the inbox for a final last filter seems like a good idea&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a item already has tags in the feed delicious can’t make use of
them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;As a word of warning I’ve also got no idea what happens if one of the
items already exists in my delicious collection and ping.fm tries to add
it from a feed, so perhaps I need to check that.&lt;/p&gt;

&lt;p&gt;It’s an imperfect solution but I’m going to give it a go for a while to
see how it works, ultimately this is something delicious and other
social bookmarking sites should provide, indeed if one of the other
sites introduces the ability to add bookmarks from RSS I’m likely to
jump ship and leave delicious behind.&lt;/p&gt;

&lt;p&gt;Finally if you do decide to go down this route think about making a
donation to twitterfeed, Mario offers a great service for free.&lt;/p&gt;

&lt;p&gt;(Oh and thanks to Scoble, whose &lt;a href="http://friendfeed.com/e/bb215e6d-5093-41c5-9491-30ec55f6b2eb/Testing-world-wide-domination-without-duplication/"&gt;broadcast of his plan for world domination&lt;/a&gt;
led me to checkout ping.fm)&lt;/p&gt;

&lt;p&gt;If anyone comes up with any improvements or alternative ways of tacking
this, I’d be very interested in hearing them.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/YJiYfsbdgYE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2009/01/29/from-rss-to-delicious-via-ping-dot-fm-and-twitterfeed/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Alas, twitter cripples SMS in the UK (and elsewhere)]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/1qbW8ORVuHk/" />
    <updated>2008-08-14T00:00:00+01:00</updated>
    <id>http://andydavies.me/blog/2008/08/14/alas-twitter-cripples-sms-in-the-uk-and-elsewhere</id>
    <content type="html">&lt;p&gt;Woke up this morning to an email from twitter saying they were scrapping
outbound SMS messages for the portion of the world that charges for
sending rather than receiving text messages i.e. anywhere that’s not the
US, Canada or India.&lt;/p&gt;

&lt;p&gt;The same message is on their blog too - &lt;a href="http://blog.twitter.com/2008/08/changes-for-some-sms-usersgood-and-bad.html"&gt;Changes for Some SMS Users—Good
and Bad News&lt;/a&gt; - and despite the title there was no good news in the
post, only the vague promise that they’d introduce new local SMS numbers
for unspecified countries within Europe in the coming weeks and months.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;I can understand why they’ve done this - the costs of sending all the
messages must burn through money - but by removing the service before a
replacement is available I think they’ve screwed up.&lt;/p&gt;

&lt;p&gt;Unlike the US, Canada and India, most of the world charges people for
sending text messages but they also offer a way to charging people for
receiving messages via &lt;a href="http://en.wikipedia.org/wiki/Reverse_SMS_billing"&gt;SMS reverse billing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In my view, twitter should have had this option up and ready to go
before scrapping their existing SMS service. I guess the danger for them
is that their users will continue to migrate to other service
(&lt;a href="http://identi.ca/"&gt;http://identi.ca/&lt;/a&gt; for example) or other ways of being notified e.g.
RSS on phones, damaging their future revenue streams.&lt;/p&gt;

&lt;p&gt;Perhaps the fact twitter are US based limits their understanding as to
how people use mobile phones and how the networks work in the rest of
the world?&lt;/p&gt;

&lt;p&gt;Also as twitter is pretty open (via rss and the API), perhaps there’s
also an opportunity for someone to set up a third party service to
provide and charge for SMS updates?&lt;/p&gt;

&lt;p&gt;Of course this screws up my traffic bot (&lt;a href="http://twitter.com/UK_M5_Traffic"&gt;uk_m5_traffic&lt;/a&gt;) as it
relies on twitter to send out the SMS notifications. In the short term I
can set up the feed reader on my phone to update from the RSS feed but
longer term I guess I’ll need to see what twitter do and what other
options I’ve got.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/1qbW8ORVuHk" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2008/08/14/alas-twitter-cripples-sms-in-the-uk-and-elsewhere/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Have you ever launched a product you've been ashamed of?]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/Rr6AARDi6s4/" />
    <updated>2008-05-22T00:00:00+01:00</updated>
    <id>http://andydavies.me/blog/2008/05/22/have-you-ever-launched-a-product-youve-been-ashamed-of</id>
    <content type="html">&lt;p&gt;In a few weeks time the product I’ve spent the last eighteen months on
will launch. I’ve built and launched products before and despite their
quirks and issues I’ve been proud of them all, but this time it’s
different, this time I have an almost overwhelming feeling of sadness.&lt;/p&gt;

&lt;p&gt;I’d describe myself as a pragmatic perfectionist (I like things done
right but the closer the deadlines get the more pragmatic I become), but
this time I seem to have run out of pragmatism.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;Part of me (I’m not sure how much) doesn’t care about this product any
more and I find that really sad as I care about what I do but the effort
it’s taken to get it this far and the frustrations involved in
development have taken their toll. When I told my wife about how I felt
she just put her arms around me as she understood the magnitude of what
it meant (no chance of me ever complaining that my wife doesn’t
understand me!).&lt;/p&gt;

&lt;p&gt;Functionally the product appears to work OK, but there’s so much that’s
clunky and inconsistent about the way it’s been built, behaves and
looks, and in the time we’ve had for development many of them could have
been addressed.&lt;/p&gt;

&lt;p&gt;The problem as I see it is that the software development side of the
product was outsourced and I don’t think the company I work for picked
the right partner or have learnt from their previous experiences with
this partner.&lt;/p&gt;

&lt;p&gt;In general I believe product development is far too important to
outsource, as “no-one cares about your product like you do”. I knew the
development was being outsourced when I joined, but at the time I just
finished a contract job and needed another so was in the position of
“beggars can’t be choosers”&lt;/p&gt;

&lt;p&gt;The product had already had a few false starts before I arrived but
between us we finally got it really moving early last year some of the
early prototypes were promising but the immaturity of our partner
quickly started to show through.&lt;/p&gt;

&lt;p&gt;Their web development techniques seemed to be stuck at around five years
ago, all tables and no semantic markup or styles, where there were
styles they tended to be in-line rather than an in a stylesheet so you
could never be sure that a change in style would be reflected across the
product. Their javascript was quite frankly appalling (badly structured
and indecipherable) and I’m sure they wouldn’t have accepted the same
quality of code in the web-services components of the product.&lt;/p&gt;

&lt;p&gt;I’ve spent the last year teaching a development team about everything
from web development techniques (semantic markup, how to use css, why
they should use a library like jquery (or prototype etc.) instead of
writing their own DOM manipulation code), through web infrastructure
(how caching can make a huge difference to the performance of our
product - we’re serving quite a lot of media rich content, the role
load-balancing has in scaling and high availability) though to how we
can’t make users decisions for them (if the user wants to delete
something, let them just warn them of the consequences before they do).&lt;/p&gt;

&lt;p&gt;Even now I’m not sure how much of what I’ve tried to teach them has
stuck, sometimes I see glimmers that it has and sometimes I see the old
ways are back, all I know is that this product has just been all take
with no return and I need something back, so it’s time to find something
else to move on to…&lt;/p&gt;

&lt;p&gt;(I will try to write more about this product, what’s gone wrong and what
I think I’ve learnt in the next couple of weeks, just need a bit more
time to reflect first)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/Rr6AARDi6s4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2008/05/22/have-you-ever-launched-a-product-youve-been-ashamed-of/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Feed readers and social bookmarking - a missing link?]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/VfOhkVAyVOo/" />
    <updated>2008-04-14T00:00:00+01:00</updated>
    <id>http://andydavies.me/blog/2008/04/14/feed-readers-and-social-bookmarking-a-missing-link</id>
    <content type="html">&lt;p&gt;Why isn’t there an easy way of getting items from a feed reader into a
social bookmarking service?&lt;/p&gt;

&lt;p&gt;Like many people (or is it just the geeks?) I use Google Reader to keep
up-to-date with news and opinions from around the web, and del.icio.us
to bookmark the interesting things I come across. A couple of weeks ago
MichaelSearcy’s analysis of &lt;a href="http://googlesystem.blogspot.com/2008/03/googles-broken-bookmarking-systems.html"&gt;Google’s Broken Bookmarking Systems&lt;/a&gt;
popped up and got me thinking about how I could get more out of the
Reader/del.icio.us combination and what it would take.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;In Reader I tend to mark items I want to read later or keep for the
future with a star, sometimes I get around to reading them again, and
sometimes I get around to adding them to del.icio.us but sometimes
despite my best intentions I don’t and slowly I’m building up two
parallel sets of items I want to keep, one in Reader and one in
del.icio.us.&lt;/p&gt;

&lt;p&gt;What I need is an easy way to get items I want to keep from Reader into
del.icio.us - currently I either have to open the item up in a new
browser tab and then use the del.icio.us toolbar to add it, or use a
Greasemonkey script to add the ability to post straight to del.icio.us
from Reader and it’s not always how I want to work.&lt;/p&gt;

&lt;p&gt;What I want to be able to do is mark something as shared in Reader and
have it appear in my del.icio.us inbox and from there I can choose to
save it (being able to delete items from the inbox would be helpful
too).&lt;/p&gt;

&lt;p&gt;Reader already produces a feed for shared items (and other the labels if
you know how to get at them), but del.icio.us doesn’t have any way of
consuming feeds and they don’t seem too keen on the idea of adding it.
I’ve had a brief scan of some of the other social bookmarking sites and
they don’t seem to support getting bookmarks from a feed either, so
perhaps there’s an opportunity for someone?&lt;/p&gt;

&lt;p&gt;For the second part of the puzzle I’d like a way of having any tags I
attach Reader to be included in the feed, this is something del.icio.us
does with its feeds so Reader could do it via something like &lt;a href="http://microformats.org/wiki/xfolk"&gt;xFolk
microformat&lt;/a&gt;, then not only will my shared items arrive in my
del.icio.us inbox but they’ll also arrive with tags already attached.&lt;/p&gt;

&lt;p&gt;Data portability and how private data can be shared between social
services is a hot topic but right now, I’d settle for services that can
share my public information!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/VfOhkVAyVOo" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2008/04/14/feed-readers-and-social-bookmarking-a-missing-link/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Ideas for improving my twitter traffic bot]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/hzOdgRcSSTk/" />
    <updated>2008-03-25T00:00:00+00:00</updated>
    <id>http://andydavies.me/blog/2008/03/25/ideas-for-improving-my-twitter-traffic-bot</id>
    <content type="html">&lt;p&gt;The bot I built for keeping me up-to-date with traffic conditions on the
M5 has proved handy a few times but it also suffers from a couple of
drawbacks…&lt;/p&gt;

&lt;p&gt;It only covers the M5, and the whole of the M5 at that, if someone wants
updates on the M4, or  just part of the M5 there’s no way for them to
choose the information that’s relevant to them.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;TwitterFeed also introduces a time delay and even on it’s most frequent
setting it will only check a feed every 30 minutes - as we found out on
Friday morning when we ran into a jam just north of the M4/M5
interchange only to hear our phones get the text message telling us
there was a hold up!&lt;/p&gt;

&lt;p&gt;So I’ve been thinking about building a new bot that would allow someone
to choose the roads (and parts of)  they want to receive updates for.&lt;/p&gt;

&lt;p&gt;The bot would allow people to send it messages about the roads they’re
interested in, grab the traffic feed from the Highways Agency (and
perhaps other feeds) on a regular basis, and when there’s something to
tell people message them via twitter.&lt;/p&gt;

&lt;p&gt;I’m thinking of something that’s quite similar to &lt;a href="http://www.mytrade.com/api/twitter/"&gt;mytrade’s twitter
bot&lt;/a&gt; in concept but needs to be more frequent in it’s updates. The
language used to communicate with the bot also needs to allow richer
concepts as in stock watching terms it needs to support not just
broadcasting prices, but broadcasting when a price crosses a user set
threshold.&lt;/p&gt;

&lt;p&gt;The things I’m looking at right now are:&lt;/p&gt;

&lt;p&gt;The syntax for communicating with the bot - something similar to the
syntax of mytrade’s bot might be good enough but I need to have a hunt
around to see what alternatives are about. (I’m not sure I like
twitter’s format for direct messaging and wonder whether !username might
be fit better with the @username format used elsewhere on twitter, but
there’s not a lot I can do about that!)&lt;/p&gt;

&lt;p&gt;Whether to use the REST API or Jabber / XMPP for communicating with
twitter. The API pages suggest using Jabber / XMPP for bots that use
direct messages so perhaps I’ll follow their advice to begin with.&lt;/p&gt;

&lt;p&gt;So time to brush off my coding skills and as I (hopefully) make some
progress I’ll add some updates here.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/hzOdgRcSSTk" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2008/03/25/ideas-for-improving-my-twitter-traffic-bot/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Some other online tools for filtering RSS]]></title>
    <link href="http://feedproxy.google.com/~r/andydavies/~3/yTQqtDDigo0/" />
    <updated>2008-03-07T21:35:00+00:00</updated>
    <id>http://andydavies.me/blog/2008/03/07/some-other-online-tools-for-filtering-rss</id>
    <content type="html">&lt;p&gt;UK_M5_Traffic currently uses Yahoo Pipes to filter and manipulate the
RSS feed it’s based on but I came across a post on &lt;a href="http://www.readwriteweb.com/archives/6_ways_to_filter_your_rss_feeds.php"&gt;Read Write Web&lt;/a&gt;
that lists some other online tools that might be worth exploring.
&lt;a href="http://www.zaptxt.com/"&gt;ZapTXT&lt;/a&gt; looks to be the most interesting but won’t send text messages
outside the US and Canada at the moment.&lt;/p&gt;

&lt;p&gt;In the short term I’ll probably carry on using Pipes as I’m now using
it’s regex features to cut down the message to make it a bit more punchy
and readable.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andydavies/~4/yTQqtDDigo0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://andydavies.me/blog/2008/03/07/some-other-online-tools-for-filtering-rss/</feedburner:origLink></entry>
  
</feed>
