Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Life on the Grid

Matt
March 16, 2014

Life on the Grid

Recording performance, code practices and addressing the unique concerns of image heavy user interfaces like the Netflix clients.

Matt

March 16, 2014
Tweet

More Decks by Matt

Other Decks in Technology

Transcript

  1. Life on the Grid Addressing scale & performance of a

    large JavaScript application ! @innerhtml / mseeley@netflix.com March 15 & 16, 2014 JQUERY.TO();
  2. Android tablets, Apple iPad 2+, Blu-ray players, Televisions, Virgin Media

    TiVo boxes Connected devices Media streamers Nintendo Wii, Nintendo Wii U, PlayStation 3, PlayStation 4, PlayStation Vita, Xbox 360 Game Consoles Apple TV, Google Chromecast, Roku 3, etc…
  3. • avoiding surprise • adapting for existing solutions • understanding

    the big picture Surviving a life on the grid is:
  4. console.timeStamp('Hello world'); ! // ... "children": [{ "startTime": 13939 "type":

    "TimeStamp "data": { "message": "He }, "frameId": "11284. "usedHeapSize": 17 "counters": { "documents": 1 "nodes": 4, "jsEventListen } }] // ...
  5. amp('Hello world'); ! // ... "children": [{ "startTime": 1393965312322.3394, "type":

    "TimeStamp", "data": { "message": "Hello world" }, "frameId": "11284.1", "usedHeapSize": 1758128, "counters": { "documents": 1, "nodes": 4, "jsEventListeners": 0 } }] // ... { "type": "TimeSta "startTime": 139 "endTime": 13939 "data": { "message": " } }
  6. 93965312322.3394, amp", "Hello world" 84.1", 1758128, : 1, teners": 0

    { "type": "TimeStamp", "startTime": 1393965312322.3394, "endTime": 1393965312322.3394, "data": { "message": "Hello world" } }
  7. var timeline = new Timeline(), startup = timeline.mark('Startup'); ! //

    Mark startup began. startup.begin(); ! // ... heigh-ho, heigh-ho. Mark more Tasks. ! // Mark startup ended. Record results. startup.end(); $.post(‘https://...', timeline.data). fail(function () { // Uh-oh! }); Source: https://gist.github.com/mseeley/9570215
  8. 0 1.00s 2.00s 3.00s RECORDS Startup Task A Task B

    Task C Task D Detailed session-level data
  9. 0 1.00s 2.00s 3.00s Task A Task B Task C

    Task D Aggregate task comparisons
  10. Async? Sync? Both! var cache = {}, getValue = function

    (url, callback) { if (url in cache) { callback(cache[url]); } else { $.get(url, function(data) { cache[url] = data; callback(data); }); } };
  11. Async once, async always! var cache = {}, getValue =

    function (url, callback) { var complete = function (data) { cache[url] = data; callback(data); }; ! if (url in cache) { setTimeout(complete, 0, cache[url]); } else { $.get(url, complete); } };
  12. myView.show({ duration: 50, ease: 'linear', onDone: function () { //

    animation complete! } }); Build forward compatible interfaces
  13. • is more than log statements • changes default application

    behavior • may adversely affect performance • will adversely affect file-size Debug code…
  14. var log = (location.hostname === 'production.com') ? function () {}

    : function () { console.log.apply(console.log, arguments); } };
  15. (function(global){ var prod = location.hostname === 'production.com', api = ["log","debug","info","warn","error","assert","dir","dirxml",

    "trace","group","groupCollapsed","groupEnd","time","timeEnd", "profile","profileEnd","count","exception","table"], log, i, len ; ! if (typeof global.console == "undefined" || !global.console) { try { global.console = {}; } catch (err) { } } ! log = (!prod && typeof global.console.log != "undefined") ? global.console.log : function(){} ; ! for (i=0, len=api.length; i<len; i++) {
  16. (function(global){ var prod = location.hostname === 'production.com', api = ["log","debug","info","warn","error","assert","dir","dirxml",

    "trace","group","groupCollapsed","groupEnd","time","timeEnd", "profile","profileEnd","count","exception","table"], log, i, len ; ! if (typeof global.console == "undefined" || !global.console) { try { global.console = {}; } catch (err) { } } ! log = (!prod && typeof global.console.log != "undefined") ? global.console.log : function(){} ; ! for (i=0, len=api.length; i<len; i++) { sed 's/console.\(log\|debug\|info\|warn\|error\| assert\|dir\|dirxml\|trace\|group\|groupEnd\|time \|timeEnd\|profile\|profileEnd\|count\)(.*);\?//g' var log = (location.hostname === 'production.com') ? function () {} : function () { console.log.apply(console.log, arguments); } }; if (location.hostname === 'production.com') { // change behavior }
  17. var maxLists = model.maxLists; ! // #ifdef DEBUG if (URL_PARAMS.maxLists)

    { maxLists = URL_PARAMS.maxLists; console.log('Override maxLists’); } // #endif
  18. var groceries = { squash: 2, apples: 8 // #ifdef

    RUGBYSEVENS ,hardCider: 12 ,munchies: 2 // #endif };
  19. 185KB (that’s more than jQuery 1.110 and jQuery 2.1.0 combined)

    Removing debug code saved: See: https://www.npmjs.org/package/preprocessor
  20. Tiles intersecting the viewport Pre-painted to cover scrolling TiledBackingStore See:

    https://trac.webkit.org/browser/trunk/Source/WebCore/ platform/graphics/TiledBackingStore.cpp
  21. Populated elements intersecting the viewport Elements reduced to placeholders Postponed

    activity See: https://www.w3.org/Bugs/Public/show_bug.cgi?id=20246 https://www.w3.org/Bugs/Public/show_bug.cgi?id=17842
  22. What’s the best way to preload a bunch of movie

    posters without introducing jank?
  23. var xhr = new XMLHttpRequest(), remaining = imgs.length, onload =

    function () { --remaining; if (remaining === 0) { // done! } else if (remaining > 0) { work(); } }, work = function () { xhr.open('GET', imgs.pop(), true); xhr.send(); }; ! xhr.onload = onload; xhr.responseType = 'blob'; ! work();
  24. <script id="imgloader" type="javascript/worker"> // JavaScript from XHR example and an

    onmessage handler </script> <script> var url = URL.createObjectURL( new Blob( [document.getElementById('imgloader').textContent], { type: 'text/javascript' } ) ), worker = new Worker(url); ! worker.onmessage = function () { URL.revokeObjectURL(url); // done! }; ! worker.postMessage(imgs); </script>
  25. JavaScript IS a profession @innerhtml / mseeley@netflix.com Thank You! Further

    reading: http://techblog.netflix.com/2013/12/pioneering-application-design-on-tvs-tv.html http://techblog.netflix.com/2012/01/webkit-in-your-living-room.html http://jobs.netflix.com/