KEMBAR78
Speed Index, explained! | PDF
Speed Index,
Explained!
Stefan Baumgartner | @ddprrt https://speakerdeck.com/ddprrt/speed-index-explained
The page has to load in under
3 seconds
It works on my machine!
The Dothraki have no word
for “works on my machine”
Use metrics!
loading
document.readyState
loading
DOMContentLoaded
window.onload
window.performance.timing
Speed Index
∫ 1 - visuallycomplete/1000
end
What does this mean?
Visuallycomplete(%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Visuallycomplete(%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Visuallycomplete(%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Visuallycomplete(%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Visuallycomplete(%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Visuallycomplete(%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
So, how’s difference
calculated?
-
=
6% difference
5% difference
this is not good
for the user
this is
Baseline JPEG
10%
Baseline JPEG
10% 50%
Baseline JPEG
10% 50% 100%
Gotcha!
Baseline JPEG
If the image loads gradually over 1 second,
it has a SpeedIndex of 500
Progressive JPEG
10% 50% 100%
Progressive JPEG
The image is already ~77% complete at the
beginning (it’s 23% different)
Progressive JPEG
So if it loads gradually over 1 second,
it has a SpeedIndex of 113
Some tricks …
Webfonts
Modern
browser?
Supports
WOFF?
Font in
Storage
Show
Font
Pre-Render
Modern
browser?
Supports
WOFF?
Font in
Storage
Show
Font
No Font
http://crocodillon.com/blog/non-blocking-web-fonts-using-localstorage
Pre-Render
localStorage
available?
Download
Font
Save in
localStorage
Show
Font
No Font
http://crocodillon.com/blog/non-blocking-web-fonts-using-localstorage
Post-Render
Critical Path CSS
<link rel=“stylesheet” href=“main.css”> blocking!
<link rel=“stylesheet” href=“main.css”> blocking!
<script src=“main.js”> blocking!
<link rel=“stylesheet” href=“main.css”> blocking!
<script src=“main.js”> blocking!
start render
<link rel=“stylesheet” href=“main.css”> blocking!
<script src=“main.js”> blocking!
start render?
<style>
…
</style>
…
<script>
loadCSS(‘main.css’)
</script>
<script src=“main.js”>
<style>
…
</style>
…
<script>
loadCSS(‘main.css’)
</script>
<script src=“main.js”>
<style>
…
</style>
…
<script>
loadCSS(‘main.css’)
</script>
<script src=“main.js”>
I’m not 100% happy with Critical Path CSS
There is still one thing however…
Speed Index should give you an
idea how the user feels when
using your website
… so why is everything
done by a machine
… so why is everything
done by a machine
Let’s do it on the client!
GetRects();
GetRectTimings();
GetFirstPaint();
GetFontTime();
CalculateVisualProgress();
CalculateSpeedIndex();
GetRects();
GetRectTimings();
Get the visible rectangle for the things
we care about.
Get the timings of the resources inside
window.performance.timing
window.performance.timing
getEntriesByType(‘resource’)
GetFirstPaint();
Calculate the timing when the browser
painted first.
// IE and Edge
window.performance.timing.msFirstPaint
// Chropera
var times = window.chrome.loadTimes();
times.firstPaintTime
// Every other browser
var headURLs = {};
var headElements =
doc.getElementsByTagName('head')[0].children;
for (var i = 0; i < headElements.length; i++) {
//get stylesheets and non-async scripts
...
}
// compare with resource timing
var requests =
win.performance.getEntriesByType("resource");
GetFontTime();
Check all font resources and do
resource timings …
CalculateSpeedIndex();
Given the visual progress information,
calculate the speed index.
resource1
firstPaint
resource3
resource4
endofPaintresponseStart
document
font
resource1
firstPaint
resource3
resource4
endofPaintresponseStart
blank, 1 point per ms! gradually
document
font
var now = ruxitApi.now();
var actionId =
ruxitApi.enterAction(
'Speed Index',
'speedIndex',
now - RUMSpeedIndex(),
null);
ruxitApi.leaveAction(actionId, now);
Tell your monitor solution
https://github.com/ddprrt/RUM-SpeedIndex
@ddprrt
@dynatrace
@ruxit

Speed Index, explained!