Building fast webapps, fast - Velocity 2010


Published on

Slides from the 2010 Velocity presentation on performance of the Meebo Bar

Published in: Technology
1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • MARCUS Martin & Marcus We're here from Meebo commonly known as today: Meebo is better known for the Meebo Bar
  • MARCUS What is the Meebo Bar? Well, if you have a site, then you can add the Meebo Bar to your site and gain a number of features, such as social IM, sharing, ad revenue and more. The Meebo Bar launched almost 2 years ago. Since then we've gone through 9 major iterations, and will soon be releasing Version 10. It will be the most technically advanced and best performing version of the bar as of yet. Since it's launch, the Meebo Bar has grown to more than 6000 websites and reaches more than 130 Million people every month The Meebo Bar lives inside of the hosting site. Because of its vast reach, it is crucial that the Meebo Bar does not slow down the site that it is on. If it does, than we slow down a significant portion of the web.
  • MARCUS The Meebo Bar is a 3PWA. With 3PWA we mean javascript, css, images and HTML loaded onto a stie from a third party provider. 3PWAs commonly interact with the page, and often load on every page The question is then how do we make it run fast?  How do we make it respectful of its hosting environment?
  • MARCUS More specifically, the challenge is to  Load lots of features Load those features fast Without Blocking rendering or onload and Without affecting the user experience in a negative way. How can we do that? Martin knows alot about how we can do that
  • MARTIN You're already familiar with some tools - CDN - GZIP - PNG Crush We'll cover some tools & techniques you're probably not familiar with Traditional 3rd Party Web App loading blocks - this is bad Defer code execution to not affect load time Optimize graphics and reduce image network requests Finally, we'll talk about deferring
  • MARTIN Meebo Embed Code
  • MARTIN Concerns Blocking page rendering Blocking network traffic Execute quickly and return control of the browser Only one piece of JS can run at a time! Should not depend on your servers
  • MARTIN Concerns Blocking page rendering Blocking network traffic
  • why might you not want to use an iframe? there are several problems that you might notice
  • Out sample code for Loading asynchronous and nonblocking javascript same-domain iframe      with access to parent page      without blocking parent onload
  • MARTIN iframe creation times are insignificant iframes guarantee sandboxing of your javascript
  • MARCUS Lots of things happen in browser during load Parse, DOM, Layout, Render Then, realtively little happens As 3PWA developers we should take advantage of this! Let's look at an example
  • MARCUS Any page with the Meebo Bar can have its videos, images and links made sharable by drag and drop. This means that when the page loads...
  • MARCUS This means that when the page loads, the Meebo Bar scans the page for images, videos and links, and make them sharable When the user hovers...
  • MARCUS When the user hovers over a sharable image, we display a drop shadow to indicate that this image is sharable by drag and drop On mouse down...
  • MARCUS On mouse down, we display the Meebo Share UI, which allows the user to share the image to a number of social networks and any buddy in the buddy list. For each sharable item, Meebo infers the title, thumbnail and URL from the page. We allow for the site to specify these attributes on any parent node of a sharable element. Let's look at a naive implementation of this functionality
  • MARCUS In this implementation, we loop over all elements that should be made sharable, look up the metadata for that element, and attach a mousedown event handler to that element lookupMetadata in turn climbs the DOM of the sharable element and inspects all parent nodes for metadata. Now, we want elements on the page to be made sharable right away, so we run this during page load.  A complex page can easily have tens of images and hundreds of links. Processing them all during loading of the page becomes noticable on all web browsers. Formally, the runtime of this approach is O(N * M), where N is the number of sharable elements and M is the number of ancestors of the sharable elements. Using the concept of deferred execution, we can do better.
  • MARCUS The key to the concept of deferring is do as little as possible up front, and delay as much of the execution until as late as possible. In this example, we attach a single mousedown event handler to the entire document. Now, whenever the user does a mousedown, we check to see if the element the user moused down on is a sharable element. If it is, then go ahead and infer the metadata, and attach the remaining event handlers required for the drag and drop share UI This way we can go ahead and set up sharing right away during load without interfearing with the loading of the page. Formally, the runtime of this algorithm is constant on load, and linear when the user mouses down on a sharable elements. Both are unnoticable in all browsers.
  • MARCUS That's a lot of code! And CSS and images! Break them down by features and load the code when the user needs it
  • MARTIN SVG & MHTML Meebo Bar   - Chrome   - Gradients   - Drop shadow   - No Images!
  • MARTIN (overview slide)
  • MARTIN We need better tools for measuring webapp performance!
  • Building fast webapps, fast - Velocity 2010

    1. 2. Building Fast  3rd-Party  Webapps O'Reilly Velocity Web Performance and Operations Conference 24 June 2010 [email_address] [email_address] Lessons learned from the Meebo Bar Martin Hunt and Marcus Westin
    2. 3. The Meebo Bar A customizable site bar with real-time social interaction
    3. 4. Meebo Bar, a 3rd Party Webapp <ul><li>How do we make it run fast?   </li></ul>Loads on every page Interacts with the page JavaScript, CSS, Images & HTML How do we make it respectful? 
    4. 5. 3rd Party Webapps The Challenge <ul><li>Do </li></ul><ul><ul><li>Load lots of features </li></ul></ul><ul><ul><li>Load features fast </li></ul></ul><ul><li>Without </li></ul><ul><ul><li>Blocking rendering or onload </li></ul></ul><ul><ul><li>Affecting User Experience </li></ul></ul>How?
    5. 6. 3rd Party Webapps: How? <ul><ul><li>How to initialize a webapp Asynchronous & non-blocking </li></ul></ul><ul><ul><ul><li>  </li></ul></ul></ul><ul><ul><li>Defer Execution Minimize impact when loading </li></ul></ul><ul><ul><li>CSS and Images Crush, Combine, Avoid  </li></ul></ul><ul><ul><li>Perceived Performance Testing and psychology </li></ul></ul>Tools Techniques
    6. 7. Meebo Bar embed code <ul><ul><li>executes in ~10ms </li></ul></ul><ul><ul><ul><li>no blocking network requests </li></ul></ul></ul><ul><ul><ul><li>no dependency on our server </li></ul></ul></ul><ul><ul><li>less than 1200 characters </li></ul></ul><ul><ul><li>gzips to about 700 bytes </li></ul></ul><ul><ul><li>embedded directly in page HTML or JS </li></ul></ul><ul><ul><li>executes even if our servers are not reachable </li></ul></ul>
    7. 8. Initializing 3rd Party Webapps Script Tag append a script tag using JavaScript to the head of the document Commonly accepted, but... Inline JS <script src=&quot;&quot;> easy for publishers to add blocks the page in all browsers XMLHttpRequests Asynchronous, non-blocking same-domain in most browsers Iframe <iframe src=&quot;&quot;> load an HTML file in an iframe Requires HTML file on the hosting site
    8. 9. Accepted script loading code <ul><li>var head = document . getElementsByTagName ( 'head' )[ 0 ], </li></ul><ul><li>el = document . createElement ( 'script' ); </li></ul><ul><li>el. src = &quot;http://www.myDom.ain/myScript.js&quot; ; head. appendChild (el); </li></ul><ul><li>good:  cross domain (we're 3rd party content!) </li></ul><ul><li>good:  doesn't block network traffic </li></ul>
    9. 10. Don't block the page! <ul><li>Script Tag Append </li></ul><ul><li>can block scripts in Firefox! </li></ul><ul><li>blocks other scripts in Firefox </li></ul><ul><ul><li>scripts execute in order </li></ul></ul><ul><ul><li>all scripts on the page block until the appended script downloads and executes </li></ul></ul><ul><ul><li>(defer attribute supported in FF3.5+) </li></ul></ul><ul><li>blocks onload event in all browsers </li></ul>are there alternative nonblocking methods?
    10. 11. Iframed JS <ul><ul><li>Iframes load HTML, not JS </li></ul></ul><ul><ul><li>Cross iframe communication is same-domain only (non-HTML5 browsers) </li></ul></ul><ul><ul><li>Window onload event fires after all iframes load </li></ul></ul>
    11. 12. Iframed JS - the solution      var iframe = document . createElement ( 'iframe' ),          doc = iframe.contentWindow. document;      doc. open (). write ( '<body onload=&quot;appendScriptTag()&quot;>' )            doc. close ()
    12. 13. More About Iframes <ul><li>iframe creation overhead? </li></ul><ul><li>     Creating one DOM node </li></ul><ul><ul><ul><li>Chrome < 1ms </li></ul></ul></ul><ul><ul><ul><li>Firefox, Safari ~1ms </li></ul></ul></ul><ul><ul><ul><li>IE ~5ms </li></ul></ul></ul><ul><li>Sandboxed JavaScript </li></ul><ul><ul><li>3rd party code will not break webpage code </li></ul></ul><ul><ul><li>Webpage code will not break 3rd party code! </li></ul></ul><ul><li>for (var i in x) {} </li></ul>
    13. 14. Defer Execution
    14. 15. Defer Execution <ul><li>Lots of stuff happens in a browser while loading a page </li></ul><ul><li>    </li></ul><ul><li>Then, relatively little happens... Take advantage of this! </li></ul>
    15. 16. Defer Execution Example In-page sharing <ul><li>  </li></ul>
    16. 17. Defer Execution Example In-page sharing <ul><li>  </li></ul>
    17. 18. Defer Execution Example In-page sharing <ul><li>  </li></ul>
    18. 19. Defer Execution Example In-page sharing
    19. 20. Naive implementation <ul><li>function makeSharable(elements) { </li></ul><ul><li>     for (var i=0; i < elements.length; i++) { </li></ul><ul><li>         var element = elements[i]; </li></ul><ul><li>         var metadata = lookupMetadata(element); </li></ul><ul><li>         element.on('mousedown', startDrag, metadata);          </li></ul><ul><li>     } </li></ul><ul><li>} </li></ul><ul><li>function lookupMetadata(el) { </li></ul><ul><li>     do { </li></ul><ul><li>         inspectElement(el) </li></ul><ul><li>     } while(el = el.parentNode) </li></ul><ul><li>} </li></ul>O(N) O(M) O(N*M)
    20. 21. Deferred implementation <ul><li>function initShare() { </li></ul><ul><li>     document.on('mousedown' , function(e) { </li></ul><ul><li>         var el = || e.srcElement </li></ul><ul><li>         if (!el.getAttribute('meeboSharable')) { return; } </li></ul><ul><li>         var metadata = lookupMetadata(el); </li></ul><ul><li>         document.on('mousemove' , handleDrag, metadata); </li></ul><ul><li>         document.on('mouseup',  stopDrag, metadata); </li></ul><ul><li>     }); </li></ul><ul><li>} </li></ul>O(1) Page finishes loading
    21. 22. Modularize & Lazy Load <ul><li>users don't need all features immediately </li></ul>1-1 Messaging connect to all the IM networks Broadcasting publishers send new content to users Social Networking receive updates about your friends' activities Sharing share site content to Facebook, Twitter, Buzz, and other sites Site Widgets site-specific widgets: videos, menus, navigation tools, etc.
    22. 23. Modularize & Lazy Load <ul><li>Also applies to  </li></ul><ul><li>images and CSS! </li></ul><ul><li>Careful: </li></ul><ul><li>Loading images can create a lot of HTTP requests </li></ul>
    23. 24. Loading Images Spriting and preloading is hard Still creates additional HTTP requests Difficult to automate Embed images into CSS instead DataURIs and MHTML files Details on the Meebo devblog (
    24. 25. Use Vector Graphics <ul><li>Vector graphics are supported in all major browsers </li></ul><ul><ul><li>Firefox 3+ </li></ul></ul><ul><ul><li>Opera 9.5+ </li></ul></ul><ul><ul><li>IE 6+ </li></ul></ul><ul><ul><li>Safari 3+ </li></ul></ul><ul><ul><li>Chrome </li></ul></ul>
    25. 26. <ul><li>  </li></ul>Without images With images
    26. 27. Tools -  use them! <ul><li>Preprocess if possible </li></ul><ul><ul><li>if multiple clients are doing the exact same task, run it on the server </li></ul></ul><ul><ul><li>generate content offline </li></ul></ul><ul><li>Compilers </li></ul><ul><ul><li>Closure Compiler </li></ul></ul><ul><li>Profilers </li></ul><ul><ul><li>DynaTrace (IE) </li></ul></ul><ul><ul><li>Speed tracer (Chrome) </li></ul></ul><ul><ul><li>Firebug (FF) </li></ul></ul><ul><ul><li>Safari 5/WebKit </li></ul></ul>
    27. 28. Perceived Performance <ul><li>Quick loading content on a slow page appears to be the cause of the slow page </li></ul><ul><li>Delaying interface drawing can look slow or broken </li></ul><ul><li>Do not forget: </li></ul><ul><li>Even asynchronous loading slows down a page.   </li></ul><ul><li>Keep payloads minimal and always monitor performance! </li></ul>
    28. 29. Questions? <ul><li>[email_address] </li></ul><ul><li>[email_address] </li></ul><ul><li>Highlights </li></ul><ul><ul><li>Always compress and minify content </li></ul></ul><ul><ul><li>Use an IFrame to load the main script payload </li></ul></ul><ul><ul><li>Defer execution until needed </li></ul></ul><ul><ul><li>Defer content download until needed </li></ul></ul><ul><ul><li>Remove HTTP requests by combining content </li></ul></ul><ul><ul><ul><li>Embed images into CSS </li></ul></ul></ul><ul><ul><ul><li>Use vector graphics </li></ul></ul></ul>
    29. 30.   <ul><li>  </li></ul>