high performance javascript - jquery conference sf bay area 2010

Post on 27-Jan-2015

109 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

Learn the inner workings of JavaScript to learn what makes things slow and how to speed them up. Heavily focused on DOM manipulation and UI updates.

TRANSCRIPT

High Performance JavaScriptNicholas C. Zakas

Principal Front End Engineer, Yahoo!jQuery Conference – SF Bay Area, April 24 2010

Principal Front End Engineer

Contributor

Author

Things I Know About

jQuery

YUI

JavaScript

Professional Wrestling

Does this matter?

Old computers ran slow applications Small amounts of CPU power and memory

New computers are generally faster butslow applications still exist

More CPU + more memory = less disciplined application development

It's still possible to write slow JavaScript on the new, faster

JavaScript engines

How can I improve JavaScript performance?

How can I improve JavaScript performance?

How can I make this fast???

How can I improve JavaScript performance?

How can I make this fast???

Why is this so slow?????

Many aspects conspire to make JavaScript slow Awareness is the first step to solution

The UI ThreadThe brains of the operation

The browser UI thread is responsible forboth UI updates and JavaScript execution

Only one can happen at a time

Jobs for UI updates and JavaScript execution areadded to a UI queue if the UI thread is busy

Each job must wait in line for its turn to execute

<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>

