Building High Performance Web Applications and Sites

Preview:

DESCRIPTION

Learn how to improve your Web application performance in the browser by avoiding common pitfalls in JavaScript, CSS, and HTTP caching techniques.

Citation preview

Building High-Performance Web Applications and SitesJohn HrvatinLead Program ManagerInternet Explorerjohnhrv@microsoft.com

Objectives and Takeaways

Session objective(s) How to make your site faster today Principles to remember when building sites

Key takeawaysSuggestions help in ALL browsersNo magic solutionsConsider maintainability

Acknowledgements

"If I have seen further it is only by standing on the shoulders of giants."

- Isaac Newton

Webpage PerformanceIE8 CPU usage: Top 100 sites

84%

16% Layout, Rendering, Formatting, …

JScript & DOM

Webpage PerformanceIE8 CPU usage: Top AJAX sites

67%

33%Layout, Rendering, Formatting, …

JScript & DOM

Topics

CSS performanceOptimizing symbol resolutionJavascript coding inefficienciesHTTP performance

Topics

CSS performanceOptimizing symbol resolutionJavascript coding inefficienciesHTTP performance

CSS PerformanceMinimize included styles

Unused styles increase download sizeBrowser must parse and match all selectors

Failures are expensive!

CSS PerformanceSimplify selectors

Complex element selectors are slowWhen possible

Use class – or ID-based selectorsMake element selectors as simple as possibleUse child instead of descendent selectorsDo not mix RTL and LTR styles

Minimizing included styles makes this easier

Better in IE8

CSS PerformanceSimplify selectors

table tr td ul li {color: green;}

li#pass {color: green;}

ul li {color: purple;}

ul > li {color: purple;}

CSS PerformanceDon't use expressions

Slow – evaluated frequentlyNot supported in IE8 standards mode!

CSS PerformanceMinimize page re-layouts

Poor user experience as content movesBrowser performs unnecessary work

Minimize Page Re-layouts

demo

CSS PerformanceTakeaways

Minimize included stylesUse less-complicated selectorsDon’t use expressionsMinimize page re-layouts

Simplify!

Topics

CSS PerformanceOptimizing Symbol ResolutionJavaScript Coding InefficienciesHTTP Performance

Optimizing Symbol ResolutionLookup chains

Scopevar name

Prototypeobj.name

Global

Local

Intermediate…

DOM

Instance

Prototype…Cost

Optimizing Symbol ResolutionLocal variablesfunction WorkOnLocalVariable(){localVariable = foo();return ( localVariable + 1 );

}

localVariablelocalVariable

Optimizing Symbol ResolutionLocal variables: Declare them as localfunction WorkOnLocalVariable2(){var localVariable = foo();return ( localVariable + 1 );

}

var localVariablelocalVariable

Optimizing Symbol ResolutionImplicit lookupsfunction BuildUI(){

var elm = document.getElementById('ui');

// Clear existing contentselm.innerHTML = '';

// Generate UIelm.innerHTML += BuildTitle();elm.innerHTML += BuildBody();elm.innerHTML += BuildFooter();

}

+=+=+=

=7

innerHTMLReferences

Optimizing Symbol ResolutionImplicit lookups: Batch changesfunction BuildUI2(){

var elm = document.getElementById('ui');

// Generate UIvar contents = BuildTitle() + BuildBody() + BuildFooter();

// Replace existing contents with UIelm.innerHTML = contents;

}=

1 innerHTMLReference

Optimizing Symbol ResolutionMultiple DOM lookupsfunction CalculateSum(){

// Retrieve Valuesvar lSide = document.body.all.lSide.value;var rSide = document.body.all.rSide.value;

// Generate Resultdocument.body.all.result.value = lSide + rSide;

}

document.body.alldocument.body.all

document.body.all

Optimizing Symbol ResolutionMultiple DOM lookups: Cache referencesfunction CalculateSum2(){

// Cache Element Collectionvar elms = document.body.all;

// Retrieve Valuesvar lSide = elms.lSide.value;var rSide = elms.rSide.value;

// Generate Resultelms.result.value = lSide + rSide;

}

var elms = document.body.all;

elmselms

elms

Optimizing Symbol ResolutionFunction lookupsfunction IterateWorkOverCollection(){

var length = myCollection.length;

for(var i = 0; i < length; i++){

Work(myCollection[i]);}

}

Work

Optimizing Symbol ResolutionFunction lookups: Cache pointersfunction IterateWorkOverCollection2(){

var funcWork = Work;var length = myCollection.length;

for(var i = 0; i < length; i++){

funcWork(myCollection[i]);}

}

var funcWork = Work;

funcWork

Optimizing Symbol ResolutionTakeaways

Watch for expensive name lookupsCache repeated lookups to local variablesOptimize only when neededConsider maintainability

IE8 JavaScript Profiler

