Overview:
How to measure your web app
Chang W. Doh
In this talking, we'll discuss
"Measuring"
and some "Optimization"
Why should we do that?
There are many Optimization Checklists on the web.
You already know or Just check them.
But, "You can’t optimize what you can’t measure."
Rendering Performance
60 FPS
= 1000ms / 60 frames
= 16.666ms per frame
Simplify: 60FPS means
"We have only 16.7ms for each frame."
Check: "Rendering time > 16ms"
e.g. Chrome DevTools
- Timeline
- cog > rendering
What makes '> 16ms'
- Repaint Issues
- Heavy CSS3 Effects
- Animation or Transition using heavy property
- Manipulating DOM dynamically
- Insertion / Deletion
-
or Too much hack!
- translateZ(0);
- ...
Example
var styleCache = document.body.style; styleCache.padding = "20px"; // cause of layout, repaint styleCache.border = "10px solid red"; // cause of layout, repaintFinally, <body> triggers layout & repaint.
styleCache.color = "blue"; // cause of repaint styleCache.backgroundColor = "#fad"; // cause of repaint styleCache.fontSize = "2em"; // cause of layout, repaint // new DOM element - cause of layout, repaint document.body.appendChild(document.createTextNode('LetItGo!'));
Further Readings
- How Browsers Works
- Accelerated Rendering in Chrome: The Layer Model
- CSS Paint Time and Page Render Weight
- Avoiding Unnecessary Paints
- Avoiding Unnecessary Paints: Animated GIF Edition
- High Performance Animation
- Antialiasing 101
- HTML5 Techniques for Optimizing Mobile Performance (en)
- Performance profiling with the Timeline (en)
Loading Performance
Fast-loading means
"Make everything less and smaller"
- Minimize HTTP/HTTPS Requests
- Minify Assets: HTML, CSS, Script, Image, ...
- Make HTML within ~14KB
- Reducing Cookie size
- Make AJAX Cacheable and Using GET
- Gzipped
- ...
"and avoid blocking..."
- Put CSS at the Top
- Script at the Bottom
- ...
Check: Page Loading Overhead
PageSpeed Insight
http://goo.gl/cr6YzA
YSlow
http://yslow.org
Optimization Tools
CSS Minifier
JavaScript Minifier
Image Optimizer
Further Readings
Script Performance
Chrome DevTools: Profiler
Catch Peaks:
- Bottleneck Functions?
- Up to you!
- Memory Usage
- A way to Garbage Collection :)
When you're using Canvas,
Canvas Profile will rescue you.
Further Readings
-
Profiling JavaScript Performance (en)
-
ECMA-262-3 in detail [huns.me]
- Static Memory Javascript with Object Pools
- Performance Tips for JavaScript in V8
- Writing Fast, Memory-Efficient JavaScript (en)
- Faster JavaScript Memoization For Improved App. Perf. (en)
- 10 Javascript Performance Boosting Tips (OLD!, en)
- Make the Web Faster Articles (en)
- Optimizing JavaScript code
- Canvas Inspection using Chrome DevTools
-
JavaScript Memory Profiling (en)
Sometimes we need to measure programatically.
Scripting Profiler & Timeline
-
Starting Profiling & Timeline Recording
function startProfiling() {
console.timeline();
console.profile();
}
-
Finishing
function finishProfiling() {
console.timelineEnd();
console.profileEnd();
}
Navigation Timing APIs
High Resolution Time
!msec
1/1000ms!!!
DOMHighResTimeStamp
PerformanceTiming
Representing the moment, in miliseconds!
window.performance.now()
High Resolution Timestamp from 'NavigationStart'
(function() {
var timeout = 3000;
var start = performance.now();
console.log( "Code starts at " + start );
setTimeout( function() {
var end = performance.now();
console.log( "timeout 3sec at " + end );
console.log( "timeout callback delay : " + (end - start - timeout) + "msec" );
}, timeout );
})();
User Timing
performance.mark()
Setting marks
window.performance.mark('ajax_loaded');
performance.measure()
Calculating measurements between marks
window.performance.measure(
'Ajax_Loading',
'ajaxStart',
'ajaxEnd'
);
removing Marks & Measurements
Clearing marks & measurements
window.peformance.clearMarks( 'nameOfMark'); window.performance.clearMeasures('nameOfMeasurement');
window.peformance.clearMarks(); // clear all window.performance.clearMeasures(); // clear all
Retrieving Marks & Measurements
Getting entries
// get 'mark' entries
window.performance.getEntriesByType('mark');
// get 'measure' entries
window.performance.getEntriesByType('measure');
// get entries by name
window.performance.getEntriesByName('name');
Sample Code
XMLHttpRequest
Basic code:
var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
do_something(e.responseText); }
myReq.send();
Adding User-timing
var reqCount = 0;
var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
window.performance.mark('mark_end_xhr');
reqCnt++;
window.performance.measure('measure_xhr_' + reqCnt, 'mark_start_xhr', 'mark_end_xhr');
do_something(e.responseText);
}
window.performance.mark('mark_start_xhr');
myReq.send();
Dump
var items = window.performance.getEntriesByType('measure');
for (var i = 0; i < items.length(); ++i) {
var req = items[i];
console.log('XHR ' + req.name + ' took ' + req.duration + 'ms');
}