Web performance*

Everything You Always Wanted to Know About

Maurizio Lupo @sithmel

(*But Were Afraid to Ask) 

100ms increase in latency = 1% reduction in sales

Amazon

why is it important?

User traffic took months to recover after we deliberately slowed page load times for certain users

Google

why is it important?

For every 1 second improvement in page load time, we saw a 2% conversion increase.

Walmart

why is it important?

why is it important?

SEO: Faster sites get better ranking

why is it important?

Within 0.1 second : feels instant

Within 1 second: fit in the flow of thoughts

Within 10 seconds: keeping the user attention

"Usability engineering" Jacob Nielsen 1993

what to measure

Time to first byte

Time to establish a connection

+

backend time

what to measure

Visual complete / speedindex

what to measure

Visual complete / speedindex

what to measure

App interactive

how to measure it

Syntetic

www.webpagetest.org

Speedcurve

how to measure it

RUM

Browser API: window.performance

Real users monitoring

how to measure it

Important:

Network congestion skews metrics!

Syntethic: take the sample at the same time every day

RUM: watch long period trends

Understanding browser networking: bandwidth

Radius of the pipe

Not an official definition

Understanding browser networking: latency

Length of wires * speed of light + routers * time to route

Not an official definition

Understanding browser networking: latency

3G: 100ms latency

DSL: 5ms latency

Last mile latency:

Geographical latency

San Francisco to NYC carries a minimum 40ms RTT

Understanding browser networking: latency

Improving latency using a CDN

Understanding browser networking: TCP

TCP provides reliable, ordered, and error-checked delivery of a stream of octets between applications running on hosts communicating by an IP network

Understanding browser networking: TCP

If latency is 100ms, opening a connection costs 300ms!

Opening a connection:

Understanding browser networking: TCP

If we sum dns fetch, TCP handshake, tsl negotiation (on a 100ms latency network) it takes 1 second!!!

Understanding browser networking: TCP

Reliable is great but:

Acknowledge reception

Head of line blocking

Congestion control

Understanding browser networking: TCP

Congestion control: slow start

Understanding browser networking: TCP

Congestion control: slow start

Understanding browser networking: TCP

Default opening window size is of 10 packets (almost everywhere)

TCP packet is commonly 1500bytes (MTU)

First 15000 (14KB) are received in a single gulp

Understanding browser networking: TCP

It sucks for short bursty exchanges, especially when latency is big (mobile network for example)

Understanding browser networking: HTTP

