Considerations for Performant Web Applications

July 17, 2014
Philippe Le Hégaret
plh@w3.org
@plhw3org

Who Am I?

  • World Wide Web Consortium (W3C)
  • Based in Boston, MA
  • Responsible for frontend Web technologies including HTML, CSS, SVG, WOFF, or Web APIs
  • Would like to have more time for Web Performance, and Testing the Web

Useability

Delay User Reaction
0-100ms Instant
100-300ms Feels sluggish
300-1000ms Machine is working…
1s+ Mental switch
10s+ I'll come back later

Breaking the 1000ms Time to Glass Mobile Barrier

Travel sites

50 performance tricks to make your HTML5 apps and sites faster

Challenges

Two main categories:

Load time
From the user request to "above the fold" (ATF)
User agent speed
Interaction and dynamic changes

Load time

Is the web getting faster?

Network layer

3G
(200 RTT)
4G
(80 RTT)
Control plane (200-2500) (50-100)
DNS lookup 200 80
TCP Connection 200 80
TLS handshake (200-400) (80-160)
HTTP Request 200 80

Breaking the 1000ms Time to Glass Mobile Barrier

Load/Above The Fold Tips

  • Cache your resources (Cache Control)
  • Compress Files in Gzip
  • Reduce HTTP Request by Combining resources (sprites)
  • Avoid HTTP 301 and 40x/50x!
  • Use LocalStorage (but no quota yet)
  • Inline Small CSS and Javascript Resources
  • Try Defer Loading of Javascript

Good to Know

  • Real user monitoring: Navigation, Resource, and User timing
  • HTTP2: multiple-frame streams, header compression, push
  • Future of caching/offline: Service Worker
  • Resource Priorities
  • Resource Hints

Navigating Timing

client-side latency measurements within applications

function onLoad() {
var now = new Date().getTime();
var loadTime =
 now-performance.timing.navigationStart;
alert("User-perceived page loading time: "
      + page_load_time);
}

Navigating Timing

Resource Timing

client-side latency measurements within applications

function onPlay() {
  var resourceList =
     window.performance.getEntriesByType("resource");
  // for all resources in ResourceList
    if (resource.initiatorType == "video") {
      alert("autoplay loading time: " +
       (performance.now() - resourceList[i].fetchStart));
    }
}
video.addEventListener("play", onPlay, false);

Resource Timing

Resource Timing

  • Support for img, video, iframe, css, XHR, etc.
  • default to 150 resources in the buffer (see also setResourceTimingBufferSize)
  • Support for cross-origin resources:
    Timing-Allow-Origin

User Timing

High precision timestamps for web applications

performance.mark("mark_fully_loaded");
doTask1(); // Some developer code
performance.mark("mark_above_the_fold");

var perfEntries = performance.getEntriesByType("mark");
// for all perfEntries, do something

Service Worker

  • navigator.serviceWorker.register(…)
  • App Lifecycle:
    • install, activate, updatefound, reloadpage
    • fetch, evicted, beforeevicted
  • Cache API: add, match, delete, clear

Resource Priorities

lazyload

hints on the download priority of resources in case of network resource contention or visibility

<img src='foo.png' lazyload>

Resource Hints

<link rel="preconnect" href="//cdn.example.com">
<link rel="prefetch" href="thankyou.html" type="text/html">
<link rel="prerender" href="part2.html">

User Agent Speed

60

Bottlenecks

  • Network layer
  • Crowded main thread
  • Memory:
    • DOM
    • Events
  • Drawing: CSS

Speed Tips

  • Avoid CSS Expressions and Filters
  • Keep your DOM simple and be Cautious to DOM Access
  • Take Advantage of HTML5 New Elements and CSS3 New Features
  • Make Sure Font Size is Valid
  • Use HTML5 Web Workers to Enable Multi-threading
  • Use Server-sent Events

What should we do within 16.7ms (60fps)?

  • DOM CRUD
  • Style Calculation
  • Layout
  • Compositing
  • Painting
  • Network requests
  • Image decode
  • Data parsing

5 Myths of Mobile Web Performance

DOM CRUD

function updateImages() {
    images.forEach(function (imgLink) {
    imgEl = document.createElement("img");
    // no img pool!
    imgEl.src = imgLink;
    container.appendChild(imgElt);
 });
 }

Layout

container.childNodes.forEach(function (elt) {
    new_width =
          elt.getBoundingClientRect().width
          + incrementSize;
    elt.style.width = new_width + "px";
    // read/write reflow!
 });

Good to know

  • requestAnimationFrame
  • Page visibility
  • CSS will-change
  • Beacon

requestAnimationFrame

Script-based animations where the user agent is in control of limiting the update rate of the animation

function animate(time) {
  if (!document.hidden) {
    // if visible, draw
    canvas.drawImage(myVideoElement, 0, 0);
  }
  window.requestAnimationFrame(animate);
}
function start() {
  window.requestAnimationFrame(animate);
}

Page Visibility

Determine the current visibility of a page

document.hidden
document.addEventListener('visibilitychange', ...);

function onvisibilitychange() {
  if (document.hidden)
   video.pause();
  else
   video.play();
}

will-change

  • Draft by Tab Aktins
  • Inform the browser of likely changes
  • #container { will-change: opacity; }

Beacon

function unload() {
  return beacon("POST", "/log", analyticsData);
}
  • Use case: send data to a web server before unloading of the document
  • Beacon: non-blocking async transfer of data

What to remember?

  • Real-User Monitoring (RUM)
  • Use tools to figure where the time goes (e.g. Chrome dev tools, Selenium)
  • caniuse.com before using new features

Ideas?

public-web-perf@w3.org

w3.org/2010/webperf