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, 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!'));
Finally, <body> triggers layout & repaint.

Further Readings


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

When you're using Canvas,

Canvas Profile will rescue you.

Further Readings


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');
}

Further Readings


Q&A

Thank you!

Overview: How to measure your WebApp

By cwdoh

Overview: How to measure your WebApp

Basics: Measuring & Optimizing WebApp.

  • 4,664