Client Side Performance @ Xero


Published on

This presentation shares some of the experiences Xero went through to greatly improve our user experience by focusing on front-end performance.

Published in: Technology, Design
  • Be the first to comment

Client Side Performance @ Xero

  1. 1. Client-Side Performance Sucks Craig Walker, Chief Technology Officer And what you can do to make it suck less.
  2. 2. Your typical internal network: <ul><li>Easier to control </li></ul><ul><li>Easier to predict </li></ul><ul><li>Knowledge of almost everything from LAN speed to operating system </li></ul>
  3. 3. There's a reason why the words “world” and “wide” are in the acronym Control and knowledge are limited to your own environment. Even how the packets fly around the internet is out of your control.
  4. 4. The HTTP Request Server Browser Receive Last Byte Send Last Byte Send Data Establish Connection Initial Connection Open Socket Initial HTTP Request First Byte Receive First Byte Send First Byte Content Download ISP Get IP DNS Lookup
  5. 5. 5% Server side performance often not the problem with response time 95% Most of the response time is taken up here
  6. 6. 25% 75%
  7. 7. Empty Cache Primed Cache
  8. 8. Focus on the front-end <ul><li>75-95% of the end-user response time for Xero customers is spent on the front end </li></ul><ul><li>Much easier to optimise than server side performance </li></ul><ul><li>Greater potential for improvement – especially from an end-users point-of-view </li></ul><ul><li>Proven to work </li></ul>
  9. 9. Performance === Usability
  10. 10. The giants who’s shoulders I’m standing on <ul><li>Yahoo! Exceptional Performance team </li></ul><ul><ul><li> </li></ul></ul><ul><li>Steve Souders </li></ul><ul><ul><li>Former Chief of Performance at Yahoo! </li></ul></ul><ul><ul><li>Now at Google </li></ul></ul><ul><ul><li>Creator of YSlow and the 14 Rules </li></ul></ul><ul><ul><li>Author of High Performance Web Sites </li></ul></ul><ul><li>Stoyan Stefanov, Patrick Meenan, Julien Lecomte, Stuart Colville, Ed Eliot and many more … </li></ul>
  11. 11. Zip It! <ul><li>Significantly reduces download size – 60-80% saving on text based content </li></ul><ul><li>90% of browsers support compression </li></ul><ul><li>Benefits ALL users </li></ul><ul><li>Zip everything you can </li></ul><ul><ul><li>html (aspx), js, css, xml, txt, json (ashx, axd) </li></ul></ul><ul><li>Benefits you too: </li></ul><ul><ul><li>Reduces traffic costs </li></ul></ul><ul><ul><li>Doesn’t require code changes </li></ul></ul>
  12. 12. Fly’s down Zipped
  13. 13. Reduce HTTP Requests <ul><li>Less components means a faster page </li></ul><ul><li>Every request is an overhead </li></ul><ul><li>Combine scripts </li></ul><ul><li>Combine CSS </li></ul><ul><li>Combine images into CSS Sprites </li></ul><ul><li>Don’t rely on cache: 304’s are still requests </li></ul>
  14. 14. CSS Sprites <ul><li>Combine all small images into one large image </li></ul><ul><li>Use CSS to control the displaying of each image </li></ul>
  15. 15. The designers want what? 11 Images 11 HTTP Requests 3.3 KB total size
  16. 16. Obey your thirst ® 1 Image 1 HTTP Request 1.6 KB total size
  17. 17. And the CSS? <div class=&quot;buttons&quot;> <span class=&quot;large green button&quot;> <button type=&quot;button&quot;> <span class=&quot;checkbox icon&quot;> Approve </span> </button> </span> <span class=&quot;large blue button&quot;> <button type=&quot;button&quot;> <span> Save </span> </button> </span> <span class=&quot;large red button&quot;> <button type=&quot;button&quot;> <span class=&quot;delete icon&quot;> Delete </span> </button> </span> <span class=&quot;medium gray button&quot;> <button type=&quot;button&quot;> <span class=&quot;delete icon&quot;> Cancel </span> </button> </span> </div> <ul><li>.buttons span.button { </li></ul><ul><ul><li>background:transparent url(buttons.png) no-repeat 0 0; </li></ul></ul><ul><li>} </li></ul><ul><li>.buttons span.button button, .buttons span.button a { </li></ul><ul><ul><li>background:transparent url(buttons.png) no-repeat 100% -120px; </li></ul></ul><ul><li>} </li></ul><ul><li>.buttons { </li></ul><ul><ul><li>background-position: 0 -30px; </li></ul></ul><ul><li>} </li></ul><ul><li>.buttons button, .buttons a { </li></ul><ul><ul><li>background-position: 100% -150px; </li></ul></ul><ul><li>} </li></ul><ul><li>.buttons { </li></ul><ul><ul><li>background-position: 0 -60px; </li></ul></ul><ul><li>} </li></ul><ul><li>.buttons button, .buttons a { </li></ul><ul><ul><li>background-position: 100% -180px; </li></ul></ul><ul><li>} </li></ul><ul><li>.buttons { </li></ul><ul><ul><li>background-position: 0 -90px; </li></ul></ul><ul><li>} </li></ul><ul><li>.buttons button, .buttons a { </li></ul><ul><ul><li>background-position: 100% -210px; </li></ul></ul><ul><li>} </li></ul>The HTML The CSS
  18. 18. Maximise Parallel Downloads <ul><li>Most browsers are limited to 6 connections total and 2 connections per hostname </li></ul><ul><li>Increase the number of hostnames to increase the number of parallel downloads (e.g.,,, </li></ul><ul><li>Don’t overdo it! (DNS lookups are expensive so limit 2-4 domains) </li></ul>Browser Parallel Downloads Firefox 2 2 Firefox 3 6 Internet Explorer 7 2 Internet Explorer 8 6 Safari 3.1 4 Safari 4.0 4
  19. 19. Maximise Parallel Downloads <ul><li>Stepped download </li></ul><ul><li>(with 1 hostname) </li></ul>Increased parallelism (using 2 hostnames)
  20. 20. Use a CDN <ul><li>Content Delivery Network </li></ul><ul><li>Distributes content closer to the last mile </li></ul><ul><li>Distribute your static content before distributing your dynamic content </li></ul><ul><li>Akamai most popular but very expensive </li></ul><ul><li>Xero utilises a rudimentary CDN using IP lookup to determine location </li></ul>
  21. 21. How it works: Images JS CSS <xsl:value-of select=&quot;Page:RegisterCSS('/common/style/xero.css','screen')&quot;/> <xsl:value-of select=&quot;Page:RegisterJavascript('/common/scripts/xero.js'&quot;/> <link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;; /> <script type=&quot;text/javascript&quot; src=&quot;;></script> GET Request Response with HTML document Get location from IP
  22. 22. Maximise the cache <ul><li>Understand the ratio of cached vs uncached </li></ul><ul><li>Add an Expires header </li></ul><ul><ul><li>Not just for images – should be used on all static content </li></ul></ul><ul><ul><li>Set a “Never expire” or far future expires policy if you can </li></ul></ul><ul><ul><li>Reduces HTTP requests – once component is served, the browser never asks for it again </li></ul></ul><ul><ul><li>Date stamping in file names makes it easier </li></ul></ul><ul><li>Remove ETags </li></ul><ul><ul><li>ETags are another caching mechanism – sent with every request </li></ul></ul><ul><ul><li>Uniquely created per web server – not good in web farms </li></ul></ul><ul><ul><li>Just turn them off and use Expires headers instead </li></ul></ul>
  23. 23. CSS external and on top <ul><li>Move all inline CSS to external style sheets for both reuse and caching </li></ul><ul><li>Put all style sheet references at the top </li></ul><ul><li>Firefox and IE will block rendering until all the CSS is downloaded </li></ul><ul><li>Use <link> and NOT @import </li></ul><ul><ul><li>In IE @import is the same as putting <link> at the bottom </li></ul></ul>
  24. 24. JavaScript external and on the bottom <ul><li>Move scripts to external files for both reuse and caching </li></ul><ul><li>Promotes better script design </li></ul><ul><li>Push scripts as low as possible </li></ul><ul><ul><li>Often difficult with document.write or with inline calls requiring loaded JavaScript </li></ul></ul><ul><ul><li>Be pragmatic – think about splitting JavaScript into “must be loaded” and “can be loaded on demand” </li></ul></ul><ul><li>Scripts will block both downloading and rendering until parsed </li></ul><ul><li>Remove duplicate scripts (IE has a habit of downloading them again) </li></ul>
  25. 25. Notice the parallel download here … … until we hit the JavaScript files where they come down sequentially, blocking any other downloads
  26. 26. Minify all static content <ul><li>CSS, JavaScript, XML, JSON, HTML can all be minified </li></ul><ul><li>Not a replacement for gzipping but is a perfect accompaniment to it </li></ul><ul><li>Lots of tools: </li></ul><ul><ul><li>JSMin </li></ul></ul><ul><ul><li>CSSTidy </li></ul></ul><ul><ul><li>YUI Compressor </li></ul></ul><ul><li>JavaScript obfuscation can also be useful – just test that your app still works afterwards </li></ul>
  27. 27. Optimise images <ul><li>Use PNGs instead of GIFs </li></ul><ul><li>Avoid alpha filters – can block rendering and freeze the browser </li></ul><ul><li>PNG8 is best and supported by IE6 (yes – even with transparency) </li></ul><ul><li>Optimise further with PNGOUT or PNGCRUSH </li></ul><ul><li>Make sure you have a favicon.ico </li></ul><ul><ul><li>Every browser will request it </li></ul></ul><ul><ul><li>Best not to respond with a 404 </li></ul></ul><ul><ul><li>Make it small and cacheable </li></ul></ul>
  28. 28. Preloading … <ul><li>Preload components you’ll need in the future </li></ul><ul><li>Unconditional preload </li></ul><ul><ul><li>Xero login page preloads all core components so that the dashboard experience is better </li></ul></ul><ul><li>Conditional preload </li></ul><ul><ul><li>Often based on where you think a user might go to next </li></ul></ul>
  29. 29. Reduce cookie weight <ul><li>Cookie’s are sent back with every request </li></ul><ul><li>Keep cookie size small and only store what’s required – use server-side storage for everything else </li></ul><ul><li>Consider cookie free domains for static content </li></ul>
  30. 30. Keep it clean <ul><li>Choose a good Ajax library – don’t go writing this stuff yourself </li></ul><ul><li>Always asynchronous </li></ul><ul><li>Use JSON over XML </li></ul><ul><ul><li>Accessing JSON faster and cheaper </li></ul></ul><ul><ul><li>Less overhead than XML </li></ul></ul><ul><li>Use GET requests over POSTs wherever possible </li></ul><ul><ul><li>POST is a 2-step process: send headers, send body </li></ul></ul><ul><ul><li>POST without a body is essentially a GET anyway </li></ul></ul><ul><li>And make sure the response is zipped! </li></ul>
  31. 31. Things to take away <ul><li>Focus on the front-end </li></ul><ul><li>Be an advocate for your users </li></ul><ul><li>Don’t let designers get in the way of performance </li></ul><ul><li>But they will so optimise, optimise, optimise! </li></ul>
  32. 32. YSlow <ul><li>Firebug extension </li></ul><ul><li>Grades performance – not about response times but about how well a site has adopted the techniques suggested </li></ul><ul><li>Response time inversely proportional to YSlow score – get as close to an A as possible to get the maximum performance gain </li></ul>
  33. 33. Fiddler <ul><li>Microsoft built HTTP debugging proxy </li></ul><ul><li>Inspect HTTP traffic, tamper with incoming and outgoing data and debug performance issues </li></ul><ul><li>Works with all browsers </li></ul>
  34. 34. AOL PageTest <ul><li>Internal AOL utility gone public </li></ul><ul><li>Browser plug-in for Internet Explorer </li></ul><ul><li>Visually displays underlying requests and provides suggestions on how to improve your response times </li></ul><ul><li>Also available as an external web-based tester at </li></ul>
  35. 35. Any questions?
  36. 36. 0800 GET XERO