<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Category: performance | JP's blog]]></title>
  <link href="http://blog.jphpsf.com/categories/performance/atom.xml" rel="self"/>
  <link href="http://blog.jphpsf.com/"/>
  <updated>2012-10-31T08:40:05-07:00</updated>
  <id>http://blog.jphpsf.com/</id>
  <author>
    <name><![CDATA[JP]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Share the #webperf love]]></title>
    <link href="http://blog.jphpsf.com/2012/08/28/share-the-webperf-love/"/>
    <updated>2012-08-28T09:15:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/08/28/share-the-webperf-love</id>
    <content type="html"><![CDATA[<p><em>August is Speed Awareness Month! This blog post was originally published
<a href="http://www.speedawarenessmonth.com/share-the-webperf-love/">yesterday</a>
 on the <a href="http://www.speedawarenessmonth.com/">Speed Awareness Month blog</a>.
Check it out to learn tips and tools for speeding up your website.</em></p>

<p>If you care about web performance, you are likely to know and use tools
such as WebPagetest, HTTP Archive, YSlow, Boomerang, etc. Whether your level
is novice or expert with these tools, using them is only one side of the
coin. What about contributing back to them? Those tools are open source
which means you - whether you are a novice or an expert - can help out.</p>

<p>Open source represents one aspect of the web performance community.
User group (meetups) focused on web performance are another.</p>

<p>In this post, I will explain how you can get started and get involved
in our continuously growing community.</p>

<!-- more -->


<h2>Open Source Contributions</h2>

<p>There are many ways one can contribute to performance open source projects.
The first common step is usually to find the source repository. This
information is typically found on the project's official website. Look for
links such as <em>"Contribute"</em>, <em>"Source Code"</em> or <em>"Fork me on GitHub"</em>. For
instance, see the <a href="http://yslow.org/">YSlow website</a>, which includes a link
to the <em>"Source"</em> in the top navigation as well as a <em>"Fork me on GitHub"</em>
banner in the top left corner:</p>

<p><img src="/images/blog/2012-08-09-yslow-banner.png" title="YSlow example" ></p>

<p>Most open source projects nowadays are hosted on GitHub or Google Code. Here
are the repositories for some of the most popular web performance related ones:</p>

<ul>
<li><a href="https://code.google.com/p/webpagetest">WebPagetest</a></li>
<li><a href="https://code.google.com/p/httparchive">HTTP Archive</a></li>
<li><a href="https://github.com/lognormal/boomerang">Boomerang</a></li>
<li><a href="https://github.com/marcelduran/yslow">YSlow</a></li>
<li><a href="https://github.com/sergeychernyshev/showslow">ShowSlow</a></li>
</ul>


<h3>1. Contribute code:</h3>

<p>Now that you've located the repository, it's time to contribute! Do you have
an idea for a new feature? Did you find a bug or see an issue in the bug tracker
that you can resolve? Implement the new functionality or create a fix and send
a patch back to the author (or submit a pull request if the project is on GitHub).</p>

<h3>2. Testing and bug reports:</h3>

<p>Not a developer or don't think you have the coding chops? Not a problem. There
are other ways to contribute. If you encounter a bug as you use the software, make
sure to report the issue in the bug tracker. Chances are that if you encounter a
problem, others might as well, but make sure to search the bug tracker first. In
addition to bugs, you can submit feature requests or enhancement suggestions.
As an example, this is the <a href="https://code.google.com/p/httparchive/issues/list">bug tracker for the HTTP archive project</a>.</p>

<h3>3. Help with user support:</h3>

<p>Users might encounter issues and in turn will have some questions. A first place to
look is the issue tracker. If you see an issue for which you know the solution,
feel free to give an answer to the original poster. Other places to look at are
mailings lists or IRC channels. Here is <a href="https://showslow.uservoice.com/">some user feedback for the ShowSlow project</a>.</p>

<h3>4. Contribute to the documentation or website:</h3>

<p>As you read the documentation, report any error you might find. If you have writing
skills, maybe you can help? Do you see any mistakes or missing information? Do you
have suggestions for new howtos or guides? Write them! Often projects are using wikis
which make it easy to add or edit content. If the documentation is not available in
your native language, consider translating it. The same can be done for the
project's website: you can help maintain it with new content, corrections,
translations, etc. For instance, this is the <a href="https://github.com/marcelduran/yslow/wiki">YSlow user documentation wiki</a>.</p>

<h3>5. Give financial support:</h3>

<p>Open source projects are often run by individuals on their spare time and personal money.
If you want to support the project, donate some money (look for a <em>"Donate"</em> link) or
have your company offer to sponsor the project.</p>

<h3>6. Live instances:</h3>

<p>What about providing hosting? Do you have bandwidth and/or hardware available? Tools like
WebPagetest or ShowSlow provide live instances hosted all over the world. Do you have a
hosting location to offer? Get in touch! You'll find the contact information on the project's
website. The following page for instance, gives <a href="https://sites.google.com/a/webpagetest.org/docs/other-resources/hosting-a-test-location">details about hosting a WebPagetest instance</a>.</p>

<h3>7. Thank yous:</h3>

<p>A very simple gesture, yet really appreciated by open source developers: express your
appreciation and thank them. It's as simple as a @mention on Twitter, but why not send
a nice email or a post card?</p>

<p>These are a few ideas to get started with open source. Still not sure where to start?
Just ask where you can help! I am sure the project owners will be happy to indicate
where help is needed.</p>

<h2>Meetups</h2>

<p>Open source projects are an important element of the performance community. Meetups
are another great way to participate. There are <a href="http://web-performance.meetup.com/">quite a few performance meetup groups</a>
already. Check them out!</p>

<p>Don't see one close to you? You could start one. I've seen three different formats
so far. First, the classic tech talk with Q&amp;A: a speaker gives a presentation on performance
followed by a Q&amp;A session. Second, the <em>Meet 4 Speed</em>: an open format where attendees
can show their work on performance or bring a problem and get help from others.
Finally, the drink up: meet over a performance enhancing pint (I shamelessly stole that
line from my good friend Aaron) and talk shop with performance people.</p>

<p>Are you or your company working on really cool performance projects? Do you have
some results or metrics to share? I love when companies are sharing their success
stories ("We implemented the following web performance tweaks and we increased our sales by
X%"!). Propose a talk to your local meetup. As an organizer myself, I am
always looking for people that have interesting things to share on web performance.</p>

<h2>Other suggestions</h2>

<p>There are a couple of other suggestions that I think are worth mentioning.</p>

<p>The first is blogging: you can share your knowledge with others on your own blog or
as a guest blogger (see the <a href="http://calendar.perfplanet.com/">Performance Calendar</a> for
instance).</p>

<p>And let's not forget forums: one example is the <a href="http://www.webpagetest.org/forums/">forum hosted by the WebPagetest project</a>
. This is a good place to find some help on performance or help others.</p>

<h2>Wrap up</h2>

<p>This is what the <a href="http://www.speedawarenessmonth.com/"><em>Speed Awareness Month</em></a> is
about. Share the #webperf love: evangelize performance best practices, raise
awereness and help improve the invaluable tools from our web performance toolbox.</p>

<p>Do you have feedback on this post? Feel free to comment below or to contact me via Twitter
(<a href="http://twitter.com/jphpsf">@jphpsf</a>).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Squeezing Octopress for faster load times]]></title>
    <link href="http://blog.jphpsf.com/2012/06/12/squeezing-octopress-for-faster-load-times/"/>
    <updated>2012-06-12T21:15:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/06/12/squeezing-octopress-for-faster-load-times</id>
    <content type="html"><![CDATA[<p>This blog runs an out of the box <a href="http://octopress.org/">Octopress</a> setup. I love Octopress. It's a great framework. It's trivial to setup, gets out of your way and it just works.</p>

<p>Being passionate about web performance optimization, I decided to <em>"eat my own dog food"</em> and look at how I could improve the load time of my blog.</p>

<!-- more -->


<h2>Baseline</h2>

<p>I've measured the homepage of the blog with my usual weapon of choice, <a href="http://www.webpagetest.org/">WebPagetest</a>. Using Firefox and Chrome roughly yielded the same results:</p>

<ul>
<li>DOM ready fires at about 1.2 seconds.</li>
<li>The page is fully loaded between 2.8 and 3 seconds.</li>
<li>There are 21 HTTP requests for a total of 244KB.</li>
</ul>


<h2>Optimizing Javascript</h2>

<p>The first obvious improvment is with javascript. The default Octopress installation will load 4 javascript files as shown in the screenshot below:</p>

<p><img src="/images/blog/2012-06-10-4-script-tags.png" title="Javascript script tags" ></p>

<p>This is bad because browsers usually have a limit in the number of concurrent downloads they can perform at the same time. While this limit has been increased in the recent years, it is still a good practice to concatenate all the Javascript resources into one file. I created a file under <code>source/javascripts/all.js</code> in which I combined all 4 files. While I was at it, I minified <code>all.js</code> to make it smaller and moved the file from the head to the bottom of the page.</p>

<p>Then I removed the 3 script tags from <code>source/_includes/head.html</code>:</p>

<p><div class='bogus-wrapper'><notextile><figure class='code'><figcaption><span>Remove script tags  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;/p&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/modernizr-2.0.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/ender.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/octopress.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;p&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>

<p>And I added the following to <code>source/_includes/custom/after_footer.html</code>:</p>

<p><div class='bogus-wrapper'><notextile><figure class='code'><figcaption><span>Loading combined all.js  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;/p&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/all.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span> <span class="nt">/&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

The load time did not change: still around 2.8 seconds. However something broke: the sidebar fails to load my recent tweets because that code depends on some that were moved to the bottom of the page (as explained above). I fixed the dependency and merged all the twitter JS code into all.js. The twitter JS code can be found in `source/_includes/asides/twitter.html`:

<div class='bogus-wrapper'><notextile><figure class='code'><figcaption><span>Removing Twitter code  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nx">$</span><span class="p">.</span><span class="nx">domReady</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>    <span class="nx">getTwitterFeed</span><span class="p">(</span><span class="s2">&quot;jphpsf&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'><span class="nt">&lt;/script&gt;</span>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/twitter.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/script&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

_Disclaimer: this last change might need to be applied to other plugins or sidebar modules. Twitter is the only one I used and after this last change, my recent tweets were back._

Trying to improve the load time further, I decided to load the all.js file asynchronously. The blog content does not depend on any javascript, so it is ok to defer the load to later. I used the same pattern as the Google Analytics snippets, eg. in `source/_includes/custom/after_footer.html` I now have:

<div class='bogus-wrapper'><notextile><figure class='code'><figcaption><span>Loading all.js asynchronously  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">all</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;script&#39;</span><span class="p">);</span> <span class="nx">all</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="s1">&#39;text/javascript&#39;</span><span class="p">;</span> <span class="nx">all</span><span class="p">.</span><span class="nx">async</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span><span class='line'>  <span class="nx">all</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="s1">&#39;{ { root_url } }/javascripts/all.js&#39;</span><span class="p">;</span>
</span><span class='line'>  <span class="nx">s</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;script&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span> <span class="nx">s</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">all</span><span class="p">,</span> <span class="nx">s</span><span class="p">);</span>
</span><span class='line'><span class="p">})();</span>
</span><span class='line'><span class="nt">&lt;/script&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

This last change brings the DOM ready event to now fires at 0.8 seconds.

Brandon Mathis (the creator of Octopress) mentioned on Twitter his plans to integrate a JS preprocessor (in the same way than Octopress uses compass for CSS preprocessing). I would hope this could include the optimizations mentioned above.

After this change:

  - DOM ready fires at about 0.8 seconds (improved by 0.4 seconds).
  - The page is fully loaded between 2.8 and 3 seconds (no changes).
  - There are 17 HTTP requests for a total of 237KB (saved 4 requests and 7KB).

## Optimizing @font-face

Octopress includes the PT Sans font as a default and is including it on the page using `@font-face`. I noticed a flash of invisible content (see screenshot below). The issue is even more noticeable on mobile devices, which tends to be slower. This is something I noticed on other websites using `@font-face` as well (Octopress blogs or not).

<img src="/images/blog/2012-06-10-invisible-content.png" title="Invisible content" >

Paul Irish explains the problem in [this 2009 blog post](http://paulirish.com/2009/fighting-the-font-face-fout/). The flash of invisible content is actually here to avoid a flash of unstyled content (at least for WebKit browsers). When using `@font-face`, the browser needs to download the font file. If the file arrives late during the page load, then the browser first shows the content without the font applied and switches to using the font as soon as it arrives. This is called a flash of unstyled content (FOUC for short). To work around this issue, WebKit engineers make the content text invisible until the font is loaded. This is better than the unstyled flash, but it is still an issue. To minimize it, the key is to load the font as fast as possible. Removing the `@font-face` all together is a solution (the fastest font is the one you don't have to load) but for now I wanted to keep using a custom font, so I started digging.

The first thing I discovered was that I was actually loading 2 fonts (Ubuntu Condensed for the headers and PT Sans for everything else). That's 25KB and 59KB. One was loaded from my domain the other from Google's webfont CDN. I removed the Ubuntu font as PT Sans was looking just fine for the headers. Also, PT Sans leverages Google's webfont CDN. The load time dropped to 2.2 seconds. The DOM ready event fires now at 0.6 seconds. Great! Can we make it even faster?

Looking at my waterfall revealed that the font was loaded late after the DOM ready event. The font download finished at around 1.6 seconds. I am assuming that means the content is invisible until then (more on that later).

Paul Irish's blog post mentioned another technique: inline the font in the CSS file using data URI. This is a good idea because it removes 2 extra requests (Google's webfont CDN loads one CSS file and then the font file). Also, a CSS file can be gzipped which can lead to additional savings.

I removed the font face include tags from the `source/_includes/custom/head.html` and added the following to the `sass/custom/_styles.scss` file (note: I did not include the actual base 64 content of the font).

<div class='bogus-wrapper'><notextile><figure class='code'><figcaption><span>Optimized @font-face syntax  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'><span class="k">@font-face</span> <span class="p">{</span>
</span><span class='line'>  <span class="nt">font-family</span><span class="o">:</span> <span class="s1">&#39;PT Sans&#39;</span><span class="o">;</span>
</span><span class='line'>  <span class="nt">font-style</span><span class="o">:</span> <span class="nt">normal</span><span class="o">;</span>
</span><span class='line'>  <span class="nt">font-weight</span><span class="o">:</span> <span class="nt">normal</span><span class="o">;</span>
</span><span class='line'>  <span class="nt">src</span><span class="o">:</span> <span class="nt">local</span><span class="o">(</span><span class="s1">&#39;PT Sans&#39;</span><span class="o">),</span> <span class="nt">local</span><span class="o">(</span><span class="s1">&#39;PTSans-Regular&#39;</span><span class="o">),</span>
</span><span class='line'>    <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;data:application/x-font-woff;base64,[BASE64 FONT CONTENT GOES HERE]&#39;</span><span class="o">)</span> <span class="nt">format</span><span class="o">(</span><span class="s1">&#39;woff&#39;</span><span class="o">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

DOM ready happens slightly later at 0.8 sec but at this point the font is downloaded. Previously the font was ready at 1.6 seconds. This should improve the flash of invisible content problem.

Are we done with `@font-face`? No. I noticed an issue in Internet Explorer where the font seems to never load. It turned out to be a great hint for the next step. Data URI length is limited to 32KB in IE8 (according to [caniuse.com](http://caniuse.com/#search=uri)). Could I find a smaller font? A quick search for PT Sans lead me to [Font Squirrel](http://www.fontsquirrel.com/fonts/PT-Sans) which had the same font as Google webfont. However, it was smaller: 18K instead of 59K. I am not sure where that difference came from. The only difference I could see was visually: while very similar, the Google's webfont seemed to be more condensed than the Font Squirrel equivalent. In the end, I think the font is fine so I went ahead and added it to the CSS file.

To verify the impact of these optimizations we can use the comparison feature of WebPagetest which includes a film strip view as well as a video comparison service. The film strip screenshot below shows that the optimized version at the bottom, as expected, loads about 1 second faster:

<img src="/images/blog/2012-06-10-filmstrip.png" title="Film strip view" >

You can view WebPagetest video comparison by following [this link](http://www.webpagetest.org/video/view.php?id=120613_c753edf2bda3cad5429e8711667fb758721e164f).

After this change:

  - DOM ready fires at about 0.7 seconds (improved by 0.1 seconds).
  - The page is fully loaded in about 2 seconds (improved by 1 second).
  - There are 15 HTTP requests for a total of 172KB (saved 2 more requests and 65KB).

## Optimizing with Cloudflare

Another thing I wanted to investigate was [CloudFlare](https://cloudflare.com/). I am running this blog behind CloudFlare's security and performance proxy and was wondering about how the various settings could affect the load time and if CloudFlare was helping my blog to load faster.

I've enabled the performance proxy of CloudFlare since day one, so this blog should already benefit from CloudFlare optimizations. To determine the gains, I decided to disable the performance proxy and measure the page speed. I lost about 0.5 seconds on my load time doing so. The main difference appeared to be the size of downloaded content. It grew from 172KB to 248KB. The difference comes from gzipping/minifying assets such as CSS or Javascript. When bypassing the performance proxy, I hit Heroku's server directly and because I haven't configured Heroku to gzip or minify assets, it serves unoptimized content. CloudFlare's performance proxy shaves 0.5 seconds off of the load time, that's not bad.

WebPagetest pointed out that I was not setting the far expire header properly for my assets. CloudFlare actually takes care of that. The default value is pretty low, it is set to 4 hours. I tweaked it to use the recommended 30 days which improved my caching score on WebPagetest.

Another benefit is the CDN: the assets of my blog are deployed on CloudFlare's CDN. This is totally transparent to me (I did not have to make any changes to my blog's code) and is great for performance. The CDN stores content closer to the user hence allowing faster delivery. I am running out of time here, but I guess the impact could be verified with Webpagetest. One can pick various test locations and compare the performance with and without CDN.

The last feature I played with is [Rocket Loader](http://blog.cloudflare.com/56590463). It's a pretty clever Javascript loader. From what I've seen it speeds up a website in two ways. First it makes any javascript files load asynchronously. Second it caches them in the browser's local storage. Unfortunatelly, when I activated the feature, the comments powered by Disqus stopped working. Rocket Loader is currently under beta, so I guess there are a few things still left to iron out. In the end, I've already done some optimization to my blog's Javascript (previously explained) so I disabled Rocket Loader.

## Conclusion

I started with 21 HTTP requests for a total of 244KB and a page loading in about 3 seconds. After optimizations, the page is down to 15 requests for a total of 172KB. The page now fully loads in about 2 seconds.

This experiment was very interesting. The big take away was learning more about `@font-face` performance implications. I think barebone Octopress out of the box performance is not bad at all: the load time of my blog prior to the changes was decent. Yet, I was able to squeeze a little more speed with a few simple changes. I will contact Brandon Mathis (the creator of Octopress) to see if he would be interested by some of these tweaks. With Octopress being open source, patches are as easy as a pull request ;)

Now it's your turn! Do you have an Octopress blog? How is your load time? If you try the above tips, do you see any improvements? Do you have any other tips that I might have missed? Contact me via the comment form below, [Twitter](https://twitter.com/jphpsf) or the [Hacker News thread](http://news.ycombinator.com/item?id=4104356,) I'd love to hear from you :)

## Update September 2012

After weighting the pros and cons about the usage of @font-face, I've decided to remove the custom font I was using. In
the end, I value speed more than fancy typography. A basic font like Helvetica is perfectly fine for this blog :)

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Front End Performance Case Study: GitHub]]></title>
    <link href="http://blog.jphpsf.com/2012/04/28/front-end-performance-case-study-github/"/>
    <updated>2012-04-28T15:36:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/04/28/front-end-performance-case-study-github</id>
    <content type="html"><![CDATA[<p>A couple weeks ago, someone in my Twitter timeline retweeted the following tweets from <a href="https://twitter.com/dom_monster">DOM Monster</a>:</p>

<p><blockquote><p>In HTML5, quotes around attribute values are optional. Which means, omit them. Smaller, faster, less clutter.</p><footer><strong>@dom_monster</strong> <cite><a href='https://twitter.com/#!/dom_monster/status/184649270144663552'>View Original Tweet</a></cite></footer></blockquote></p>

<p><blockquote><p>Here's an example. This page from GitHub contains about 4,517 quote characters. Most of these can be omitted.<br/>https://github.com/rails/rails/commit/3756a3fdfe8d339a53bf347487342f93fd9e1edb</p><footer><strong>@dom_monster</strong> <cite><a href='https://twitter.com/#!/dom_monster/status/184652815615004672'>View Original Tweet</a></cite></footer></blockquote></p>

<p>This is a very specific and interesting performance optimization suggestion. I never really thought about it much or even looked at it to see what kind of performance impact, the omission of quote characters might have on a web page. However, after reading these tweets, I started to wonder: how well is GitHub doing on front end performance?</p>

<!-- more -->


<p><img src="/images/blog/2012-04-19-github-chrome-devtools.png" title="Chrome dev tools" ></p>

<p>A quick look at the Chrome dev tools with an empty cache for the GitHub url mentioned above showed a total load time of 5.43 seconds (onload at 3.33 and DOM ready at 1.33s) and an HTTP request count of 73 for a total of 1.36MB. That seemed a little high (for reference, the <a href="http://httparchive.org/trends.php">HTTP archive trends</a> reports an average of 84 requests for a total of about 1MB). As some of you who know me from the <a href="http://www.meetup.com/SF-Web-Performance-Group/">SF web performance meetup</a>, I really like dissecting web pages and figuring out what might make a given page slower.</p>

<p><em>Disclaimer: I do not work for GitHub and I have not contacted GitHub prior to writing this blog post. They might be aware of some of the issues and might be working on the front end performance of GitHub already. In any case, I would love to learn what they think of the following analysis.</em></p>

<h2>Webpagetest</h2>

<p>One of my favorite tools in my performance toolbox is <a href="http://www.webpagetest.org/">WebPagetest</a>. WebPagetest is a front end performance analysis tool that crawls a web page and generates a performance report card. It includes a lot of performance metrics, waterfall charts for first view and repeat view, page speed/yslow type of overview scores, ... Also, it runs on a variety of real browsers (you can choose between IE, Chrome, Firefox, etc).</p>

<p>I ran the previous GitHub url and you can see the results using the following links:</p>

<ul>
<li><a href="http://www.webpagetest.org/result/120417_4P_3ZS5T/">Performance report with IE8</a></li>
<li><a href="http://www.webpagetest.org/result/120417_VT_3ZRY4/">Performance report with Firefox 11</a></li>
</ul>


<p>I tried to run the test with Chrome as well but encountered some issues with SSL in WebPagetest (I haven't looked at the problem at this time and I am not sure if the issue is with Chrome or WebPagetest).</p>

<p>Let's dive in!</p>

<h2>Javascript blocks rendering</h2>

<p><img src="/images/blog/2012-04-19-js-blocks-rendering.png" title="Javascript blocks rendering" ></p>

<h3>The problem</h3>

<p>According to WebPagetest, the rendering starts pretty late (at around 6 seconds in Firefox and 3 seconds in IE).</p>

<p>In most browsers, a javascript <code>&lt;script&gt;</code> tag will block rendering as the browser is loading and parsing the javascript code. The reason for this is fairly simple: a javascript file might include code that could modify the HTML document via a <code>document.write()</code> for instance (<a href="http://www.stevesouders.com/blog/2012/04/10/dont-docwrite-scripts/">boooh, don't do that</a>) or any other DOM manipulation technique. As this might affect the rendered page, browsers usually stop any rendering activity while parsing and evaluating javascript.</p>

<p>If you look at the waterfalls, the rendering start on GitHub is delayed by 2 javascript files (from the file name it seems that one is the jQuery source code and the other is the actual GitHub javascript code).</p>

<h3>Solutions</h3>

<p>The 2 <code>&lt;script&gt;</code> tags are located at the top of the HTML document in the head. A performance best practice recommends to place the javascript <code>&lt;script&gt;</code> tags at the bottom of the HTML document (right before the <code>&lt;/body&gt;</code> closing tag) in order for the browser to start parsing the file as late as possible.</p>

<p>Another approach could be to use an asynchronous script loading technique (via a script loader such as <a href="http://labjs.com/">LABjs</a> or <a href="http://stevesouders.com/controljs/">ControlJS</a>; a custom solution as described <a href="http://mathiasbynens.be/notes/async-analytics-snippet">here</a> would work too).</p>

<p>This should allow the page rendering to start sooner.</p>

<h2>Reduce the size of downloads</h2>

<h3>The problem</h3>

<p>WebPagetest is accounting for 1,425KB of data transferred. That is quite a lot.</p>

<p>The worst offender in GitHub's case seems to be the Gravatar 3rd party service. Gravatar is a popular service that allows to show a personal avatar for users of the interweb based on their email address. In the case of that GitHub page, Gravatar is loading 34 images for a total of 500KB. That is more than a third of the payload.</p>

<p>The second worst offender is the host called <code>camo.githubapp.com</code>. It seems to be serving 2 images in our example. At first, I was a bit puzzled about that host as I could not quite figure out why GitHub was serving directly 2 images worth 500KB (that is another third of our total payload) instead of using their CDN. After a bit of research I found the <a href="https://github.com/atmos/camo">Camo project</a>. GitHub is enforcing SSL for every page. When GitHub users write comments and insert funny cat pictures to illustrate their point, the said cat pictures might be served from a non SSL host. This will cause a nagging mixed content warning from the browser. Camo is basically an SSL image proxy that solves the issue. See more on <a href="https://github.com/blog/743-sidejack-prevention-phase-3-ssl-proxied-assets">this blog post</a>. Note that one of the 2 images is taking 7 seconds to load.</p>

<h3>Solutions</h3>

<p>We have about 1,000KB of images. A common practice is to compress and optimize images. There is a lot of tools out there for that purpose. WebPagetest performance review tab estimates that some of the images can be compressed and save about 40KB. Note that it does not include one of the largest images, which is a animated gif proxied through Camo. I sent the gif to Smush.it and it came back 50KB lighter. Bottom line: potential savings would be around 10%. Compressing images might not be easily achievable. I don't think it would be a good idea to compress them on the fly (it would take some extra CPU resources to do that through Camo for instance). A better approach might be to have the image compressed at the source (in the case of Gravatar, when a user uploads an avatar). That would probably require a significant effort and I am not sure it'll be worth the gain.</p>

<p>An alternative could be to implement asynchronous image loading. When you first load the GitHub page, none of that content is visible (all the images are below the fold). Knowing that, the HTML page could be generated with a placeholder for the image which would be loaded later on via javascript. The javascript could be listening for scroll events and monitor the visibility of the images in order to decide when to load them. Pamela Fox <a href="http://blog.pamelafox.org/2012/02/delayed-image-loading-on-long-pages.html">wrote about that</a> not long ago. You can also see the technique in action on Meetup's website (for instance visit <a href="http://www.meetup.com/SF-Web-Performance-Group/events/45587992/">this meetup page</a> and look at the sidebar with the list of attendees while you scroll). Note that for users browsing with javascript disabled, they would miss the images. I am not sure that would be a deal breaker as I am assuming most of GitHub users have javascript turned on.</p>

<h2>Reducing the number of HTTP requests</h2>

<h3>The problem</h3>

<p>WebPagetest shows 71 HTTP requests. Trying to reduce those numbers is usually a good idea. There is always some overhead with HTTP request, so the less you do, the better it is.</p>

<p>I mentioned earlier the presence of 2 <code>&lt;script&gt;</code> tags in the head. I am wondering if there is a specific reason for them to not be combined together. The same goes for the CSS stylesheets (<code>github-xxxx.css</code> and <code>github2-xxxx.css</code>).</p>

<p>GitHub uses some sprites which is good and avoids some HTTP requests. I am wondering if GitHub would see any gain by combining sprites together (aka über-sprite ). I am looking at the various icons in the png files (in WebPagetest, under the waterfall, click the link "View all Images"). It looks <code>like mini_button_icons.png</code>, <code>repostat.png</code>, <code>public.png</code>, <code>file_modes.png</code>, <code>jump.png</code>, <code>diffstat.png</code>... could all be combined into one.</p>

<p>Some pages include several individual icons which could be sprited. For instance a <a href="https://github.com/jphpsf">github profile/dashboard page</a> has all the timeline icons in individual files (<code>pull_request.png</code>, <code>push.png</code>, <code>fork.png</code>, <code>issues_closed.png</code>, <code>issues_comment.png</code>, <code>watch_started.png</code>, etc).</p>

<h3>Solutions</h3>

<p>Well, I guess I spoiled that one. You've read it above. Combine all the things!s</p>

<h2>The double sometimes quadruple logo</h2>

<p><img src="/images/blog/2012-04-19-quadruple-logo-ie.png" title="IE performance waterfall" ></p>

<h3>The problem</h3>

<p>In the waterfall for Firefox, you can see 2 logos being loaded (the regular black version and the alternative hover version in blue: <code>logov7@4x.png</code> and <code>logov7@4x-hover.png</code>).</p>

<p>In the waterfall for IE, you'll notice something interesting: GitHub is loading 4 logos! It is loading a smaller version (both regular and hover) as well as a higher resolution one (I am assuming given the 4x in the filename that is intended for retina displays). It seems to be a bug in the code. The smaller logos are enclosed in a conditional HTML comment targeted at IE. The conditional has an if branch but not a else branch. So when the browser is not IE, the if branch is ignored and the high resolution logos are used. But when the browser is IE, the if branch is executed loading the smaller logos. Then the high resolution logos are loaded as well. I am actually wondering why does IE need the smaller logos? Are the higher resolution logos not suitable for IE?</p>

<h3>Solutions</h3>

<p>The change between regular and hover is done with a CSS <code>:hover</code> rule that tweaks the logos opacity to 0 or a 100 to hide or show the desired version. The two version of the logos could probably be sprited together and used as CSS background image instead of inline <code>&lt;img&gt;</code> tags. Another approach: always load the regular black logo and lazy load (or preload) the hover logo via javascript. The hover effect could be achieved via javascript as well.</p>

<p>For the issue specific with the IE conditional comment, maybe look at removing the conditional comment all together.</p>

<h2>Caching issue with IE over SSL?</h2>

<p><img src="/images/blog/2012-04-19-cache-repeat-views.png" title="Cache repeat views" ></p>

<h3>The problem</h3>

<p>With Firefox, WebPagetest summary shows 82 requests and 1,420KB for the first view. The repeat view seems to be using caching and performs only 12 requests for a total of 65KB. Great!</p>

<p>With IE however, WebPagetest shows that a repeat view executes 45 requests for a total of 1,329KB (first view was 71 for 1,425KB). Looking at the various requests details (click on a filename in the waterfall), I can see that a far future expire header is set as well as the Cache-Control header for max-age. According to <a href="https://blogs.msdn.com/b/ieinternals/archive/2010/04/21/internet-explorer-may-bypass-cache-for-cross-domain-https-content.aspx">this page on MSDN</a>, this might be a known issue with IE (or more accurately with WinINET)</p>

<h2>Epic pull requests can be big</h2>

<p><img src="/images/blog/2012-04-19-epic-pull-request.png" title="Chrome dev tools" ></p>

<h3>The problem</h3>

<p>Some pull requests on GitHub can affect a lot of files and generate a really long diff. Take <a href="https://github.com/emberjs/ember.js/pull/248">this one</a> for instance. Look at the diff. It generates an HTML document of 18.48MB (1.05MB gzipped). It takes 10 seconds in Chrome before getting the first byte of that page.</p>

<h3>Solution</h3>

<p>This is a tough one. My first thought would be to look at asynchronous requests and reusing the viewport visibility trick mentioned above. Generate the diff skeleton without the diff content for each file. Then, use <a href="https://github.com/defunkt/jquery-pjax">pjax</a> to load the diff of each file. pjax could be triggered in 3 cases: First, after the initial page load, the diff of each file could be loaded one by one. Second, if a user clicks a specific file anchor at the top, then immediately load that diff via pjax. Third, as the user scrolls up or down the page, maybe some javascript code could detect which diff is visible and load it via pjax?</p>

<h2>Closing words: A note about performance metrics</h2>

<p>You know the saying "Premature optimization is the root of all evil". Related: don't optimize without measuring first.</p>

<p>Measure. Optimize. Monitor. Rinse &amp; Repeat.</p>

<p>The above analysis is looking at a very specific page but it was chosen fairly randomly from a tweet.</p>

<p>A better and more proper approach would be to setup first some kind of real user monitoring (such as <a href="https://github.com/yahoo/boomerang">Boomerang</a>, <a href="http://newrelic.com/rum">New Relic</a> or the <a href="http://www.torbit.com/insight/">new Torbit Insight</a>) and find which pages are the worst offenders. Then start optimizing. After that, monitor the performance metrics and see if the optimization works as expected and if metrics are improving.</p>

<p>Monitoring is one thing, but using web analytics in addition to performance metrics is also important to help drive optimizations decision. For instance, let's imagine that GitHub's visitors using IE represents less than 1% of all GitHub's visitors. In this case, fixing the issues specific to IE (such as double logo or SSL caching) might not be the most important optimization. Now, let's imagine that GitHub's visitors are in 99% of the case repeat users. At which point, they might be visiting GitHub with a primed cache (which would include assets such as avatars and icon images).</p>

<p>In the end, is GitHub slow? I actually don't think so. When I use GitHub, I don't have a perception of slowness or lag. Perceived performance is an important concept to consider (by opposite to the hard numbers discussed above, which tend to say "GitHub is slow"). Yet, I am wondering what would be the performance business case for GitHub? Even if GitHub does not feel slow, faster is always better. In the case of e-commerce websites or search engines, there is a direct correlation between performance and revenue (Amazon, Bing, Google, Walmart, they all shared numbers over the past few years). In the case of GitHub, what is the performance business pitch? Would a faster GitHub translate to more users? Would that then drive more revenue?</p>

<p><em>Thanks to <a href="https://twitter.com/#!/ryanbigg">Ryan Bigg</a> for reviewing this post and providing great feedback.</em></p>
]]></content>
  </entry>
  
</feed>