demo

Visual Studio 2010 Profiler

New summary page depicting performance bottlenecks

Visual Studio 2010 Profiler

Ajax/JScript Profiling is now integrated with Load Test Performance Sessions

See a demo at http://channel9.msdn.com/pdc2008/TL24/

Topics

CSS Performance ConsiderationsOptimizing Symbol ResolutionJavaScript Coding InefficienciesHTTP Performance

JavaScript Coding InefficienciesParsing JSON

With evalRequires new script execution context (slow)Less secure

With custom libraryMore secure, but even slower

JavaScript Coding InefficienciesParsing JSON: Use the native methods

Built-in JSON methodsJSON.parse()JSON.stringify()toJSON() on prototypes of Date, Number, String, and Boolean

Native equivalent of the reference parser from http://wiki.ecmascript.org/doku.php?id=es3.1:json_support As safe as http://www.json.org/json_parser.js

but faster

New in IE8

JSON Performance

demo

JavaScript Coding InefficienciesThe switch statementswitch(option){

case 1: …case 2: …case 3: ……case 1000: …

}case 1000:

JavaScript Coding InefficienciesThe switch statement: Use a lookup table

var lookup = {1: function(){…}2: function(){…}3: function(){…}…1000: function(){…}

}

try { lookup [option]();} catch(e) { // Default operation}

lookup[option]();

JavaScript Coding InefficienciesProperty access methodsvar property = foo();

this.getProperty = function(){ return property;}

this.setProperty = function(value){ property = value;}

JavaScript Coding InefficienciesProperty access methods: Use direct accessthis.property = foo();

JavaScript Coding InefficienciesProperty access methods

Instantiating DOM functions

Problems: Costly (in CPU cycles)Consider: Caching function pointers, batching changesWhy: Generic script interface

Better in IE8

JavaScript Coding InefficienciesMinimize DOM interaction

Scopevar name

Prototypeobj.name

Global

Local

Intermediate…

DOM

Instance

Prototype…Cost

JavaScript Coding InefficienciesMinimize DOM interaction

Scopevar name

Prototypeobj.name

Global

Local

Intermediate…

DOM

Instance

Prototype…Cost

Better in IE8

Trident (MSHTML)

JScript Engine

JavaScript Coding InefficienciesMinimize DOM interaction

DOM

JavaScript Coding InefficienciesMinimize DOM interaction

function getElementsByClassName(className, node, tag) {      …      var elements = node.getElementsByTagName(tag);      var pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");      for(var i = 0, j = 0; i < elements.length; i++) {            if (pattern.test(elements[i].className)) {                  classElements[j] = elements[i]; 

j++;            }      }      return classElements;}

var elements = node.getElementsByTagName(tag);

elements.lengthelements[i]

JavaScript Coding InefficienciesMinimize DOM interaction

function getElementsByClassName(className, node, tag) { …      var results = node.getElementsByTagName(tag);      var elements = new Array(results.length);      while (length--) elements[length] = results[length];      var pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");      for(var i = 0, j = 0; i < elements.length; i++) {            if (pattern.test(elements[i].className)) {                  classElements.push(results[i]);    j++;   }      }  return classElements; }

elements.length

elements[i]

var elements = new Array(results.length);while (length--) elements[length] = results[length];

JavaScript Coding InefficienciesSmart use of DOM methods

Smart use of DOM methods can minimize overall DOM interaction

nextSibling() better than childNodes[i]querySelectorAll() better for element groups

JavaScript Coding InefficienciesSmart use of DOM methodsfunction LoopChildren(elm) {

var nodes = elm.childNodes;var length = nodes.length;

for(var i = 0; i < length; i++){

var node = nodes[i];…

} }

nodes[i];

JavaScript Coding InefficienciesSmart use of DOM methodsfunction LoopChildren2(elm) {

var node = elm.firstChild;

while(node != null){

…node = node.nextSibling;

}}

node.nextSibling;

JavaScript Coding InefficienciesUse querySelectorAll for groups

function doValidation2(){

// Retrieve the required elements by using Selectors // Selects all form fields with 'required' classes var reqs = document.querySelectorAll(".required"); // Set the flag to false by default var missingRequiredField = false;

// Validate that the form data is not empty for (var i = 0; i < reqs.length; i++) {

if (reqs[i].value == "")missingRequiredField = true;

} }

New in IE8

document.querySelectorAll

JavaScript Coding InefficienciesTakeaways

Use the native JSON objectTurn large switch statements into lookupsAvoid property access methodsMinimize DOM interactionUse querySelectorAll for groups

Optimize only when neededConsider maintainability

Topics

CSS PerformanceOptimizing Symbol ResolutionJavaScript Coding InefficienciesHTTP Performance

HTTP PerformanceTypical visit

Request from server/cacheJavaScriptCSSImagesHTML

