[CodeDaze 2016] Every Millisecond Counts: Performance & UX

Fee39f0c0ffb29d9ac21607ed188be6b?s=47 Davey Shafik
September 15, 2016

[CodeDaze 2016] Every Millisecond Counts: Performance & UX

How do you lose 900 million dollars in 100ms? Or 8 million visits in just 4/10 of a second?

User expectations are higher than ever when it comes to web performance, so much so that we've created an entirely new application architecture just to make it feel like our websites are faster than they actually are.

This talk will look at how we can improve our users experience at any scale through performance optimizations at every layer of the stack, from backend to browser.

Fee39f0c0ffb29d9ac21607ed188be6b?s=128

Davey Shafik

September 15, 2016
Tweet

Transcript

  1. E V E R Y M I L L I

    S E CO N D CO U N TS P E R F O R M A N C E A N D U S E R E X P E R I E N C E
  2. D AV E Y S H A F I K

    • Developer • Author • Open Source Contributor • Release Manager for PHP 7.1 • @dshafik
  3. http://developer.akamai.com

  4. Let’s start a conversation about mental health in tech mhprompt.org

  5. W H Y P E R FO R M A

    N C E M AT T E RS CC-BY-ND 2.0: Raymond June
  6. A M A ZO N CC-BY 2.0: Thomas Shahan

  7. LO S E S 1 % O F R E

    V E N U E P E R 1 0 0 M S S O U R C E : H T T P : / / R A D A R . O R E I L LY. C O M / 2 0 0 8 / 0 8 / R A D A R - T H E M E - W E B - O P S . H T M L
  8. $ 1 , 0 7 0 , 0 0 0

    , 0 0 0 2 0 1 5
  9. 1 5 ¢ F O R E V E R

    Y S I N G L E P E RS O N O N E A RT H 2 0 1 5
  10. $ 3 . 3 2 P E R US C

    I T I Z E N 2 0 1 5
  11. R E M I N D E R : P

    E R 1 0 0 M S S LO W E R !
  12. G O O G L E CC-BY: Robert Scoble

  13. 0 . 5 S S LO W E R =

    2 0 % L E SS S E A R C H E S S O U R C E : H T T P : / / G L I N D E N . B L O G S P O T. C O M / 2 0 0 6 / 1 1 / M A R I S S A - M A Y E R - A T- W E B - 2 0 . H T M L
  14. B I N G CC-BY-SA 2.0: badgreeb RECORDS

  15. 2 S S LO W E R = - 4

    . 3 % R E V E N U E / U S E R S O U R C E : H T T P : / / V E L O C I T Y C O N F. C O M / V E L O C I T Y 2 0 0 9 / P U B L I C / S C H E D U L E / D E TA I L / 8 5 2 3
  16. G Q CC-BY 2.0: BIAU Guillaume

  17. CU T LOA D T I M E BY 8

    0 % : T R A F F I C + 8 0 % & T I M E S P E N T + 3 2 % S O U R C E : H T T P : / / D I G I D AY. CO M / P U B L I S H E RS /G Q - CO M - CU T- PA G E - LOA D -T I M E - 8 0 - P E R C E N T/
  18. M O R E

  19. • WALMART: 1s improvement = 2% increase in conversions •

    ETSY: +160KB of images mobile site = 12% increase in bounce rate • STAPLES: 1s improvement = 10% increase in conversions S O U R C E : H T T P : / / W W W. S L I D E S H A R E . N E T/C L I F FC R O C K E R / V E LO C I TY- N Y- H O W-TO - M E A S U R E - R E V E N U E - I N - M I L L I S E CO N D S S O U R C E : H T T P : / / R A D A R . O R E I L LY. CO M / 2 0 1 4 / 0 1 / W E B - P E R FO R M A N C E - I S - US E R- E X P E R I E N C E . H T M L S O U R C E : H T T P : / / W W W. S L I D E S H A R E . N E T/ D E VO N AU E RS W A L D/ W A L M A RT- PA G E S P E E D S L I D E
  20. CO N C LUS I O N

  21. U S E RS C A N P E R

    C E I V E T I N Y C H A N G E S I N P E R FO R M A N C E A S L I T T L E A S 1 4 M S
  22. S LO W E R S I T E S

    M A K E CUSTO M E RS L E SS H A P P Y
  23. L E SS H A P PY = P O

    O R US E R E X P E R I E N C E
  24. YO U P R O B A B LY N

    OT I C E D I T YO U RS E L F…
  25. 1 0 S E CO N D S I S

    A N E T E R N I TY
  26. M O B I L E : 5 3 %

    B O U N C E A F T E R 3 S S O U R C E : H T T P S : / / W W W. S OA STA . CO M / B LO G /G O O G L E - M O B I L E -W E B - P E R F O R M A N C E -ST U DY/
  27. W H O I S R E S P O

    N S I B L E FO R P E R FO R M A N C E ? CC-BY 2.0: davetoaster
  28. E V E R YO N E ! CC-BY 2.0:

    James Cridland
  29. E V E R YO N E ! • Designers

    • Sysadmins/Devops • Backend Developers • Frontend Developers • Browser Vendors
  30. W H AT M A K E S A W

    E B PA G E ? CC-BY-SA 2.0: Susanne Nilsson
  31. TOTA L PA G E W E I G H

    T D I ST R I B U T I O N HTTP Archive – September 2015 http://httparchive.org/trends.php Fonts 5% CSS 3% JS 17% HTML 3% Images 63% Other 9%
  32. TOTA L PA G E W E I G H

    T ( M B ) 0-1MB 1-2MB 2-3MB 3-4MB 4-5MB 5-6MB 6-8MB 3% 2% 4% 8% 15% 28% 36%
  33. TOTA L R E Q U E STS P E

    R PA G E 1-25 26-50 51-75 76-100 101-125 126-150 > 150 15% 8% 12% 16% 18% 16% 11%
  34. D E S I G N E RS CC-BY 2.0:

    Cliff Hutson
  35. CO M P R E SS YO U R I

    M AG E S
  36. CO M P R E SS YO U R I

    M AG E S ( O R D E V E LO P E RS W I L L D O I T FO R YO U ! )
  37. SYS A D M I N S / D E

    V O P S CC-BY-SA 2.0: Bjorn Watland
  38. E N A B L E H T T P/

    2
  39. L E T ’ S E N C R Y

    PT ! CC-BY: Jason Baker
  40. L E TS E N C R Y PT. O

    R G Attribution
  41. L E TS E N C R Y PT. O

    R G • Free (as in beer) • Automatic • Secure • Transparent • Open • Cooperative
  42. U S E T H E C LO U D

    TO S C A L E B A S E D 
 O N P E R C E I V E D P E R F O R M A N C E CC-BY 2.0: Steve Jurvetson
  43. S C A L E D B A S E

    D O N P E R C E I V E D P E R F O R M A N C E • Resource usage doesn’t tell you the whole story • Use SpeedIndex scores as an additional metric to determine scaling thresholds • Use marcelduran / webpagetest-api (node)
  44. var WebPageTest = require('webpagetest'); var http = require('http'); var wpt

    = new WebPageTest('www.webpagetest.org', 'KEY HERE'); wpt.runTest('https://daveyshafik.com', {pageSpeed: true}, function(err, data) { console.log("Test results at: " + data.data.jsonUrl); checkResponse(data.data.jsonUrl); }); function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = ''; response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  45. var WebPageTest = require('webpagetest'); var http = require('http'); var wpt

    = new WebPageTest('www.webpagetest.org', 'KEY HERE'); wpt.runTest('https://daveyshafik.com', {pageSpeed: true}, function(err, data) { console.log("Test results at: " + data.data.jsonUrl); checkResponse(data.data.jsonUrl); }); function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = ''; response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData);
  46. var WebPageTest = require('webpagetest'); var http = require('http'); var wpt

    = new WebPageTest('www.webpagetest.org', 'KEY HERE'); wpt.runTest('https://daveyshafik.com', {pageSpeed: true}, function(err, data) { console.log("Test results at: " + data.data.jsonUrl); checkResponse(data.data.jsonUrl); }); function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = ''; response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData);
  47. var WebPageTest = require('webpagetest'); var http = require('http'); var wpt

    = new WebPageTest('www.webpagetest.org', 'KEY HERE'); wpt.runTest('https://daveyshafik.com', {pageSpeed: true}, function(err, data) { console.log("Test results at: " + data.data.jsonUrl); checkResponse(data.data.jsonUrl); }); function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = ''; response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData);
  48. var WebPageTest = require('webpagetest'); var http = require('http'); var wpt

    = new WebPageTest('www.webpagetest.org', 'KEY HERE'); wpt.runTest('https://daveyshafik.com', {pageSpeed: true}, function(err, data) { console.log("Test results at: " + data.data.jsonUrl); checkResponse(data.data.jsonUrl); }); function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = ''; response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData);
  49. function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = '';

    response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  50. function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = '';

    response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  51. function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = '';

    response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  52. function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = '';

    response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  53. function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = '';

    response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  54. function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = '';

    response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  55. function checkResponse(reportUrl) { http.get(reportUrl, function(response) { var responseData = '';

    response.on('data', function(data) { responseData += data; }); response.on('end', function() { var data = JSON.parse(responseData); if (data.statusCode == 200) { console.log("First view: " + data.data.average.firstView.SpeedIndex); console.log("Repeat view: " + data.data.average.repeatView.SpeedIndex); } else { console.log(data.statusText); setTimeout(function () { checkResponse(reportUrl); }, 5000); } }); }); }
  56. None
  57. B A C K E N D D E V

    E LO P E RS CC-BY 2.0: Bobo Boom
  58. C A C H E A G G R E

    S S I V E LY CC-BY: Travis Wise
  59. D ATA B A S E C AC H I

    N G
  60. D ATA B A S E C AC H I

    N G • Memcache • Cassandra
  61. F U L L PAG E C AC H I

    N G
  62. F U L L PA G E C A C

    H I N G • Memcache • Cassandra • Varnish • Squid
  63. E D G E S I D E I N

    C LU D E S ( E S I )
  64. E D G E S I D E I N

    C LU D E S • Created by Akamai (and some other companies) • Partially supported by Varnish, Squid, and others • Uses special HTML tags to cache fragments of pages differently than rest of the page • e.g. no caching, different TTL, per user session, or per geographic area
  65. E X A M P L E E D G

    E S I D E I N C LU D E : LO G I N <esi:include src="personal-greeting.html"/> <esi:remove> Hello! </esi:remove>
  66. E X A M P L E E D G

    E S I D E I N C LU D E : LO G I N <esi:include src="personal-greeting.html"/> <esi:remove> Hello! </esi:remove>
  67. <esi:include src="personal-greeting.html"/> <esi:remove> Hello! </esi:remove> E X A M P

    L E E D G E S I D E I N C LU D E : LO G I N
  68. <esi:include src="personal-greeting.html"/> <esi:remove> Hello! </esi:remove> E X A M P

    L E E D G E S I D E I N C LU D E : LO G I N
  69. I M AG E S

  70. F O R M AT N E G OT I

    AT I O N
  71. J P E G X R W E B P

    ɂ Ʌɚ
  72. CO M P R E SS I O N

  73. J P E G L E V E LS :

    0 - 1 0 0
  74. J P E G L E V E LS :

    0 - 1 0 0 T H E Y ’ R E W H AT E V E R T H E E N CO D E R W A N TS T H E M TO M E A N
  75. P E R C E I V E D Q

    UA L I TY
  76. Q UA L I TY H U M A N

    S C A N S E E P E R C E I V E D Q UA L I TY
  77. None
  78. None
  79. O R I G I N A L : 1

    6 . 8 M B
  80. 9 0 : 5 . 8 M B

  81. 8 0 : 4 . 2 M B

  82. 7 0 : 3 . 2 M B

  83. 6 0 : 2 . 5 M B

  84. 5 0 : 1 . 9 M B

  85. 4 0 : 1 . 4 M B

  86. 3 0 : 1 . 2 M B

  87. 2 0 : 9 5 0 K B

  88. 1 0 : 5 9 4 K B

  89. 0 : 3 9 3 K B

  90. O R I G I N A L

  91. 0

  92. SS I M S T R U CT U R

    A L S I M I L A R I TY I M AG E
  93. E M M Y A W A R D W

    I N N I N G A LG O R I T H M Zhou Wang, Alan C. Bovik, Hamid R. Sheikh, and Eero P. Simoncelli
  94. SS I M A LG O R I T H

    M • Brightness • Contrast • Structure • Fast
  95. D SS I M ST R U CT U R

    A L D I SS I M I L A R I TY: D I STA N C E M E T R I C D E R I V E D F R O M SS I M
  96. AUTOPLAY

  97. None
  98. 0.009273 /images/90.png 0.008136 /images/80.png 0.009007 /images/70.png 0.010287 /images/60.png 0.012078 /images/50.png

    0.014768 /images/40.png 0.017413 /images/30.png 0.020712 /images/20.png 0.028642 /images/10.png 0.038585 /images/0.png
  99. P E R C E PT I V E Q

    UA L I TY T H R E S H O L D
  100. Original: 14.1MB 80: 0.008136 4.6MB 30: 0.017413 1.2MB 50: 0.012078

    1.9MB
  101. -91.4%

  102. F R O N T E N D D E

    V E LO P E RS CC-BY 2.0: Bill Jacobus
  103. P R E D I CT I V E B

    R O W S I N G
  104. P R E B R O W S I N

    G
  105. P R E B R O W S I N

    G 1. DNS Prefetch 2. TCP Preconnect 3. Prefetch 4. Prerender
  106. Ɇ ɂ

  107. D N S P R E F E TC H

    ɐ Ɇ ɂ 10.0.0.1 127.0.0.1
  108. TC P P R E CO N N E CT

    ɐ Ɇ Ȑ ɂ 10.0.0.1 127.0.0.1
  109. P R E LOA D ɐ Ɇ Ȑ ɂ 10.0.0.1

    127.0.0.1
  110. P R E R E N D E R ɐ

    Ɇ Ȑ  ɂ 10.0.0.1 127.0.0.1
  111. D N S P R E F E TC H

  112. <head> <link rel="dns-prefetch" href="//example.org"> </head> D N S P R

    E F E TC H
  113. <head> <link rel="dns-prefetch" href="//example.org"> </head> D N S P R

    E F E TC H
  114. <head> <link rel="dns-prefetch" href="//example.org"> </head> D N S P R

    E F E TC H
  115. <head> <link rel="dns-prefetch" href="//example.org"> </head> D N S P R

    E F E TC H
  116. <head> <link rel="preconnect" href="https://example.org" </head> P R E CO N

    N E CT
  117. <head> <link rel="prefetch" href="/page/2"> </head> P R E F E

    TC H
  118. <head> <link rel="prefetch" href="/page/2"> </head> P R E F E

    TC H
  119. <head> <link rel="prerender" href="/page/2"> </head> P R E R E

    N D E R
  120. W A R N I N G ! CC-BY 2.0:

    Robert Couse-Baker
  121. 1-25 26-50 51-75 76-100 101-125 126-150 > 150 15% 8%

    12% 16% 18% 16% 11% 0-1MB 1-2MB 2-3MB 3-4MB 4-5MB 5-6MB 6-8MB 3% 2% 4% 8% 15% 28% 36% Fonts 5% CSS 3% JS 17% HTML 3% Images 63% Other 9% YO U H AV E TO R E N D E R T H E E N T I R E PAG E !
  122. R E L = P R E LOA D

  123. P R E F E TC H VS P R

    E LO A D
  124. P R E LOA D V S P R E

    F E TC H • prefetch is an optional and low-priority fetch for a resource that might be used by a subsequent navigation • preload is a mandatory and high-priority fetch for a resource that is necessary for the current navigation • preload is typically sent as a header, rather than a <link> tag
  125. L I N K H E A D E R

    Link: /resource; rel=preload
  126. N E W A R C H I T E

    CT U R E S
  127. H T T P/ 1 . X S U C

    K S CC-BY: Flóra Soós
  128. H T T P/ 1 . X S U C

    K S • Minify + Concat JavaScript and CSS • Inlining small JavaScript and CSS • Using image sprites • Using data: URIs • Domain sharding
  129. T H E S E T H I N G

    S A R E A L L " C L E V E R " H AC K S CC-BY: Matt Biddulph
  130. M U LT I P L E X I N

    G CC-BY: Alosh Bennett C A N U S E O N E C O N N E C T I O N F O R P A R A L L E L R E Q U E S T S
  131. S E R V E R P US H CC-BY:

    Steven Depolo
  132. D E P E N D E N C I

    E S CC-BY-SA 2.0: David Gamez
  133. W E I G H TS CC-BY 2.0: Tri Vu

    Dao
  134. D E L I V E R I N G

    A PAG E
  135. PAG E A SS E TS Ɇ ɂ Ȑ

  136. PAG E A SS E TS Ɇ ɂ Ȑ

  137. PAG E A SS E TS GET /index.html Ɇ ɂ

    Ȑ
  138. PAG E A SS E TS GET /index.html 200 OK

    text/html Ɇ ɂ Ȑ
  139. PAG E A SS E TS Ɇ Ȑ ɂ GET

    /index.html 200 OK text/html
  140. PAG E A SS E TS Ɇ Ȑ ɂ GET

    /index.html 200 OK text/html critical-path.css critical-path.js logo.svg
  141. PAG E A SS E TS Ɇ Ȑ ɂ GET

    /index.html 200 OK text/html critical-path.css critical-path.js logo.svg font.eot
  142. PAG E A SS E TS Ɇ Ȑ ɂ GET

    /index.html 200 OK text/html critical-path.css critical-path.js logo.svg font.eot main.js
  143. PAG E A SS E TS Ɇ Ȑ ɂ GET

    /index.html 200 OK text/html critical-path.css critical-path.js logo.svg font.eot styles.css main.js
  144. I N S U M M A R Y

  145. P E R F O R M A N C

    E M AT T E RS
  146. T I M E = M O N E Y

  147. T I M E = U S E R S

    AT I S FA CT I O N = M O N E Y
  148. P E R F O R M A N C

    E = US E R E X P E R I E N C E
  149. F E E D B A C K & Q

    U E S T I O N S Twitter: Email: Slides: @dshafik dshafik@akamai.com http://daveyshafik.com/slides