high performance javascript
DESCRIPTION
Performance is a big topic, but this talk will at least touch on the areas that tend to slow down your application: Resource loading, libraries, DOM, CSS, memory, and the application itself. Then we will focus on getting maximum performance from JavaScript and your applications.TRANSCRIPT
HIGH PERFORMANCE JAVASCRIPT
by Mike Wilcox
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Before tuning the JavaScript...
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Page and Resource Loading
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Page and Resource Loading
Libraries or Library Usage
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Page and Resource Loading
Libraries or Library Usage
Application Architecture
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Page and Resource Loading
Libraries or Library Usage
Application Architecture
DOM
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Page and Resource Loading
Libraries or Library Usage
Application Architecture
DOM
CSS
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Page and Resource Loading
Libraries or Library Usage
Application Architecture
DOM
CSS
Memory Management
Wednesday, September 3, 2014
WHAT NEEDS PERFORMANCE
Page and Resource Loading
Libraries or Library Usage
Application Architecture
DOM
CSS
Memory Management
JavaScript
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
DNS lookup + only a few files load in parallel
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
DNS lookup + only a few files load in parallel
The 50 jQuery plugin scripts is a no-no
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
DNS lookup + only a few files load in parallel
The 50 jQuery plugin scripts is a no-no
Too few resources can be very slow
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
DNS lookup + only a few files load in parallel
The 50 jQuery plugin scripts is a no-no
Too few resources can be very slow
Not uncommon for web apps to have 3+ megabytes of code
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
DNS lookup + only a few files load in parallel
The 50 jQuery plugin scripts is a no-no
Too few resources can be very slow
Not uncommon for web apps to have 3+ megabytes of code
Solution:
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
DNS lookup + only a few files load in parallel
The 50 jQuery plugin scripts is a no-no
Too few resources can be very slow
Not uncommon for web apps to have 3+ megabytes of code
Solution:
Load a main core file, enough to display the page, then lazy-load the rest, or as needed.
Wednesday, September 3, 2014
PAGE AND RESOURCE LOADING
Too many resources is very slow
Using requirejs in dev mode can mean 50 files
DNS lookup + only a few files load in parallel
The 50 jQuery plugin scripts is a no-no
Too few resources can be very slow
Not uncommon for web apps to have 3+ megabytes of code
Solution:
Load a main core file, enough to display the page, then lazy-load the rest, or as needed.
Learn (much) more: http://www.slideshare.net/anm8tr/faster-websites-kill-kill-4402077
Wednesday, September 3, 2014
LIBRARIES
Wednesday, September 3, 2014
LIBRARIES
Use the right library
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Angular needs to load a lot of boilerplate and polyfills
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Angular needs to load a lot of boilerplate and polyfills
Use the library the way it was intended
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Angular needs to load a lot of boilerplate and polyfills
Use the library the way it was intended
The Dojo fallacy was making “everything a widget”
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Angular needs to load a lot of boilerplate and polyfills
Use the library the way it was intended
The Dojo fallacy was making “everything a widget”
Angular makes everything a component
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Angular needs to load a lot of boilerplate and polyfills
Use the library the way it was intended
The Dojo fallacy was making “everything a widget”
Angular makes everything a component
Knockout templates can get slow
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Angular needs to load a lot of boilerplate and polyfills
Use the library the way it was intended
The Dojo fallacy was making “everything a widget”
Angular makes everything a component
Knockout templates can get slow
No library can be the right library
Wednesday, September 3, 2014
LIBRARIES
Use the right library
jQuery is easy not fast
Angular needs to load a lot of boilerplate and polyfills
Use the library the way it was intended
The Dojo fallacy was making “everything a widget”
Angular makes everything a component
Knockout templates can get slow
No library can be the right library
No overhead to download - write exactly what the app needsWednesday, September 3, 2014
APPLICATION ARCHITECTURE
Wednesday, September 3, 2014
APPLICATION ARCHITECTURE
Don’t parse everything at once
Wednesday, September 3, 2014
APPLICATION ARCHITECTURE
Don’t parse everything at once
Don’t download all the data at once
Wednesday, September 3, 2014
APPLICATION ARCHITECTURE
Don’t parse everything at once
Don’t download all the data at once
Display *something* as soon as possible
Wednesday, September 3, 2014
APPLICATION ARCHITECTURE
Don’t parse everything at once
Don’t download all the data at once
Display *something* as soon as possible
Know the limits of:
Wednesday, September 3, 2014
APPLICATION ARCHITECTURE
Don’t parse everything at once
Don’t download all the data at once
Display *something* as soon as possible
Know the limits of:
The browser
Wednesday, September 3, 2014
APPLICATION ARCHITECTURE
Don’t parse everything at once
Don’t download all the data at once
Display *something* as soon as possible
Know the limits of:
The browser
Your users
Wednesday, September 3, 2014
APPLICATION ARCHITECTURE
Don’t parse everything at once
Don’t download all the data at once
Display *something* as soon as possible
Know the limits of:
The browser
Your users
You
Wednesday, September 3, 2014
DOM
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
createTextNode can be many times faster than innerHTML
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
createTextNode can be many times faster than innerHTML
Create your widget in a fragment first, then add it to the page
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
createTextNode can be many times faster than innerHTML
Create your widget in a fragment first, then add it to the page
Image resizing is extra work for the browser
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
createTextNode can be many times faster than innerHTML
Create your widget in a fragment first, then add it to the page
Image resizing is extra work for the browser
Like in CSS, setting and getting sizes and positions, and scroll causes a reflow
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
createTextNode can be many times faster than innerHTML
Create your widget in a fragment first, then add it to the page
Image resizing is extra work for the browser
Like in CSS, setting and getting sizes and positions, and scroll causes a reflow
addEventListener is not free
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
createTextNode can be many times faster than innerHTML
Create your widget in a fragment first, then add it to the page
Image resizing is extra work for the browser
Like in CSS, setting and getting sizes and positions, and scroll causes a reflow
addEventListener is not free
Add listeners to the parent and check the clicked node via event.target
Wednesday, September 3, 2014
DOM
Most of the time, creating nodes is faster than a big innerHTML
createTextNode can be many times faster than innerHTML
Create your widget in a fragment first, then add it to the page
Image resizing is extra work for the browser
Like in CSS, setting and getting sizes and positions, and scroll causes a reflow
addEventListener is not free
Add listeners to the parent and check the clicked node via event.target
Do NOT add a listener to hundreds of child nodes
Wednesday, September 3, 2014
CSS
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Keep them clean and maintained, so time is wasted downloading unused definitions
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Keep them clean and maintained, so time is wasted downloading unused definitions
Don’t use JavaScript when it’s a job for CSS
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Keep them clean and maintained, so time is wasted downloading unused definitions
Don’t use JavaScript when it’s a job for CSS
Use element.style as little as possible
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Keep them clean and maintained, so time is wasted downloading unused definitions
Don’t use JavaScript when it’s a job for CSS
Use element.style as little as possible
Set classNames (or better, use classList)
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Keep them clean and maintained, so time is wasted downloading unused definitions
Don’t use JavaScript when it’s a job for CSS
Use element.style as little as possible
Set classNames (or better, use classList)
Use transitions or animations, not jQuery
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Keep them clean and maintained, so time is wasted downloading unused definitions
Don’t use JavaScript when it’s a job for CSS
Use element.style as little as possible
Set classNames (or better, use classList)
Use transitions or animations, not jQuery
Know what styles affect a page reflow and affect performance
Wednesday, September 3, 2014
CSS
Use as few stylesheets as reasonable
Keep them clean and maintained, so time is wasted downloading unused definitions
Don’t use JavaScript when it’s a job for CSS
Use element.style as little as possible
Set classNames (or better, use classList)
Use transitions or animations, not jQuery
Know what styles affect a page reflow and affect performance
Namely anything to do with sizes: setting as well as getting
Wednesday, September 3, 2014
MEMORY MANAGEMENT
Value Graph
Root Node Object Node
Scalar Node
How Garbage Collection Works
Wednesday, September 3, 2014
MEMORY MANAGEMENTObject is dereferenced, and it and its descendants are slated for GC
Value GraphWednesday, September 3, 2014
MEMORY MANAGEMENTHowever, if there is a reference to any object in the tree, it can’t be released
Value GraphWednesday, September 3, 2014
MEMORY MANAGEMENTValue graph example shown in code
var app = {! registry: {},! getWidget: function(id){! ! var widget = {};! ! this.registry[id] = widget;! ! return widget;! }};var widget = app.getWidget('mine');widget = null; // will not release
Wednesday, September 3, 2014
MEMORY MANAGEMENTValue graph example shown in code
var app = {! registry: {},! getWidget: function(id){! ! var widget = {};! ! this.registry[id] = widget;! ! return widget;! }};var widget = app.getWidget('mine');widget = null; // will not release
Moral: Clean up after yourself. Suggest a dispose(); method on the widget that removes itself from the registry
Wednesday, September 3, 2014
Before tuning the JavaScript...
WHEN TO OPTIMIZE
Wednesday, September 3, 2014
Wednesday, September 3, 2014
“Premature optimization is the root of all evil”
~ Donald Knuth
Wednesday, September 3, 2014
“Premature optimization is the root of all evil”
~ Donald Knuth
“Except when you should be planning ahead.”
~ Mike Wilcox
Wednesday, September 3, 2014
PLANNING AHEAD
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Implement or use a widget life cycle system
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Implement or use a widget life cycle system
Unbind event listeners that aren't needed any more
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Implement or use a widget life cycle system
Unbind event listeners that aren't needed any more
Careful with scope
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Implement or use a widget life cycle system
Unbind event listeners that aren't needed any more
Careful with scope
Browsers are actually really good at GC
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Implement or use a widget life cycle system
Unbind event listeners that aren't needed any more
Careful with scope
Browsers are actually really good at GC
But know when you are capturing in your closures
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Implement or use a widget life cycle system
Unbind event listeners that aren't needed any more
Careful with scope
Browsers are actually really good at GC
But know when you are capturing in your closures
Use JSHint in your IDE
Wednesday, September 3, 2014
PLANNING AHEAD
Clean up after yourself
Implement or use a widget life cycle system
Unbind event listeners that aren't needed any more
Careful with scope
Browsers are actually really good at GC
But know when you are capturing in your closures
Use JSHint in your IDE
It will warn against bad practices that can slow your code
Wednesday, September 3, 2014
DON’T WORRY
Wednesday, September 3, 2014
DON’T WORRY
Maintainability trumps performance 98.6% of the time
Wednesday, September 3, 2014
DON’T WORRY
Maintainability trumps performance 98.6% of the time
90% of the time, the only performance you'll need is rendering DOM
Wednesday, September 3, 2014
DON’T WORRY
Maintainability trumps performance 98.6% of the time
90% of the time, the only performance you'll need is rendering DOM
Code that is async, or immediately after is not performance critical
Wednesday, September 3, 2014
DON’T WORRY
Maintainability trumps performance 98.6% of the time
90% of the time, the only performance you'll need is rendering DOM
Code that is async, or immediately after is not performance critical
Size matters
Wednesday, September 3, 2014
DON’T WORRY
Maintainability trumps performance 98.6% of the time
90% of the time, the only performance you'll need is rendering DOM
Code that is async, or immediately after is not performance critical
Size matters
A loop of 20 items will be fine in a forEach, suffering a few measly milliseconds
Wednesday, September 3, 2014
CRITICAL AREAS
Wednesday, September 3, 2014
CRITICAL AREAS
Memory is always critical - it can give you the scrolling “janks”
Wednesday, September 3, 2014
CRITICAL AREAS
Memory is always critical - it can give you the scrolling “janks”
Template parsing; especially many widgets on page load
Wednesday, September 3, 2014
CRITICAL AREAS
Memory is always critical - it can give you the scrolling “janks”
Template parsing; especially many widgets on page load
Canvas rendering; especially animation
Wednesday, September 3, 2014
CRITICAL AREAS
Memory is always critical - it can give you the scrolling “janks”
Template parsing; especially many widgets on page load
Canvas rendering; especially animation
Oft-triggered actions, like on page resize or mousemove
Wednesday, September 3, 2014
CRITICAL AREAS
Memory is always critical - it can give you the scrolling “janks”
Template parsing; especially many widgets on page load
Canvas rendering; especially animation
Oft-triggered actions, like on page resize or mousemove
Millions of items of grid data
Wednesday, September 3, 2014
CRITICAL AREAS
Memory is always critical - it can give you the scrolling “janks”
Template parsing; especially many widgets on page load
Canvas rendering; especially animation
Oft-triggered actions, like on page resize or mousemove
Millions of items of grid data
Just kidding. You should never do this.
Wednesday, September 3, 2014
JAVASCRIPT PERFORMANCE
Now you’re ready improve your...
Wednesday, September 3, 2014
AVOID EVAL
Wednesday, September 3, 2014
AVOID EVAL
As well as new Function(...) or a string in setTimeout()
Wednesday, September 3, 2014
AVOID EVAL
As well as new Function(...) or a string in setTimeout()
Expensive operations as each time they are called, the script engine must convert source to executable code
Wednesday, September 3, 2014
AVOID EVAL
As well as new Function(...) or a string in setTimeout()
Expensive operations as each time they are called, the script engine must convert source to executable code
Has to be interpreted at runtime - #NOJIT
Wednesday, September 3, 2014
AVOID EVAL
As well as new Function(...) or a string in setTimeout()
Expensive operations as each time they are called, the script engine must convert source to executable code
Has to be interpreted at runtime - #NOJIT
Better:
Wednesday, September 3, 2014
AVOID EVAL
As well as new Function(...) or a string in setTimeout()
Expensive operations as each time they are called, the script engine must convert source to executable code
Has to be interpreted at runtime - #NOJIT
Better:
Use JSON
Wednesday, September 3, 2014
AVOID EVAL
As well as new Function(...) or a string in setTimeout()
Expensive operations as each time they are called, the script engine must convert source to executable code
Has to be interpreted at runtime - #NOJIT
Better:
Use JSON
Parse function with a predetermined convention
Wednesday, September 3, 2014
Slow:with (test.object) { foo = 'Value of foo property of object'; bar = 'Value of bar property of object';}
Faster:var myObj = test.object;myObj.foo = 'Value of foo property of object';myObj.bar = 'Value of bar property of object';
Hopefully you weren’t doing this...
AVOID WITH
Wednesday, September 3, 2014
Slow:with (test.object) { foo = 'Value of foo property of object'; bar = 'Value of bar property of object';}
Faster:var myObj = test.object;myObj.foo = 'Value of foo property of object';myObj.bar = 'Value of bar property of object';
Hopefully you weren’t doing this...
AVOID WITH
Wednesday, September 3, 2014
Slow: for (i = 0; i < object.length; i++) { try { // do something that throws an exception } catch (e) { // handle exception }}
Faster:try { for (i = 0; i < object.length; i++) { // do something }} catch (e) { // handle exception}
#NOJIT
TRY-CATCH
Wednesday, September 3, 2014
Slow: for (i = 0; i < object.length; i++) { try { // do something that throws an exception } catch (e) { // handle exception }}
Faster:try { for (i = 0; i < object.length; i++) { // do something }} catch (e) { // handle exception}
#NOJIT
TRY-CATCH
Wednesday, September 3, 2014
Slow:window.str = '';function globalScope() { for (var i=0; i < 100; i++) { str += i; }}
Faster:window.str = '';function localScope() { var tempstr = ''; for (var i=0; i < 100; i++) { tempstr += i; } str = tempstr;}
Slow lookup; Bad GC
AVOID GLOBAL SCOPE
Wednesday, September 3, 2014
Slow:window.str = '';function globalScope() { for (var i=0; i < 100; i++) { str += i; }}
Faster:window.str = '';function localScope() { var tempstr = ''; for (var i=0; i < 100; i++) { tempstr += i; } str = tempstr;}
Slow lookup; Bad GC
AVOID GLOBAL SCOPE
Wednesday, September 3, 2014
// always the same! Get the variable firstvar a = 0;for(var i = 0; i < array.length; i++){
a += Math.sin(1);}
// creating a new function every time #NOJITvar a = 0, b = [1,2,3];for(var i = 0; i < array.length; i++){
b.forEach(function(num){a += num;
}); }
Functions take time, creating them is worse
UNNECESSARY FUNCTIONS
Wednesday, September 3, 2014
// always the same! Get the variable firstvar a = 0;for(var i = 0; i < array.length; i++){
a += Math.sin(1);}
// creating a new function every time #NOJITvar a = 0, b = [1,2,3];for(var i = 0; i < array.length; i++){
b.forEach(function(num){a += num;
}); }
Functions take time, creating them is worse
UNNECESSARY FUNCTIONS
Wednesday, September 3, 2014
// always the same! Get the variable firstvar a = 0;for(var i = 0; i < array.length; i++){
a += Math.sin(1);}
// creating a new function every time #NOJITvar a = 0, b = [1,2,3];for(var i = 0; i < array.length; i++){
b.forEach(function(num){a += num;
}); }
Functions take time, creating them is worse
UNNECESSARY FUNCTIONS
Wednesday, September 3, 2014
// Problem: for large arrays, this can get slowvar items = [{id:'a'}, {id:'b'}, {id:'c'}];function getItemById(id){! for(var i = 0; i < items.length; i++){! ! if(items[i].id === id){! ! ! return items[i];! ! }! }}
// Solution: use a hash map insteadvar items = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};function getItemById(id){! return items[id];}
Unnecessary Array lookups
LIST VS MAPS
Wednesday, September 3, 2014
// Problem: for large arrays, this can get slowvar items = [{id:'a'}, {id:'b'}, {id:'c'}];function getItemById(id){! for(var i = 0; i < items.length; i++){! ! if(items[i].id === id){! ! ! return items[i];! ! }! }}
// Solution: use a hash map insteadvar items = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};function getItemById(id){! return items[id];}
Unnecessary Array lookups
LIST VS MAPS
Wednesday, September 3, 2014
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];}
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];}
function getItemById(id){
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];}
function getItemById(id){! return itemMap[id];
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];}
function getItemById(id){! return itemMap[id];}
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];}
function getItemById(id){! return itemMap[id];}
// Could also get tricky:
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];}
function getItemById(id){! return itemMap[id];}
// Could also get tricky: itemList.map = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Solution: Why not use both?var! itemList = [{id:'a'}, {id:'b'}, {id:'c'}],! itemMap = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};!function addItem(item){! itemList.push(item);! itemMap[item.id] = item;}function getItemByIndex(index){! return itemList[index];}
function getItemById(id){! return itemMap[id];}
// Could also get tricky: itemList.map = {a:{id:'a'}, b:{id:'b'}, c:{id:'c'}};
Problem: you need an “ordered hash map”
LIST VS MAPS
Wednesday, September 3, 2014
// Fastestfor(var i = 0; i < array.length; i++){
this.doThing(i); }
// Fast(ish)array.forEach(function(){
doThing(i); });
// Slowvar self = this;array.forEach(function(i){ self.doThing(i); });
// Slowestarray.forEach(function(i){ this.doThing(i); }, this);
Changing context on a function is costly
THIS
Wednesday, September 3, 2014
OBJECTS VS ARRAYS
http://www.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/Wednesday, September 3, 2014
OBJECTS VS ARRAYS
Properties on objects are quite complex: they can be created with setters, and with differing enumerability and writability.
http://www.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/Wednesday, September 3, 2014
OBJECTS VS ARRAYS
Properties on objects are quite complex: they can be created with setters, and with differing enumerability and writability.
Items in arrays aren’t able to be customized as heavily — they either exist or they don’t. At an engine level, this allows for more optimization.
http://www.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/Wednesday, September 3, 2014
OBJECTS VS ARRAYS
Properties on objects are quite complex: they can be created with setters, and with differing enumerability and writability.
Items in arrays aren’t able to be customized as heavily — they either exist or they don’t. At an engine level, this allows for more optimization.
This is particularly beneficial when the array contains numbers. For example, when you need vectors, don’t define a class with properties x, y, z; use an array instead.
http://www.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/Wednesday, September 3, 2014
Memoryhttps://speakerdeck.com/addyosmani/javascript-memory-management-masterclass
Loopshttp://jsperf.com/fastest-array-loops-in-javascript/32
http://jsperf.com/add-a-property-to-an-array/2http://jsperf.com/array-vs-uint32array
Functionshttp://jsperf.com/iifes-vs-nested-functions/2
Performancehttps://github.com/sq/JSIL/wiki/JavaScript-Performance-For-Madmen
https://gist.github.com/khoomeister/4985691 (make js faster)http://www.html5rocks.com/en/tutorials/speed/v8/
http://www.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/http://developer.nokia.com/community/wiki/JavaScript_Performance_Best_Practices
http://code.mendhak.com/angular-performance/
Librarieshttp://xepler.com/blog/2014/03/19/the-good-the-bad-and-the-ugly-a-jquery-tale
References
Wednesday, September 3, 2014
Wednesday, September 3, 2014