In browserLayoutExecute scriptAdditional downloads

HTTP PerformanceHTTP compression: Use it

RequestGET / HTTP/1.1Accept: */*Accept-Language: en-usUA-CPU: x86Accept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 (compatible;

MSIE 7.0)Host: www.live.com

ResponseHTTP/1.1 200 OKContent-Length: 3479Expires: -1Date: Tue, 24 Apr 2007 21:30:46 GMTContent-Type: text/html; charset=utf-

8Pragma: no-cacheContent-Encoding: gzip

Accept-Encoding: gzip, deflate

Content-Encoding: gzip

HTTP PerformanceScaled images

<html><head>

<title>Test</title></head><body>

…<!-- icon.gif dimensions: 500 x 400 --><img src="icon.gif" width="50" height="40" />…

</body></html>

width="50" height="40"500 x 400

HTTP PerformanceScaled images: Use sized copies

<html><head>

<title>Test</title></head><body>

…<!-- icon2.gif dimensions: 50 x 40 --><img src="icon2.gif" width="50" height="40" />…

</body></html>

width="50" height="40"50 x 40

HTTP PerformanceFile linking

<html><head>

<title>Test</title><script src= type="text/javascript"></script>

</head><body>

…</body>

</html>

<script src=“1.js” … ></script>

<script src=“2.js” … ></script>

<link href=“1.css” … ></link>

<link href=“2.css” … ></link>

HTTP PerformanceFile linking: Link one CSS file and one JS file

<html><head>

<title>Test</title><script type="text/javascript"></script>

</head><body>

…</body>

</html>

<script src=“1+2.js” … ></script>

<link href=“1+2.css” … ></link>

HTTP PerformanceMany images

<html><head>

<title>Test</title></head><body>

…<img src="a.gif" /> Item 1<img src="b.gif" /> Item 2…

</body></html>

<img src="a.gif" /><img src="b.gif" />

HTTP PerformanceMany images: Combine and mask (sprites)

<head><title>Test</title><style type="text/css">

.a, .b { width: 10; height: 10 }

.a, .b { background-image: "abc.gif" }

.a { background-position: 0 0 }

.b { background-position: 0 -10 }</style>

</head><body>

…<div class="a"></div> Item 1<div class="b"></div> Item 2…

</body>

<div class="a"></div><div class="b"></div>

.a, .b { width: 10; height: 10 }

.a, .b { background-image: "abc.gif" }

.a { background-position: 0 0 }

.b { background-position: 0 -10 }

HTTP PerformanceRepeat visits

Conditional HTTP requestsPlain HTTP request

Pragma: no-cache

Time conditionalIf-modified-since: date,time

Provide cacheable contentTime conditional

Expires: date,timeMax-age: #seconds

Request

HTTP PerformanceRepeat visits: Use conditional requests

HTTP/1.1 304 Not ModifiedContent-Type: image/jpegLast-Modified:

Wed, 22 Feb 2006 04:15:54 GMT

GET /images/banner.jpg HTTP/1.1Host: www.microsoft.comIf-Modified-Since:

Wed, 22 Feb 2006 04:15:54 GMT

Response

Request

HTTP PerformanceRepeat visits: Provide cacheable content

GET /images/banner.jpg HTTP/1.1

HTTP/1.1 200 OKContent-Type: image/jpegExpires: Fri, 12 Jun 2009 02:50:50

GMT

GET /images/banner.jpg HTTP/1.1Host: www.microsoft.com

Response

Request Response

No response:Request serviced from cache

HTTP PerformanceScript blocking

<html><head>

<title>Test</title><script type="text/javascript"></script>

</head><body>

…</body>

</html>

<script src=“1+2.js” … ></script>

Better in IE8

HTTP PerformanceScript blocking

<html><head>

<title>Test</title></head><body>

</body></html>

<script src=“1+2.js” … ></script>

HTTP PerformanceTools

FiddlerInspect network trafficwww.fiddler2.com

neXpert Fiddler plug-in to aid performance testinghttp://www.fiddler2.com/fiddler2/addons/neXpert.asp

NEW!!!

HTTP PerformanceTakeaways

Reduce the number of requestsCombine external scripts, styles, and imagesUse caching

Reduce the size of requestsUse HTTP compressionUse conditional requests

Avoid blocking factorsPut script at end of HTML

Summary

Identify the performance bottleneckNetwork/bandwidth – using FiddlerJavaScript – using developer toolsAggressive DOM access – using developer tools

Reduce, simplify, re-factorReduce the bytes sent between the client/serverSimplify your code to avoid costly JavaScript and CSS constructsCache DOM properties and function pointers

Please Complete an Evaluation FormYour feedback is important!

Evaluation forms can be found on each chairTemp Staff at the back of the room have additional evaluation form copies

© 2009 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.

The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions,

it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.