Download - From Zero to Hero – Web Performance
Basti• Sebastian Springer
• from Munich
• work @ MaibornWolff
• https://github.com/sspringer82
• @basti_springer
• JavaScript Developer
Caching values
const arr = ['Peter', 'Paul', 'Mary'];for (let i = 0; i < arr.length; i++) { console.log(arr[i]);} // 1.734msconst arr = ['Peter', 'Paul', 'Mary'];for (let i = 0, j = arr.length; i < j; i++) { console.log(arr[i]);} // 1.699ms
Optimisations of the engineDieter Schütz / pixelio.de
Remember your optimisations?
const arr = ['Peter', 'Paul', 'Mary'];for (let i = 0; i < arr.length; i++) { console.log(arr[i]);} // 1.734msfor (let i = 0; i < arr.length; i++) { console.log(arr[i]);} // 0.079ms
2nd run
Optimisation
Optimising your JavaScript code is not your problem. Most of the work is done by the engine itself. You just have to know
how your environment works.
Optimising your code is pointless, as it only reduces readability.
Keep the big picture in mind!
What matters?
The time until your user sees the first information and is able to interact with
your application.
Critical Rendering Path
Thorben Wengert / pixelio.de
Critical Rendering Path
Process between receiving HTML, CSS and JS files and rendering the information in the users browser.
Critical Rendering Path
1. Processing HTML -> DOM
2. Processing CSS -> CSSOM
3. Building the Render Tree
4. Rendering
Processing HTML
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model
https://creativecommons.org/licenses/by/3.0/
Processing CSS
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model
https://creativecommons.org/licenses/by/3.0/
Building the Render Tree
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model
https://creativecommons.org/licenses/by/3.0/
Measuring
Downloading files
A browser only has a limited number of parallel connections to a server.
Firefox: 6 Chrome: 6
Internet Explorer: 13
Download
Deliver only a few small files
CSS: Preprocessors + Minifier JS: Modulesystem + Minifier
Images: Sprites
Download
Service Worker
Service Worker
Separate browser process that act as a proxy between browser and server. A service worker is able to intercept and
answer a request to a server directly. Service workers are able to speed up applications and make
them available offline.
Service Worker
Render Blocking CSS
Receiving CSS files is blocking the render process of a page.
The more CSS is used, the longer the blocking takes.
Render Blocking CSS
Do not use @import in your CSS - better pack everything in just one file.
Use as little CSS as possible in the Critical Rendering Path. The media attribute helps to reduce the processed CSS.
Last resort solution: inline CSS
Render Blocking JavaScript
All of the JavaScript that is not necessary for the initial page load can be loaded at a later time.
Generating a script tag at the load event.
or lazy loading with a module loader such as webpack
App Shell Architecture
Minimal HTML, CSS and JavaScript as foundation for the User Interface.
• loads fast • can be cached • shows dynamic content
The user is moving within the application. The application stays open in the browser over a long period of time.
Data is loaded over the whole lifecycle of the application.
There are no additional page loads
Application state is stored in memory.
Object representations are stored in memory.
Memory consumption increases over time.
JavaScript Engines
The competition between browser manufacturers brought up some highly optimised engines.
JavaScript Engines
• Google Chrome: V8
• Mozilla Firefox: SpiderMonkey
• Microsoft Internet Explorer: Chakra
• Apple Safari: Nitro
Example: V8
V8 is a JavaScript engine specifically designed for fast execution of large JavaScript applications.
Hidden Classes
For property access usually one big directory is used. To speed up property access hidden classes per object is
used. The hidden class points to the location of a property in memory.
function Point(x, y) { this.x = x; this.y = y;} var p1 = new Point(2, 4);
function Point(x, y) { this.x = x; this.y = y;} var p1 = new Point(2, 4);
p1
Hidden Class C0
function Point(x, y) { this.x = x; this.y = y;} var p1 = new Point(2, 4);
p1
Hidden Class C0
x: offset 0
Hidden Class C0 Property x added -
use C1.
Hidden Class C1
x: offset 0
function Point(x, y) { this.x = x; this.y = y;} var p1 = new Point(2, 4);
p1
Hidden Class C2
x: offset 0 y: offset 1
Hidden Class C0
Property y added - use C2
Hidden Classes
Additional Object of the same type share the same hidden classes and their transitions.
JIT Compiler
JIT Compiler
V8 compiles JavaScript code to machine code at first run.
The engine tries to guess the according hidden classes and patches the machine code. All future usages of the object are
using the same hidden classes. If there’s a mismatch the engine corrects it accordingly.
JIT Compiler
# ebx = the point object cmp [ebx,<hidden class offset>],<cached hidden class> jne <inline cache miss> mov eax,[ebx, <cached x offset>]
p1.x
Garbage Collection
V8 does memory management when the processor is idle to reduce impact to the application.
The Garbage Collector regularly checks used memory and frees unused memory.
Unused means: No more references to the object in memory.
Garbage Collection
new assigned memory
older objects
Memory structure
Most objects only have a short lifecycle
young generation
old generation
new assigned memory
Garbage CollectionObject1
Object2Object3
Object1
Object2Object3
older objects
Object1
As soon as one block is full, every used object is moved to another block. The
old block is emptied afterwards. If an object is moved for the second time
it’s moved to old generation space.
Garbage Collection
To speed up GC, you should try to move as few objects as possible.
Garbage CollectionWhere the young generation space is cleaned up with a
scavenge algorithm which is using a lot of memory, the old generation space is cleaned up with a mark-and-sweep
collector.
Active objects are marked, all unmarked objects are deleted.
A complete run takes 100 ms. Your application is stopped for this time. V8 is able to do this process in increments which
take 5ms each.
JavaScript Engines
A lot optimisations of a browser engine only work for structures which are used multiple times.
Repaints & Reflows
Repaint: Browser checks all elements for visibility, color, measurements and other visual properties.
Repaints & Reflows
Reflow: The browser recalculates the layout of the page. A reflow might cause reflows for other elements (children, or
siblings). After a reflow a repaint is triggered.
Trigger for reflows• Addition, removal or update of a DOM element
• Change of the content of a page
• Movement of an element
• Animations
• Reading measurements
• Change of CSS property
• Change of the class name of an element
• Addition or removal of a stylesheet
• Change of window size
• Scrolling
Omitting reflows• Omit series of single style changes
• Collect operations in CSS classes
• Detach elements, change them, attach them to the DOM
• Cache styles in JS variables
• Use fixed positions for animations
Profiling
Rendering: Recalculate Layout
Painting: Display the page
Memory Leaks
Memory leaks slow down an application, cause crashes and increase latency.
A memory leak occurs, if memory is not used any more but not freed by the GC.
Memory Leaks
Global variables
forgotten intervals
DOM elements in JS variables
Closures
Memory Leaksvar theThing = null; var replaceThing = function () { var originalThing = theThing; var unused = function () { if (originalThing) console.log("hi"); }; theThing = { longStr: new Array(1000000).join('*'), someMethod: function () { console.log(someMessage); } };}; setInterval(replaceThing, 100);
http://info.meteor.com/blog/an-interesting-kind-of-javascript-memory-leak
Memory Leaks
Memory fills up
JavaScript Animations
If you’re doing animations with JavaScript, you periodically change certain CSS properties of an object.
At 60 frames per second an animation is looking fluid.
function move(elem, to) { var left = 0; function frame() { left++; elem.style.left = left + 'px'; if (left === to) { clearInterval(id) } } var id = setInterval(frame, 10); } document.getElementById('outer').onclick = function () { move(this.children[0], 500);};
<div id="outer" class="outer"> <div id="inner" class="inner"></div> </div>
HTML
CSS
Disadvantages
JavaScript is executed in the CPU and shares this resource with a lot of other processes.
GC cycles can slow performance further down.
If your system is under load, animations are not fluid anymore.
Alternative
Web Animations API
https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API
Control your animations with JavaScript
Is not supported by all browsers yet.
CSS animations
CSS animations
CSS animations are calculated by the GPU and don’t create load on the CPU.
CSS animations are more fluid than their JS counterpart.
Your browser is able to optimise your CSS animations.
document.getElementById('outer').onclick = function () { this.children[0].className += ' move'; };
#inner { transition: left 5s linear; } .move { left: 500px; }
<div id="outer" class="outer"> <div id="inner" class="inner"></div> </div>
HTML
CSS
JS
CSS animations
If transitions are not enough, you can control animations with @keyframes.
There are a lot of generators online (e.g. http://cssanimate.com)
Prefetching
Prefetching
Your browser prefetches certain pages in order to load faster if a user is browsing to that page. All browsers except Safari
support this attribute.
Chrome (49), IE (not Edge) and Opera are supporting prerendering, where your browser prerenders the page to
further speed up display of a page.
<link rel="prefetch" href="users.html" />
How do others handle performance?
Performance @facebook
A very good example of web performance tuning is the react library. The virtual DOM provides an in memory structure on
which all the changes are performed. Afterwards all necessary operations are calculated and performed in an optimised
operation to the actual DOM.
More performance @facebook
To further improve performance, react introduces a full rewrite of the reconciliation algorithm with version 16. In this version
there are different schedulers which determine when a change should be performed.
Questions?
Rainer Sturm / pixelio.de
CONTACT
Sebastian Springer [email protected]
MaibornWolff GmbH Theresienhöhe 13 80339 München
@basti_springer
https://github.com/sspringer82