├── inheritance └── inheritance.md ├── js-better-faster.css ├── credits └── credits.md ├── showoff.json ├── modules └── modules.md ├── title └── title.md ├── pageload └── pageload.md ├── tools └── tools.md ├── timers └── timers.md ├── unrelated └── unrelated.md ├── resources └── resources.md ├── LICENSE ├── jslang └── jslang.md ├── dom └── dom.md └── pitfalls └── pitfalls.md /inheritance/inheritance.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # Inheritance 4 | 5 | !SLIDE 6 | 7 | # don't use it 8 | 9 | ## unless you have to 10 | 11 | ### and that's all I have to say about that 12 | -------------------------------------------------------------------------------- /js-better-faster.css: -------------------------------------------------------------------------------- 1 | .biblioteca ul { 2 | font-size: 20pt; 3 | } 4 | 5 | .biblioteca ul li { 6 | line-height: 32pt; 7 | } 8 | 9 | .process ol { 10 | font-size: 20pt; 11 | } 12 | 13 | .process ol li { 14 | line-height: 32pt; 15 | } 16 | 17 | .overview ol { 18 | font-size: 24pt; 19 | } 20 | 21 | .overview ol li { 22 | line-height: 32pt; 23 | } -------------------------------------------------------------------------------- /credits/credits.md: -------------------------------------------------------------------------------- 1 | !SLIDE biblioteca 2 | 3 | # this slideshow 4 | 5 | ## was running in the browser, with JavaScript 6 | 7 | * source on GitHub at 8 | * available online at 9 | * built with ShowOff - 10 | 11 | --- 12 | 13 | ## thanks for coming! -------------------------------------------------------------------------------- /showoff.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"section": "title"}, 3 | {"section": "jslang"}, 4 | {"section": "pitfalls"}, 5 | {"section": "inheritance"}, 6 | {"section": "modules"}, 7 | {"section": "dom"}, 8 | {"section": "timers"}, 9 | {"section": "pageload"}, 10 | {"section": "tools"}, 11 | {"section": "unrelated"}, 12 | {"section": "resources"}, 13 | {"section": "credits"} 14 | ] 15 | -------------------------------------------------------------------------------- /modules/modules.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # modules 4 | 5 | ## how to make `BC.util`? 6 | 7 | ### _not_ the same as inheritance 8 | 9 | !SLIDE 10 | 11 | @@@ javascript 12 | BC.util = (function (BC) { 13 | var util = {}, 14 | foo; // private variable 15 | 16 | // public 17 | util.someFunction = function () {}; 18 | 19 | // private 20 | function someOther() {} 21 | 22 | return util; 23 | }(BC)); 24 | --- 25 | ## this a fast, reusable pattern -------------------------------------------------------------------------------- /title/title.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | # JavaScript: Better and Faster # 3 | 4 | ## Ben Cherry 5 | 6 | ### Performance Engineer at Slide, Inc. 7 | 8 | !SLIDE overview 9 | 10 | # what we'll cover 11 | 12 | 1. the JavaScript language 13 | 2. run-time performance pitfalls 14 | 3. inheritance 15 | 4. DOM performance 16 | 5. long-running scripts 17 | 6. page-load performance 18 | 7. performance tools 19 | 8. random extras 20 | 9. other resources 21 | 22 | --- 23 | ## and we'll try to do it in one hour -------------------------------------------------------------------------------- /pageload/pageload.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # page-load performance 4 | 5 | ## getting your script running quickly 6 | 7 | !SLIDE 8 | @@@ html 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | --- 17 | ## always at the bottom, so the page is not blocked 18 | # no exceptions! 19 | 20 | !SLIDE 21 | # avoid inline scripts 22 | @@@ html 23 | 28 | --- 29 | ## these cannot be cached or minified 30 | ## only put dynamic values here 31 | 32 | !SLIDE 33 | # minification 34 | --- 35 | @@@ javascript 36 | function foo() { 37 | var bar = 1; 38 | return bar + 5; 39 | } 40 | --- 41 | @@@ javascript 42 | function foo(){var a=1;return a+5} 43 | --- 44 | ## our build process does this for you 45 | ## make sure you're using it! -------------------------------------------------------------------------------- /tools/tools.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # Performance Tools 4 | 5 | !SLIDE 6 | 7 | # my JavaScript profiler 8 | --- 9 | @@@ javascript 10 | var profiler = performance.newProfiler(); 11 | function foo() { 12 | profiler.begin("body"); 13 | // ... some operations ... 14 | profiler.end("body"); 15 | } 16 | // ... repeated calls to foo() ... 17 | profiler.report(); // alerts time spent in "body" 18 | --- 19 | ## source at 20 | 21 | !SLIDE biblioteca 22 | 23 | # other tools 24 | 25 | * JSLint (JavaScript syntax checker) 26 | * YSlow (Firebug extension) 27 | * Page Speed (Firebug extension) 28 | * Speed Tracer (Chrome extension) 29 | * dynaTrace AJAX (Windows program/IE plugin) -------------------------------------------------------------------------------- /timers/timers.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # long-running operations 4 | 5 | ## sometimes you can't avoid it 6 | 7 | !SLIDE 8 | 9 | # problem script 10 | --- 11 | @@@ javascript 12 | var i; 13 | for (i = 0; i < 10000; i += 1) { 14 | oneMillisecondOperation(i); 15 | } 16 | --- 17 | ## browser locks for 10s! 18 | 19 | !SLIDE 20 | 21 | # solution: timers 22 | --- 23 | @@@ javascript 24 | var i = 0; 25 | setTimeout(function iterate() { 26 | var stop = i + 500; 27 | for (; i < stop; i += 1) { 28 | oneMillisecondOperation(i); 29 | } 30 | setTimeout(iterate, 20); 31 | }, 0); 32 | --- 33 | ## split into half-second chunks, with 20ms in between 34 | 35 | !SLIDE bullets 36 | # minimum intervals 37 | --- 38 | @@@ javascript 39 | setTimeout(function () { 40 | alert("foo"); 41 | }, 0); 42 | // how long until "foo"? 43 | --- 44 | ## no browser really does 0ms 45 | ## Chrome is ~5ms, but IE is ~18ms 46 | ## others are ~10-12ms 47 | 48 | -------------------------------------------------------------------------------- /unrelated/unrelated.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # random extras 4 | 5 | ## somewhat important 6 | 7 | !SLIDE 8 | 9 | # `parseInt` needs radix! 10 | --- 11 | @@@ javascript 12 | parseInt("123"); // 123 13 | parseInt("10"); // 10 14 | parseInt("010"); // 8 -> WTF? 15 | 16 | // with a radix 17 | parseInt("010", 10); // 10 -> crisis averted! 18 | --- 19 | ## never forget your radix 20 | 21 | !SLIDE 22 | 23 | # `sort` has issues 24 | --- 25 | @@@ javascript 26 | var a = [3,1,2]; 27 | a.sort(); // [1,2,3] 28 | a = [10,1,2]; 29 | 30 | a.sort(); // [1,10,2] - f**ing javascript! 31 | 32 | a.sort(betterComparison); // [1,2,10] 33 | --- 34 | ## `.sort()` sorts alphabetically 35 | ## write your own comparison function 36 | 37 | !SLIDE 38 | 39 | # CSS expressions are evaluated _right-to-left_! 40 | --- 41 | @@@ css 42 | #foo div a {/* ... */} 43 | --- 44 | ## this starts by looking at every `` 45 | ## then it looks for those whose parent is `
` 46 | ## then it checks to see if its parent is `#foo` 47 | -------------------------------------------------------------------------------- /resources/resources.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # Useful Resources 4 | 5 | ## because this was not nearly exhaustive 6 | 7 | !SLIDE biblioteca 8 | 9 | # dead trees 10 | 11 | * _High Performance Web Sites_, by Steve Souders (Yahoo!, at the time) 12 | * _Even Faster Web Sites_, by Steve Souders (Google, now) 13 | * _JavaScript: The Good Parts_, by Douglas Crockford (Yahoo!) 14 | * _High Performance JavaScript_, by Nicholas Zakas (Yahoo!) (_coming soon_) 15 | * _Secrets of the JavaScript Ninja_, by John Resig (Mozilla/jQuery) (_coming soon_) 16 | 17 | !SLIDE biblioteca 18 | 19 | # blogs 20 | 21 | * _High Performance Web Sites_, by Steve Souders 22 | * _NCZOnline_, by Nicholas Zakas 23 | * _Douglas Crockford's JavaScript_, by Doug Crockford 24 | * _Perfection Kills_, by @kangax (author of Prototype.js) 25 | * _John Resig - Blog_, by John Resig (creator of jQuery) 26 | * _Software is Hard_, by Jan Odvarko (Firebug developer) 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ben Cherry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /jslang/jslang.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # The JavaScript Language # 4 | 5 | ### just what you need to know to understand this talk ### 6 | 7 | !SLIDE 8 | 9 | # variables and functions # 10 | --- 11 | @@@ javascript 12 | var foo = 1; // variable statement 13 | 14 | function bar() {} // function statement 15 | 16 | (function baz() {}); // function expression 17 | 18 | (function (spam) {}(1)); // function parameter 19 | --- 20 | ## those are the _only ways_ you should declare things 21 | 22 | !SLIDE 23 | 24 | # scope # 25 | --- 26 | @@@ javascript 27 | var foo = 1; 28 | (function () { 29 | var baz = 2; 30 | foo = 3; 31 | }()); 32 | alert(foo); // 3 33 | alert(baz); // ReferenceError 34 | --- 35 | ## JavaScript has _function-level scope_ 36 | 37 | !SLIDE 38 | 39 | # hoisting # 40 | --- 41 | @@@ javascript 42 | var foo = 1; 43 | (function () { 44 | alert(foo); // undefined 45 | var foo = 2; 46 | }()); 47 | alert(foo); // 1 48 | --- 49 | ## names are always _hoisted_ to the top of their scope 50 | ## and always initialized to `undefined` 51 | !SLIDE 52 | 53 | # closure # 54 | --- 55 | @@@ javascript 56 | var foo = (function () { 57 | var bar = 5; 58 | 59 | return function () { 60 | alert(bar); 61 | }; 62 | }()); 63 | foo(); // 5 64 | setTimeout(foo, 10000); // 5, 10s later 65 | --- 66 | ## functions have access to their original _scope chain_ -------------------------------------------------------------------------------- /dom/dom.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # The DOM 4 | 5 | ## it's absolutely terrible 6 | 7 | ### but I have three simple rules to make it better 8 | 9 | !SLIDE subsection 10 | 11 | # rule 1 12 | 13 | ## never edit the live tree 14 | 15 | !SLIDE 16 | 17 | # you can detach sub-trees 18 | --- 19 | @@@ javascript 20 | var elem = $("#myelem"), 21 | parent = elem.parent(); 22 | 23 | elem.detach(); 24 | // ... muck with elem and sub-elements ... 25 | parent.append(elem); 26 | --- 27 | ### `.detach()` is new in jQuery 1.4 28 | 29 | !SLIDE 30 | 31 | # or you can clone and replace 32 | --- 33 | @@@ javascript 34 | var old = $("#myelem"), 35 | clone = old.clone(); 36 | 37 | // ... muck with the clone ... 38 | old.replaceWith(clone); 39 | --- 40 | 41 | ## but be careful about event handlers 42 | ## use `.clone(true)` to preserve them 43 | 44 | !SLIDE subsection 45 | 46 | # rule 2 47 | 48 | ## build bottom-up 49 | 50 | !SLIDE 51 | 52 | # bottom-up construction 53 | --- 54 | @@@ javascript 55 | var child = document.createElement("div"), 56 | parent = document.createElement("div"), 57 | grand = document.createElement("div"); 58 | 59 | parent.appendChild(child); 60 | grand.appendChild(parent); 61 | document.body.appendChild(grand); 62 | 63 | !SLIDE subsection 64 | 65 | # rule 3 66 | 67 | ## minimize event handlers 68 | 69 | !SLIDE 70 | # memory leaks in IE 71 | @@@ javascript 72 | $(".myelems").bind("click", function () {/* ... */}); 73 | 74 | // ... 75 | 76 | $(".myelems").remove(); 77 | 78 | // aww snap, memory leak! 79 | --- 80 | ## was that really that surprising? 81 | 82 | !SLIDE 83 | # unbind before removal 84 | --- 85 | @@@ javascript 86 | $(".myelems").unbind("click").remove(); 87 | // phew! 88 | --- 89 | ## but that kind of sucks too 90 | 91 | !SLIDE 92 | # use event delegation 93 | --- 94 | @@@ javascript 95 | $(".myelems").live("click", function () {/* ... */}); 96 | 97 | $(".myelems").remove(); 98 | 99 | $("
").addClass("myelems").appendTo($("body")); 100 | --- 101 | ## the new `
` gets the handler for free 102 | 103 | !SLIDE 104 | # avoid handlers in loops 105 | --- 106 | @@@ javascript 107 | function makeElem(id) { 108 | return $("
").attr("id", id).click(function () { 109 | alert($(this).attr("id")); 110 | }); 111 | } 112 | 113 | var i; 114 | for (i = 0; i < 1000; i += 1) { 115 | someParent.append(makeElem(i)); 116 | } 117 | --- 118 | ## this is slow! 119 | 120 | !SLIDE 121 | # faster 122 | --- 123 | @@@ javascript 124 | function handler() { 125 | alert(this.attr("id")); 126 | } 127 | 128 | function makeElem(id) { 129 | return $("
").attr("id", i).click(handler); 130 | } 131 | 132 | var i; 133 | for (i = 0; i < 1000; i += 1) { 134 | someParent.append(makeElem(i)); 135 | } 136 | -------------------------------------------------------------------------------- /pitfalls/pitfalls.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | 3 | # Run-Time Performance # 4 | ## common pitfalls ## 5 | 6 | !SLIDE subsection 7 | 8 | # "namespaces" # 9 | 10 | !SLIDE 11 | 12 | ## Python ## 13 | 14 | @@@ python 15 | import bc.util 16 | bc.util.some_function() 17 | 18 | # this is quite fast 19 | --- 20 | ## JavaScript ## 21 | 22 | @@@ javascript 23 | BC.util.someFunction(); 24 | 25 | // but this is very slow 26 | 27 | !SLIDE process 28 | 29 | # here's what happens # 30 | --- 31 | @@@ javascript 32 | BC.util.someFunction(); 33 | 34 | 1. lookup `BC` 35 | 2. resolve property `util` 36 | 3. resolve property `someFunction` 37 | 4. execute function 38 | 39 | --- 40 | ## imagine that in a loop! ## 41 | 42 | !SLIDE 43 | 44 | # store that reference # 45 | --- 46 | @@@ javascript 47 | var some_function = BC.util.some_function, 48 | i; 49 | 50 | for (i = 0; i < 1000000; i += 1) { 51 | some_function(); 52 | } 53 | --- 54 | ## this is much faster ## 55 | 56 | !SLIDE subsection 57 | 58 | # scope chains # 59 | 60 | !SLIDE 61 | 62 | # the slow way 63 | --- 64 | @@@ javascript 65 | var foo = 1; 66 | function bar() { 67 | var i; 68 | for (i = 0; i < 10000; i += 1) { 69 | alert(foo); 70 | } 71 | } 72 | bar(); 73 | --- 74 | ## `foo` is one step down the chain 75 | 76 | !SLIDE 77 | 78 | # faster 79 | --- 80 | @@@ javascript 81 | var foo = 1; 82 | function bar() { 83 | var myFoo = foo, i; 84 | for (i = 0; i < 10000; i += 1) { 85 | alert(myFoo); 86 | } 87 | } 88 | bar(); 89 | --- 90 | ## now `myFoo` is on the end of the chain 91 | 92 | !SLIDE subsection 93 | 94 | # arrays 95 | 96 | !SLIDE 97 | 98 | # arrays are objects, not arrays 99 | --- 100 | @@@ javascript 101 | var a = []; 102 | typeof a; // "object" 103 | a.length; // 0 104 | 105 | a[10] = 1; 106 | a.length; // 11 107 | 108 | a["something_else"] = 1; 109 | a.something_else; // 1 110 | a.length; // 11 111 | 112 | !SLIDE 113 | # this means arrays are slower than you expect 114 | 115 | ## but some browsers do optimize them 116 | 117 | !SLIDE subsection 118 | 119 | # loops 120 | 121 | !SLIDE 122 | 123 | # for loops 124 | --- 125 | @@@ javascript 126 | // slow method 127 | var i; 128 | for (i = 0; i < someArray.length; i += 1) { 129 | // ... 130 | } 131 | --- 132 | @@@ javascript 133 | // faster 134 | var i, l; 135 | for (i = 0, l = someArray.length; i < l; i += 1) { 136 | // ... 137 | } 138 | 139 | !SLIDE 140 | 141 | # for-in loops 142 | --- 143 | @@@ javascript 144 | var key; 145 | for (key in someObject) { 146 | // ... 147 | } 148 | --- 149 | ## these are slow, avoid them 150 | 151 | !SLIDE 152 | 153 | # for-in alternative 154 | --- 155 | @@@ javascript 156 | var keys = ["foo", "bar", "baz"], i, l, key; 157 | for (i = 0, l = keys.length; i < l; i += 1) { 158 | key = keys[key]; 159 | // ... someObject[key] ... 160 | } 161 | --- 162 | ## this is much faster, and is preferred 163 | 164 | !SLIDE subsection 165 | 166 | # arguments 167 | 168 | !SLIDE 169 | 170 | @@@ javascript 171 | function foo() { 172 | return arguments[0]; 173 | } 174 | foo(1); // 1 175 | --- 176 | ## much slower (up to 100x) than using parameters 177 | ## `arguments` should be avoided if possible 178 | 179 | --------------------------------------------------------------------------------