$30 off During Our Annual Pro Sale. View Details »

How DRY impacts JavaScript performance // Faster JavaScript execution for the lazy developer

How DRY impacts JavaScript performance // Faster JavaScript execution for the lazy developer

The slides for my Velocity Europe 2011 talk.

Mathias Bynens

November 17, 2011
Tweet

More Decks by Mathias Bynens

Other Decks in Technology

Transcript

  1. How DRY impacts JavaScript performance //
    Faster JavaScript execution for the lazy developer
    Mathias Bynens – Velocity Europe, November 2011

    View Slide

  2. @mathias

    View Slide

  3. JavaScript & performance
    Rule #1: nothing to do with JS

    View Slide

  4. JavaScript & performance

    View Slide

  5. JavaScript & performance
    What about
    the actual run-time performance
    on the client side?

    View Slide

  6. DRY
    flic.kr/p/2ZGCT

    View Slide

  7. WET
    flic.kr/p/5Jnj7Q

    View Slide

  8. “DRY leads to readable,
    maintainable code”

    View Slide

  9. DRY JavaScript
    improves
    performance
    …if you do it right

    View Slide

  10. So, where to avoid
    repetition?

    View Slide

  11. What’s slow in JavaScript?

    View Slide

  12. What’s slow in JavaScript?
    1. The DOM

    View Slide

  13. What’s slow in JavaScript?
    1. The DOM
    2. Function calls

    View Slide

  14. What’s slow in JavaScript?
    1. The DOM
    2. Function calls
    3. Lookups

    View Slide

  15. DOM manipulation
    // Create the element in memory
    var el = document.createElement('p');
    // Insert the element into the DOM
    document.body.appendChild(el);

    View Slide

  16. DOM manipulation






    View Slide

  17. DOM manipulation
    var div = document.createElement('div'),
    p = document.createElement('p');
    // Bad
    document.body.appendChild(div);
    div.appendChild(p);

    View Slide

  18. DOM manipulation
    var div = document.createElement('div'),
    p = document.createElement('p');
    // Better
    div.appendChild(p);
    document.body.appendChild(div);

    View Slide

  19. DOM manipulation







    View Slide

  20. DOM manipulation
    var p = document.createElement('p'),
    i = 4;
    while (i--) { // Add four elements
    document.body.appendChild(p.cloneNode(false));
    }

    View Slide

  21. DOM manipulation
    var frag = document.createDocumentFragment(),
    p = document.createElement('p'),
    i = 4;
    while (i--) { // Add four elements
    frag.appendChild(p.cloneNode(false));
    }
    document.body.appendChild(frag);

    View Slide

  22. Function calls
    // Function declaration
    function foo(bar) {
    return bar;
    }
    // Function call
    foo('something');

    View Slide

  23. Function calls
    alert('foo');
    document.getElementById('foo');
    $('#foo');

    View Slide

  24. Function calls
    $('.foo').show();
    // other stuff…
    $('.foo').hide();

    View Slide

  25. Function calls
    var $foo = $('.foo');
    $foo.show();
    // other stuff…
    $foo.hide();

    View Slide

  26. Function calls
    var $foo = $('.foo').show();
    // other stuff…
    $foo.hide();

    View Slide

  27. Property lookups
    var obj = {
    'x': 42,
    'y': {
    'foo': 'bar'
    }
    };
    obj.x; // 42
    obj.y.foo; // 'bar'

    View Slide

  28. Property lookups
    document.title
    dojo.query(…)
    YAHOO.util.Dom.get(…)

    View Slide

  29. Property lookups
    var foo = YAHOO.util.Dom.get('foo'),
    bar = YAHOO.util.Dom.get('bar'),
    baz = YAHOO.util.Dom.get('baz'),
    qux = YAHOO.util.Dom.get('qux');

    View Slide

  30. Property lookups
    var get = YAHOO.util.Dom.get,
    foo = get('foo'),
    bar = get('bar'),
    baz = get('baz'),
    qux = get('qux');

    View Slide

  31. Array item lookups
    var elems = document.getElementsByTagName('p'),
    length = elems.length;
    while (length--) {
    if (elems[length].className == 'foo') {
    // do something with elems[length]
    elems[length].innerHTML = 'LOLWAT';
    }
    }

    View Slide

  32. Array item lookups
    var elems = document.getElementsByTagName('p'),
    length = elems.length,
    elem;
    while (length--) {
    elem = elems[length];
    if (elem.className == 'foo') {
    // do something with elem
    elem.innerHTML = 'LOLWAT';
    }
    }

    View Slide

  33. Scope lookups
    var foo = 42;
    foo; // no scope lookup

    View Slide

  34. Scope lookups
    var foo = 42;
    (function() {
    foo; // one scope lookup
    }());
    // IIFE – see http://mths.be/iife

    View Slide

  35. Scope lookups
    var foo = 42;
    (function() {
    (function() {
    foo; // two scope lookups
    }());
    }());

    View Slide

  36. Scope lookups

    View Slide

  37. Scope lookups
    var foo = 42;
    (function(foo) {
    (function(foo) {
    foo; // ZOMG, no scope lookups!!1
    }(foo));
    }(foo));

    View Slide

  38. Scope lookups

    View Slide

  39. Scope lookups
    (function() {
    // every time you use `window`
    // or `document` here
    // that’s a scope lookup
    }());

    View Slide

  40. Scope lookups
    (function() {
    var doc = document,
    win = window;
    // lookup once, then cache
    }());

    View Slide

  41. Scope lookups
    (function(win, doc) {
    // use `win` and `doc` here
    // no scope lookups
    // no performance penalty!
    }(this, document));

    View Slide

  42. Recap: what’s slow in JavaScript?

    View Slide

  43. Recap: what’s slow in JavaScript?
    1. The DOM

    View Slide

  44. Recap: what’s slow in JavaScript?
    1. The DOM
    2. Function calls

    View Slide

  45. Recap: what’s slow in JavaScript?
    1. The DOM
    2. Function calls
    3. Lookups

    View Slide

  46. Especially when used inside…

    View Slide

  47. Especially when used inside…
    • Loops

    View Slide

  48. Especially when used inside…
    • Loops
    • Intervals

    View Slide

  49. Especially when used inside…
    • Loops
    • Intervals
    • Handlers for events that fire frequently

    View Slide

  50. It happens to the best!
    // Don’t do this:
    $(window).scroll(function() {
    $('.foo').something();
    });

    View Slide

  51. It happens to the best!
    // Don’t do this:
    $(window).scroll(function() {
    $('.foo').something();
    });

    View Slide

  52. It happens to the best!
    // Don’t do this:
    $(window).scroll(function() {
    $('.foo').something();
    });
    // See http://mths.be/azs

    View Slide

  53. typeof performance != 'the whole story'

    View Slide

  54. tips & tricks
    (not really)

    View Slide

  55. New objects
    var obj = new Object();
    obj.x = 42;
    obj.y = 'foo';
    obj.z = false;

    View Slide

  56. New objects
    var obj = {
    'x': 42,
    'y': 'foo',
    'z': false
    };

    View Slide

  57. New arrays
    var arr = new Array();
    arr.push(42);
    arr.push('foo');
    arr.push(false);

    View Slide

  58. New arrays
    var arr = [
    42,
    'foo',
    false
    ];

    View Slide

  59. Avoid switch
    switch(foo) {
    case 'alpha':
    // do X
    break;
    case 'beta':
    // do Y
    break;
    default:
    // do Z
    break;
    }

    View Slide

  60. Avoid switch
    var switchObj = {
    'alpha': function() {
    // do X
    },
    'beta': function() {
    // do Y
    },
    '_default': function() {
    // do Z
    }
    };
    (switchObj.hasOwnProperty(foo) && switchObj[foo] || switchObj._default)(args);

    View Slide

  61. Don’t use jQuery for everything
    $('.foo').click(function() {
    $(this).prop('id');
    // same as this, before jQuery 1.6:
    // $(this).attr('id');
    // also `href`, `checked`, `value`…
    });

    View Slide

  62. Don’t use jQuery for everything
    $('.foo').click(function() {
    this.id;
    this.href;
    this.checked;
    this.value;
    // etc.
    });

    View Slide

  63. jQuery document ready
    $(document).ready(function() {
    // teh coads
    });

    View Slide

  64. jQuery document ready
    $().ready(function() {
    // heh
    });

    View Slide

  65. jQuery document ready
    $.fn.ready(function() {
    // not pretty, but fastest solution
    });

    View Slide

  66. jQuery document ready
    $(function() {
    // moar sexy, but slower
    });

    View Slide

  67. jQuery document ready
    (function() {
    // move s to the bottom<br/>// and just use an IIFE*<br/>}());<br/>// * unless you use .appendChild() / .innerHTML on document.documentElement or document.body: http://mths.be/ieoa<br/>

    View Slide

  68. jQuery collection size
    $('.foo').size(); // NO.

    View Slide

  69. jQuery collection size
    // jQuery source:
    $.fn.size = function() {
    return this.length;
    };
    // …so, just use:
    $('.foo').length;

    View Slide

  70. Use context
    $('#foo .bar').addClass('baz');
    $('#foo .qux').hide();
    $('#foo input').removeClass('wut');

    View Slide

  71. Use context
    var $foo = $('#foo');
    $('.bar', $foo).addClass('baz');
    $('.qux', $foo).hide();
    $('input', $foo).removeClass('wut');

    View Slide

  72. this.location = 'http://jsperf.com/'

    View Slide

  73. http://jsperf.com/browse/mathias-bynens

    View Slide

  74. Questions?
    @mathias

    View Slide