Every resource requires a short bursty connections :-(

Understanding browser networking: HTTP

HTTP 1.1 Keepalive: the browser can reuse the same connection :-|

but HTTP head of line blocking

Understanding browser networking: HTTP

Let's open more than one connection for each domain! (usually 8)

:-( Every connection pays the price (slow start)

:-) Parallel download

Understanding browser networking: HTTP

HTTP2 multiplexing

Single connection

Uses binary frames for parallel transmission

HTTP3: http2 over UDP (quic)

What's next?

Understanding browser networking: HTTP

HTTP Features*

*only the ones impacting performances

Understanding browser networking: Caching

cache-control

Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>
Cache-control: immutable 
Cache-control: stale-while-revalidate=<seconds>
Cache-control: stale-if-error=<seconds>

Understanding browser networking: Caching

cache-control

Good practice: cache assets forever and change name when you need a new version

Understanding browser networking: Caching

conditional GET

1 - The server send the Etag header as key of a resource (not the only method)

2 - The browser asks for the same resource sending the Etag received previously

3 - If the resource didn't change the server respond with a 304: Not modified

HTTP/1.1 304 Not Modified
Date: Sat, 09 Feb 2013 16:09:50 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Sat, 02 Feb 2013 12:02:47 GMT
ETag: "c0947-b1-4d0258df1f625"

Understanding browser networking: Caching

Main page is never cached

You can change default behaviour using

Service workers

Understanding browser networking: Compression

HTTP1.1 can optionally compress the data (gzip for example)

Understanding browser networking: Redirects

Very useful but may hurt performance

HTTP/1.1 301 Moved Permanently
Location: http://www.example.org/
Content-Type: text/html
Content-Length: 174

Understanding browser networking: Chunked encoding

In HTTP1.0 resources uses content-length header

You have to wait to reach that length before reading and parsing the resource

From HTTP1.1 you can use transfer-encoding: chunked

Resources can be parsed without waiting to be fully loaded

Very important for HTML and images!!!!

Domain sharding:

Increase number of parallel transmissions

Transmit cookies only from and to a single domain

HTTP2: They are antipatterns!!!!

HTTP2 multiplexing allows parallel transmissions
HPACK header compression avoid sending cookies more than once

HTTP1:

Mythbusting

Inlining:

HTTP2 or 3: use server push

HTTP1: faster because no extra request (no caching)

Mythbusting

Resource bundling:

HTTP2: still important but smaller bundles (more granular caching)

HTTP1: faster and more efficient

Mythbusting

To be continued ....

Parsing and rendering: HTML

HTML can be parsed (and rendered) progressively!*

*HTTP chunked transfer encoding

Parsing and rendering: HTML

Phase 0: preparsing

Super fast scan of the document searching for resources to download

Parsing and rendering: HTML

Phase 1: parsing

The browser builds the DOM. But it stops on blocking resources.

The CSS should be parsed and the CSSOM built before proceding

JS should be executed before proceding

Parsing and rendering: HTML

Phase 2: rendering

The browser paints on the screen. An update of the CSSOM may trigger a repaint. The content too, but it is rare.

Parsing and rendering: HTML

but also of "client hints":

<link rel="dns-prefetch" href="//example.com">
<link rel="preconnect" href="http://css-tricks.com">
<link rel="preload" href="image.png">

Preparser initiate the download of:

<script src="script.js"></script>
<link rel="stylesheet" href="main.css"/>
<img src="image.jpg"/>

Parsing and rendering: CSS

It blocks the parsing and it can't be parsed progressively.

It can be loaded asynchronously using javascript (but it has to be done cleverly to be picked up by the preparser)

<link
  rel="preload"
  href="path/to/mystylesheet.css"
  as="style"
  onload="this.rel='stylesheet'">

Parsing and rendering: CSS

Any resource referenced by the CSS is downloaded only when the rule matches

Example: img tag vs background-image CSS rule

img is always downloaded!

Parsing and rendering: CSS

Minified css is faster to download and parse

Browsers allow link and style tags in the body. It should only block the html underneath

It is also a good idea bundling many css together

but

Parsing and rendering: JS

It blocks the parsing (unless asynchronous) and it can't be parsed progressively.

Parsing and rendering: JS

Loading scripts with javascript:

It can be an antipattern during page load (no preparser involved)

<script>
    var script = document.createElement('script');
    script.src = "//somehost.com/awesome-widget.js";
    document.getElementsByTagName('head')[0].appendChild(script);
</script>

Parsing and rendering: JS

Using defer or async

async: execute as soon as it is ready

defer: execute when html parse is over (it retains the original ordering, but not for inline scripts)

The image is misleading. Download is initiated by the preparser

Parsing and rendering: JS

type="module"

works the same as defer

It enables ESM in the browser (import)

imported modules are bad news for performance, unless you use something like this:

<script type="module">
  import {addTextToBody} from './utils.mjs';

  addTextToBody('Modules are pretty cool.');
</script>
<link rel="modulepreload" href="./utils.mjs">

Parsing and rendering: JS

JS can be minified and bundled

Big bundles takes longer to download/parse/execute

Different scripts depending from each others require to be executed in order (no async attribute)

Parsing and rendering: images

They never block rendering but:

Trigger a repaint if width and height are not specified

Parsing and rendering: images

Progressive JPEG improve speed perception

Parsing and rendering: fonts

They don't block but text is not rendered if font missing

Flash of Invisible Text

Parsing and rendering: fonts

You can wait to have the font and then apply the font

Flash of Unstyled Text

Parsing and rendering: fonts

The default pattern to download the font is terribly inefficient

html -> load css -> load font

better (also avoids foit/fout)

html -> load css (font inline)

html (inline the font)

This works but defeat caching

HTTP2 server push can help

CSS font-display

@font-face {
  font-family: "Open Sans Regular";
  font-weight: 400;
  font-style: normal;
  src: url("fonts/OpenSans-Regular-BasicLatin.woff2") format("woff2");
  font-display: swap;
}

Webkit and Mozilla only (no IE or old edge)

Parsing and rendering: fonts

Note: woff fonts are binary and are subjected to same domain policy

No worries you can use CORS

This is going to cost you an extra round trip!

Mythbusting

One less image

busted

Mythbusting

Client side rendering is good enough

partially busted (not on load)

Mythbusting

Minification is useful

True: even if content is gzipped verbose js and css is longer to decompress and parse

Thanks for listening!

Questions?

Web performance

By Maurizio Lupo

Web performance

What you always wanted to know about

  • 542