690 likes | 801 Views
Building High-Performance Web Applications and Sites. John Hrvatin Lead Program Manager Internet Explorer johnhrv@microsoft.com. Objectives and Takeaways. Session objective(s) How to make your site faster today Principles to remember when building sites Key takeaways
E N D
Building High-Performance Web Applications and Sites John Hrvatin Lead Program Manager Internet Explorer johnhrv@microsoft.com
Objectives and Takeaways • Session objective(s) • How to make your site faster today • Principles to remember when building sites • Key takeaways • Suggestions help in ALL browsers • No magic solutions • Consider maintainability
Acknowledgements "If I have seen further it is only by standing on the shoulders of giants." - Isaac Newton
Topics • CSS performance • Optimizing symbol resolution • Javascript coding inefficiencies • HTTP performance
Topics • CSS performance • Optimizing symbol resolution • Javascript coding inefficiencies • HTTP performance
CSS PerformanceMinimize included styles • Unused styles increase download size • Browser must parse and match all selectors • Failures are expensive!
CSS PerformanceSimplify selectors • Complex element selectors are slow • When possible • Use class – or ID-based selectors • Make element selectors as simple as possible • Use child instead of descendent selectors • Do not mix RTL and LTR styles • Minimizing included styles makes this easier Better in IE8
CSS PerformanceSimplify selectors • table tr td ulli {color: green;} • li#pass {color: green;} • ulli {color: purple;} • ul > li {color: purple;}
CSS PerformanceDon't use expressions • Slow – evaluated frequently • Not supported in IE8 standards mode!
CSS PerformanceMinimize page re-layouts • Poor user experience as content moves • Browser performs unnecessary work
demo Minimize Page Re-layouts
CSS PerformanceTakeaways • Minimize included styles • Use less-complicated selectors • Don’t use expressions • Minimize page re-layouts • Simplify!
Topics • CSS Performance • Optimizing Symbol Resolution • JavaScript Coding Inefficiencies • HTTP Performance
Optimizing Symbol ResolutionLookup chains • Scope • var name • Prototype • obj.name Cost DOM Global Prototype … Intermediate … Instance Local
Optimizing Symbol ResolutionLocal variables • function WorkOnLocalVariable(){ • localVariable = foo(); • return ( localVariable + 1 ); • } localVariable localVariable
Optimizing Symbol ResolutionLocal variables: Declare them as local • function WorkOnLocalVariable2(){ • var localVariable = foo(); • return ( localVariable + 1 ); • } varlocalVariable localVariable
Optimizing Symbol ResolutionImplicit lookups • function BuildUI(){ • var elm = document.getElementById('ui'); • // Clear existing contentselm.innerHTML = ''; • // Generate UI • elm.innerHTML += BuildTitle();elm.innerHTML += BuildBody();elm.innerHTML += BuildFooter(); • } 7 innerHTML References = += += +=
Optimizing Symbol ResolutionImplicit lookups: Batch changes • function BuildUI2(){ • var elm = document.getElementById('ui'); • // Generate UI • var contents = BuildTitle() • + BuildBody() • + BuildFooter(); • // Replace existing contents with UIelm.innerHTML = contents; • } 1 innerHTML Reference =
Optimizing Symbol ResolutionMultiple DOM lookups • function CalculateSum(){ • // Retrieve Values • var lSide = document.body.all.lSide.value;var rSide = document.body.all.rSide.value; • // Generate Resultdocument.body.all.result.value = lSide • + rSide; • } document.body.all document.body.all document.body.all
Optimizing Symbol ResolutionMultiple DOM lookups: Cache references • function CalculateSum2(){ • // Cache Element Collection • var elms = document.body.all; • // Retrieve Values • var lSide = elms.lSide.value;var rSide = elms.rSide.value; • // Generate Resultelms.result.value = lSide + rSide; • } var elms = document.body.all; elms elms elms
Optimizing Symbol ResolutionFunction lookups • function IterateWorkOverCollection(){ • var length = myCollection.length; • for(var i = 0; i < length; i++){ • Work(myCollection[i]); • } • } Work
Optimizing Symbol ResolutionFunction lookups: Cache pointers • function IterateWorkOverCollection2(){ • var funcWork = Work; • var length = myCollection.length; • for(var i = 0; i < length; i++){ • funcWork(myCollection[i]); • } • } varfuncWork = Work; funcWork
Optimizing Symbol ResolutionTakeaways • Watch for expensive name lookups • Cache repeated lookups to local variables • Optimize only when needed • Consider maintainability
demo IE8 JavaScript Profiler
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 Considerations • Optimizing Symbol Resolution • JavaScript Coding Inefficiencies • HTTP Performance
JavaScript Coding InefficienciesParsing JSON • With eval • Requires new script execution context (slow) • Less secure • With custom library • More secure, but even slower
JavaScript Coding InefficienciesParsing JSON: Use the native methods New in IE8 • Built-in JSON methods • JSON.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.jsbut faster
demo JSON Performance
JavaScript Coding InefficienciesThe switch statement • switch(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 methods • var property = foo(); • this.getProperty = function() • { • return property; • } • this.setProperty = function(value) • { • property = value; • }
JavaScript Coding InefficienciesProperty access methods: Use direct access • this.property = foo();
JavaScript Coding InefficienciesProperty access methods • Instantiating DOM functions • Problems: Costly (in CPU cycles) • Consider: Caching function pointers, batching changes • Why: Generic script interface Better in IE8
JavaScript Coding InefficienciesMinimize DOM interaction • Scope • var name • Prototype • obj.name Cost DOM Global Prototype … Intermediate … Instance Local
JavaScript Coding InefficienciesMinimize DOM interaction Better in IE8 • Scope • var name • Prototype • obj.name Cost DOM Global Prototype … Intermediate … Instance Local
JavaScript Coding InefficienciesMinimize DOM interaction Trident (MSHTML) DOM JScript Engine
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.length elements[i]
JavaScript Coding InefficienciesMinimizeDOM 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; } • var elements = new Array(results.length); • while (length--) elements[length] = results[length]; elements.length elements[i]
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 methods function 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 methods function LoopChildren2(elm) { • var node = elm.firstChild; • while(node != null) • { • … • node = node.nextSibling; • } • } node.nextSibling;
JavaScript Coding InefficienciesUse querySelectorAll for groups New in IE8 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; • } } document.querySelectorAll
JavaScript Coding InefficienciesTakeaways • Use the native JSON object • Turn large switch statements into lookups • Avoid property access methods • Minimize DOM interaction • Use querySelectorAll for groups • Optimize only when needed • Consider maintainability