Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[php[world] 2016] Every Millisecond Counts: Performance & UX

Davey Shafik
November 17, 2016

[php[world] 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.

Davey Shafik

November 17, 2016
Tweet

More Decks by Davey Shafik

Other Decks in Programming

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

    View Slide

  2. D AV E Y S H A F I K
    • Developer
    • Author
    • Open Source Contributor
    • Release Manager for PHP 7.1
    • @dshafik

    View Slide

  3. h tt p : / /d e v e l o p e r. a ka m a i .co m

    View Slide

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

    View Slide

  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

    View Slide

  6. A M A ZO N
    CC-BY 2.0: Thomas Shahan

    View Slide

  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

    View Slide

  8. $ 8 8 9 , 9 0 0 , 0 0 0
    2 0 1 4

    View Slide

  9. 1 2 . 5 ¢ FO 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 4

    View Slide

  10. $ 2 . 7 9 P E R US C I T I Z E N
    2 0 1 4

    View Slide

  11. R E M I N D E R : P E R 1 0 0 M S S LO W E R !

    View Slide

  12. G O O G L E
    CC-BY: Robert Scoble

    View Slide

  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 AY E R - AT- W E B - 2 0 . H T M L

    View Slide

  14. B I N G
    CC-BY-SA 2.0: badgreeb RECORDS

    View Slide

  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

    View Slide

  16. G Q
    CC-BY 2.0: BIAU Guillaume

    View Slide

  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/

    View Slide

  18. M O R E

    View Slide

  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

    View Slide

  20. CO N C LUS I O N

    View Slide

  21. US 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 F O R M A N C E
    A S L I T T L E A S 1 4 M S

    View Slide

  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

    View Slide

  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

    View Slide

  24. YO U P R O B A B LY N OT I C E D I T
    YO U RS E L F…

    View Slide

  25. 1 0 S E CO N D S I S A N E T E R N I TY

    View Slide

  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/

    View Slide

  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

    View Slide

  28. E V E R YO N E !
    CC-BY 2.0: James Cridland

    View Slide

  29. E V E R YO N E !
    • Designers
    • Sysadmins/Devops
    • Backend Developers
    • Frontend Developers
    • Browser Vendors

    View Slide

  30. W H AT M A K E S A W E B PA G E ?
    CC-BY-SA 2.0: Susanne Nilsson

    View Slide

  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%

    View Slide

  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%

    View Slide

  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%

    View Slide

  34. D E S I G N E RS
    CC-BY 2.0: Cliff Hutson

    View Slide

  35. 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 ! )

    View Slide

  36. SYS A D M I N S / D E V O P S
    CC-BY-SA 2.0: Bjorn Watland

    View Slide

  37. E N A B L E H T T P/ 2

    View Slide

  38. L E T ’ S E N C R Y PT !
    CC-BY: Jason Baker

    View Slide

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

    View Slide

  40. L E TS E N C R Y PT. O R G
    • Free (as in beer)
    • Automatic
    • Secure
    • Transparent
    • Open
    • Cooperative

    View Slide

  41. 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

    View Slide

  42. 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)

    View Slide

  43. 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);
    }
    });
    });
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  47. 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);
    }
    });
    });
    }

    View Slide

  48. 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);
    }
    });
    });
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  54. View Slide

  55. B A C K E N D D E V E LO P E RS
    CC-BY 2.0: Bobo Boom

    View Slide

  56. C A C H E A G G R E S S I V E LY
    CC-BY: Travis Wise

    View Slide

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

    View Slide

  58. D ATA B A S E C AC H I N G
    • Memcache
    • Cassandra

    View Slide

  59. F U L L PAG E C AC H I N G

    View Slide

  60. F U L L PA G E C A C H I N G
    • Memcache
    • Cassandra
    • Varnish
    • Squid

    View Slide

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

    View Slide

  62. 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

    View Slide

  63. 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


    Hello!

    View Slide

  64. 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


    Hello!

    View Slide

  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


    Hello!

    View Slide

  66. I M AG E S

    View Slide

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

    View Slide

  68. J P E G X R
    W E B P
    ɂ Ʌɚ

    View Slide

  69. CO M P R E SS I O N

    View Slide

  70. 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

    View Slide

  71. P E R C E I V E D Q UA L I TY

    View Slide

  72. 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

    View Slide

  73. View Slide

  74. O R I G I N A L : 1 6 . 8 M B

    View Slide

  75. 9 0 : 5 . 8 M B

    View Slide

  76. 8 0 : 4 . 2 M B

    View Slide

  77. 7 0 : 3 . 2 M B

    View Slide

  78. 6 0 : 2 . 5 M B

    View Slide

  79. 5 0 : 1 . 9 M B

    View Slide

  80. 4 0 : 1 . 4 M B

    View Slide

  81. 3 0 : 1 . 2 M B

    View Slide

  82. 2 0 : 9 5 0 K B

    View Slide

  83. 1 0 : 5 9 4 K B

    View Slide

  84. 0 : 3 9 3 K B

    View Slide

  85. O R I G I N A L

    View Slide

  86. 0

    View Slide

  87. 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

    View Slide

  88. 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

    View Slide

  89. SS I M A LG O R I T H M
    • Brightness
    • Contrast
    • Structure
    • Fast

    View Slide

  90. 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

    View Slide

  91. AUTOPLAY

    View Slide

  92. 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

    View Slide

  93. P E R C E PT I V E Q UA L I TY T H R E S H O L D

    View Slide

  94. Original: 14.1MB 80: 0.008136 4.6MB
    30: 0.017413 1.2MB
    50: 0.012078 1.9MB

    View Slide

  95. -91.4%

    View Slide

  96. F R O N T E N D D E V E LO P E RS
    CC-BY 2.0: Bill Jacobus

    View Slide

  97. P R E D I CT I V E B R O W S I N G

    View Slide

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

    View Slide

  99. P R E B R O W S I N G
    1. DNS Prefetch
    2. TCP Preconnect
    3. Prefetch
    4. Prerender

    View Slide

  100. D N S P R E F E TC H
    TC P P R E CO N N E CT
    P R E LOA D
    P R E R E N D E R
    ɐ
    Ɇ Ȑ

    ɂ
    10.0.0.1
    127.0.0.1

    View Slide

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

    View Slide




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

    View Slide




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

    View Slide




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

    View Slide




  105. P R E CO N N E CT

    View Slide




  106. P R E F E TC H

    View Slide




  107. P R E F E TC H

    View Slide




  108. P R E R E N D E R

    View Slide

  109. W A R N I N G !
    CC-BY 2.0: Robert Couse-Baker

    View Slide

  110. 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 !

    View Slide

  111. R E L = P R E LOA D

    View Slide

  112. P R E F E TC H VS P R E LO A D

    View Slide

  113. 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 tag

    View Slide

  114. L I N K H E A D E R
    Link: /resource; rel=preload

    View Slide

  115. N E W A R C H I T E CT U R E S

    View Slide

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

    View Slide

  117. 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

    View Slide

  118. 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

    View Slide

  119. 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

    View Slide

  120. S E R V E R P US H
    CC-BY: Steven Depolo

    View Slide

  121. D E P E N D E N C I E S
    CC-BY-SA 2.0: David Gamez

    View Slide

  122. W E I G H TS
    CC-BY 2.0: Tri Vu Dao

    View Slide

  123. D E L I V E R I N G A PAG E

    View Slide

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

    View Slide

  125. 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

    View Slide

  126. I N S U M M A R Y

    View Slide

  127. P E R F O R M A N C E M AT T E RS

    View Slide

  128. T I M E = M O N E Y

    View Slide

  129. T I M E = U S E R S AT I S FA CT I O N = M O N E Y

    View Slide

  130. P E R F O R M A N C E = US E R E X P E R I E N C E

    View Slide

  131. F E E D B AC K & Q U E ST I O N S
    Feedback:
    Twitter:
    Email:
    Slides:
    https://joind.in/talk/
    @dshafik
    [email protected]
    http://daveyshafik.com/slides
    ed949

    View Slide