<script type="text/javascript">$(document).ready(function(){ $("#btn").bind("click",function(){ //do something });});</script>

Before Click

UI Thread

UI Queue

time

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

Draw down state

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

onclick UI UpdateUI Update

Draw up state

No UI updates while JavaScript is executing!

JavaScript May Cause UI Update

<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>

<script type="text/javascript">$(document).ready(function(){ $("#btn").bind("click",function(){ $("body").append("<div class=\"tip\">You " +

"clicked me!</div>”); });});</script>

A UI update must use the latest info available

Long-running JavaScript=

Unresponsive UI

Responsive UI

UI Thread

time

JavaScript UI UpdateUI Update

Unresponsive UI

UI Thread

time

JavaScript UI UpdateUI Update

The runaway script timer prevents JavaScriptfrom running for too long

Each browser imposes its own limit (except Opera)

Internet Explorer

Firefox

Safari

Chrome

Runaway Script Timer Limits• Internet Explorer: 5 million statements• Firefox: 10 seconds• Safari: 5 seconds• Chrome: Unknown, hooks into normal crash

control mechanism• Opera: none

How Long Is Too Long?

“0.1 second [100ms] is about the limit for having the user feel that the system is reacting instantaneously, meaning that no special feedback is necessary except to display the result.”

- Jakob Nielsen

Translation:No single JavaScript job should execute for more than 100ms to

ensure a responsive UI

Recommendation:Limit JavaScript execution to no more

than 50ms

function processArray(items, process, callback){ for (var i=0,len=items.length; i < len; i++){ process(items[i]); } callback();}

Timers to the rescue!

JavaScript Timers

• Created using setTimeout()• Schedules a new JavaScript execution job for

some time in the future• When the delay is up, the job is added to the

UI queue– Note: This does not guarantee execution

after the delay, just that the job is added to the UI queue and will be executed when appropriate

JavaScript Timers

• For complex processing, split up into timed functionality

• Use timers to delay some processing for later

function timedProcessArray(items, process, callback){ //create a clone of the original

var todo = items.concat(); setTimeout(function(){ var start = +new Date(); do { process(todo.shift()); } while (todo.length > 0 && (+new Date() - start < 50)); if (todo.length > 0){ setTimeout(arguments.callee, 25); } else { callback(items); } }, 25);}

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

UI UpdateUI Update onclick

After 25ms

UI Thread

UI Queue

time

UI UpdateUI Update onclick

JavaScript

After 25ms

UI Thread

UI Queue

time

UI UpdateUI Update onclick JavaScript

After Another 25ms

UI Thread

UI Queue

time

UI UpdateUI Update onclick JavaScript

JavaScript

After Another 25ms

UI Thread

UI Queue

time

UI UpdateUI Update onclick JavaScript JavaScript

Web Workers to the rescue!

Web Workers

• Asynchronous JavaScript execution• Execution happens in a separate process

– Not on the UI thread = no UI delays• Data-driven API

– Data is serialized when sending data into or out of Worker

– No access to DOM, BOM– Completely separate execution

environment

//in pagevar worker = new Worker("process.js");worker.onmessage = function(event){ useData(event.data);};worker.postMessage(values);

//in process.jsself.onmessage = function(event){ var items = event.data; for (var i=0,len=items.length; i < len; i++){ process(items[i]); } self.postMessage(items);};

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

When Clicked

UI Thread

UI Queue

time

onclick

UI Update

UI Update

Worker Thread

When Clicked

UI Thread

UI Queue

time

UI UpdateUI Update onclick

Worker Thread

JavaScript

Worker Thread Complete

UI Thread

UI Queue

time

UI UpdateUI Update onclick

onmessage

Worker Thread Complete

UI Thread

UI Queue

time

UI UpdateUI Update onclick onmessage

Web Workers Support

4.04.03.53.5 4.04.0

Repaint and ReflowUI update jobs

Long UI updates=

Unresponsive UI

Unresponsive UI

UI Thread

time

JavaScript UI UpdateUI Update

Long UI updates=

Unresponsive UI=

Frustrated users

JavaScript can cause long UI updates

A repaint occurs when a visual change doesn't require recalculation of layout

Changes to visibility, colors (text/background), background images, etc.

Repaint

<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>

<script type="text/javascript">$(document).ready(function(){ $("#btn").bind("click",function(){ $(this).css({ color: "#f00" }); });});</script> Repaint!

A reflow occurs when a visual change requires a change in layout

Initial page load ▪ browser resize ▪ DOM structure change ▪ layout style changelayout information retrieved

Reflow

<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>

<script type="text/javascript">$(document).ready(function(){ $("#btn").bind("click",function(){ $("body").append("<div class=\"tip\">You " +

"clicked me!</div>”); });});</script> Reflow!

Repaints and reflows are queued up as JavaScript executes

Reflow

var list = $("ul.items");

for (var i=0; i < 10; i++){ list.append("<li>Item #" + i + "</li>");}

Reflow x 10!

Limiting repaints/reflows improves overall performance

Solution #1Perform DOM manipulations

off-document

Off-Document Operations

• Fast because there's no repaint/reflow• Techniques:

– Remove element from the document, make changes, insert back into document

– Set element's display to “none”, make changes, set display back to default

– Build up DOM changes on a DocumentFragment then apply all at once

DocumentFragment• A document-like object• Not visually represented• Considered to be owned by the document from

which it was created• When passed to appendChild(), appends all

of its children rather than itself

Reflow!

No reflow!

Solution #2Group Style Changes

$("span.example").css({ color: "red" });$("span.example").css({ height: "100px" });$("span.example").css({ fontSize: "25px" });$("span.example").css({ backgroundColor: "white" });

Repaint! Reflow!

Reflow!

Repaint!

.active { color: red; height: 100px; fontSize: 25px; background-color: white;}

$("span.example").addClass("active");

Reflow!

Grouping Style Changes

var item = document.getElementById("myItem");item.style.cssText = "color:red;height:100px;" + "font-size:25px;background-color: white");

Reflow!

Grouping Style Changes

Solution #3Avoid Accidental Reflow

$("div.example").css({ width: "100px"});

var width = $("div.example").width();

Reflow!

Accidental Reflow

What to do?• Minimize access to layout information

– offsetTop, offsetLeft, offsetWidth, offsetHeight– scrollTop, scrollLeft, scrollWidth, scrollHeight– clientTop, clientLeft, clientWidth, clientHeight– Most computed styles

• If a value is used more than once, store in local variable

Recap

Things I Know About

jQuery

YUI

JavaScript

Professional Wrestling

The browser UI thread is responsible forboth UI updates and JavaScript execution

Only one can happen at a time

Responsive UI

UI Thread

time

JavaScript UI UpdateUI Update

Unresponsive UI

UI Thread

time

JavaScript UI UpdateUI Update

Unresponsive UI

UI Thread

time

JavaScript UI UpdateUI Update

Avoid Slow JavaScript• Don't allow JavaScript to execute for more

than 50ms• Break up long JavaScript processes using:

– Timers– Web Workers

Avoid Long UI Updates• Be careful of repaint and reflow• Perform complex DOM operations off-

document– Remove elements and re-add them– Use DocumentFragment objects

• Group style changes together• Avoid accidental reflow

Questions?

Etcetera• My blog: www.nczonline.net• My email: nzakas@yahoo-inc.com• Twitter: @slicknet

Creative Commons Images Used• http://www.flickr.com/photos/lrargerich/3115367361/

• http://www.flickr.com/photos/photomonkey/93277011/

• http://www.flickr.com/photos/hippie/2406411610/

• http://www.flickr.com/photos/55733754@N00/3325000738/

• http://www.flickr.com/photos/eurleif/255241547/

• http://www.flickr.com/photos/off_the_wall/3444915939/

• http://www.flickr.com/photos/wwarby/3296379139/

• http://www.flickr.com/photos/derekgavey/4358797365/

• http://www.flickr.com/photos/mulad/286641998/

top related