1<!DOCTYPE html><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="generator" content="Gatsby 5.16.1"/><meta name="description" data-gatsby-head="true"/><meta name="twitter:card" content="summary" data-gatsby-head="true"/><meta name="twitter:title" content="A dive into Spotify performance at 1 am" data-gatsby-head="true"/><meta name="twitter:description" data-gatsby-head="true"/><meta name="twitter:site" content="@3perfcom" data-gatsby-head="true"/><meta name="twitter:creator" content="@iamakulov" data-gatsby-head="true"/><meta name="og:title" content="A dive into Spotify performance at 1 am" data-gatsby-head="true"/><meta name="og:description" data-gatsby-head="true"/><meta name="og:site_name" content="PerfPerfPerf" data-gatsby-head="true"/><meta name="fb:admins" content="100002052594007" data-gatsby-head="true"/><meta name="og:type" content="article" data-gatsby-head="true"/><meta name="article:published_time" content="2022-05-05T01:00:00.000Z" data-gatsby-head="true"/><meta name="article:author" content="Ivan Akulov" data-gatsby-head="true"/><meta name="article:modified_time" content="2022-05-05T01:00:00.000Z" data-gatsby-head="true"/><link rel="sitemap" type="application/xml" href="/sitemap-index.xml"/><link rel="icon" href="/favicon-32x32.png?v=896ef987c9f87d07396089ed2e630f97" type="image/png"/><link rel="manifest" href="/manifest.webmanifest" crossorigin="anonymous"/><link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png?v=896ef987c9f87d07396089ed2e630f97"/><link rel="alternate" type="application/rss+xml" title="PerfPerfPerf Blog" href="/rss.xml"/><title data-gatsby-head="true">A dive into Spotify performance at 1 am · PerfPerfPerf</title><link rel="canonical" href="https://3perf.com/blog/spotify-1am/" data-gatsby-head="true"/><html lang="en"><head><meta itemProp="name" content="A dive into Spotify performance at 1 am" data-gatsby-head="true"/><meta itemProp="description" data-gatsby-head="true"/><style data-href="/styles.b5c5436dd0507acd97e4.css" data-identity="gatsby-global-css">@font-face{font-display:swap;font-family:Bricolage Grotesque Variable;font-stretch:75% 100%;font-style:normal;font-weight:200 800;src:url(/static/bricolage-grotesque-vietnamese-standard-normal-315cef462476639efb58bdf85db6adf9.woff2) format("woff2-variations");unicode-range:u+0102-0103,u+0110-0111,u+0128-0129,u+0168-0169,u+01a0-01a1,u+01af-01b0,u+0300-0301,u+0303-0304,u+0308-0309,u+0323,u+0329,u+1ea0-1ef9,u+20ab}@font-face{font-display:swap;font-family:Bricolage Grotesque Variable;font-stretch:75% 100%;font-style:normal;font-weight:200 800;src:url(/static/bricolage-grotesque-latin-ext-standard-normal-a84345800ca1888afc1e9ebb595cc2d5.woff2) format("woff2-variations");unicode-range:u+0100-02ba,u+02bd-02c5,u+02c7-02cc,u+02ce-02d7,u+02dd-02ff,u+0304,u+0308,u+0329,u+1d00-1dbf,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-display:swap;font-family:Bricolage Grotesque Variable;font-stretch:75% 100%;font-style:normal;font-weight:200 800;src:url(/static/bricolage-grotesque-latin-standard-normal-e956cf557f2fb3fb7bed172a0ae8b6cd.woff2) format("woff2-variations");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}@font-face{font-display:swap;
1font-family:Fira Code;font-style:normal;font-weight:600;src:url(/static/fira-code-latin-600-normal-7ee6420189e6ca18a7d4f07c24ebbda7.woff2) format("woff2"),url(/static/fira-code-latin-600-normal-40873d2585f5b229e8e229799faed247.woff) format("woff")}@font-face{font-display:swap;font-family:Fira Code;font-style:normal;font-weight:400;src:url(/static/fira-code-latin-400-normal-e662d57ce51fba1f46e32dff4dd23e4d.woff2) format("woff2"),url(/static/fira-code-latin-400-normal-88fb5395c38bbc52be72b1063bc16fff.woff) format("woff")}</style><style data-styled="" data-styled-version="6.0.4">*,*::before,*::after{box-sizing:border-box;}/*!sc*/ 2html{font-family:'Bricolage Grotesque Variable',sans-serif;overflow-x:hidden;--link-color:#06c;--link-border-color:rgba(0,102,204,0.25);--link-active-color:#d04000;--link-active-border-color:rgba(208,64,0,0.25);}/*!sc*/ 3body{margin:0;font-size:16px;line-height:1.4;overflow:hidden;}/*!sc*/ 4a{color:var(--link-color);text-decoration:none;cursor:pointer;border-bottom:1px solid;border-color:var(--link-border-color);transition:color 0.25s ease-out,border-color 0.25s ease-out;}/*!sc*/ 5a:hover,a:focus,a:active{color:var(--link-active-color);border-color:var(--link-active-border-color);transition:none;}/*!sc*/ 6code{font-family:'Fira Code',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;background:rgba(0, 0, 0, 0.06);padding:0 3px;border-radius:2px;}/*!sc*/ 7p{margin:0;}/*!sc*/ 8p+p{margin-top:16px;}/*!sc*/ 9li{margin:0;}/*!sc*/ 10li+li{margin-top:16px;}/*!sc*/ 11data-styled.g1[id="sc-global-ftzMja1"]{content:"sc-global-ftzMja1,"}/*!sc*/ 12.jLbNpk #perf-letters path{fill:black;}/*!sc*/ 13.jLbNpk rect{stroke:black;}/*!sc*/ 14data-styled.g2[id="styled__LogoSvg-sc-lzfaox-0"]{content:"jLbNpk,"}/*!sc*/ 15.fHUXzs{margin:0 auto;max-width:1000px;width:100%;padding:0 20px;}/*!sc*/ 16@media print{.fHUXzs{max-width:none;}}/*!sc*/ 17data-styled.g3[id="WidthWrapper-sc-1hg7f1n-0"]{content:"fHUXzs,"}/*!sc*/ 18.ewhQKw{display:inline-block;overflow:hidden;line-height:0;}/*!sc*/ 19data-styled.g4[id="styled__Container-sc-1ekqqun-0"]{content:"ewhQKw,"}/*!sc*/ 20.jViMaS{display:flex;flex-wrap:wrap;padding:0;margin:-8px -12px;list-style-type:none;}/*!sc*/ 21data-styled.g6[id="styled__Container-sc-exfs5j-0"]{content:"jViMaS,"}/*!sc*/ 22.bHlTQw{margin:8px 12px;}/*!sc*/ 23data-styled.g7[id="styled__Item-sc-exfs5j-1"]{content:"bHlTQw,"}/*!sc*/ 24.chErgn{display:block;border:none;width:min-content;}/*!sc*/ 25data-styled.g8[id="styled__ItemLink-sc-exfs5j-2"]{content:"chErgn,"}/*!sc*/ 26.kZXEoD{color:var(--link-color);text-decoration:none;cursor:pointer;border-bottom:1px solid;border-color:var(--link-border-color);transition:color 0.25s ease-out,border-color 0.25s ease-out;}/*!sc*/ 27.styled__ItemLink-sc-exfs5j-2:hover .kZXEoD,.styled__ItemLink-sc-exfs5j-2:focus .kZXEoD,.styled__ItemLink-sc-exfs5j-2:active .kZXEoD{color:var(--link-active-color);border-color:var(--link-active-border-color);transition:none;}/*!sc*/ 28data-styled.g10[id="styled__Label-sc-exfs5j-4"]{content:"kZXEoD,"}/*!sc*/ 29.qJRRG{display:flex;justify-content:space-between;}/*!sc*/ 30data-styled.g12[id="styled__Credentials-sc-fmk9on-1"]{content:"qJRRG,"}/*!sc*/ 31.eMPHzj{max-width:550px;margin-top:8px;font-size:10px;text-transform:uppercase;letter-spacing:1px;}/*!sc*/ 32data-styled.g13[id="styled__Legal-sc-fmk9on-2"]{content:"eMPHzj,"}/*!sc*/ 33.ecDLDl{letter-spacing:1px;}/*!sc*/ 34data-styled.g14[id="styled__LicenseName-sc-fmk9on-3"]{content:"ecDLDl,"}/*!sc*/ 35.YNXaB{margin-top:16px;}/*!sc*/ 36data-styled.g17[id="styled__MailchimpForm-sc-1pidu4x-1"]{content:"YNXaB,"}/*!sc*/ 37.ealAEm{margin-right:16px;margin-bottom:8px;height:32px;border:none;border-radius:2px;padding:0 12px;font-size:inherit;font-family:inherit;}/*!sc*/ 38data-styled.g18[id="styled__MailchimpInput-sc-1pidu4x-2"]{content:"ealAEm,"}/*!sc*/ 39.celNKA{cursor:pointer;height:32px;padding:0 12px;border-radius:2px;font-size:inherit;font-family:inherit;background:#ffdb01;color:black;border:none;}/*!sc*/ 40.celNKA:hover,.celNKA:focus,.celNKA:active{background:#ffe967;}/*!sc*/ 41data-styled.g19[id="styled__MailchimpSubmit-sc-1pidu4x-3"]{content:"celNKA,"}/*!sc*/ 42.hSVmgK{position:absolute;
42left:-5000px;}/*!sc*/ 43data-styled.g20[id="styled__HiddenDiv-sc-1pidu4x-4"]{content:"hSVmgK,"}/*!sc*/ 44.jLAQgJ{display:flex;align-items:center;flex-wrap:wrap;gap:12px 24px;}/*!sc*/ 45data-styled.g21[id="styled__Container-sc-1wdhdtf-0"]{content:"jLAQgJ,"}/*!sc*/ 46.hMAVWe{display:block;height:50px;width:50px;}/*!sc*/ 47data-styled.g22[id="styled__Logo-sc-1wdhdtf-1"]{content:"hMAVWe,"}/*!sc*/ 48.cmWeoQ{flex:1 0 auto;max-width:calc(100% - 24px);}/*!sc*/ 49data-styled.g23[id="styled__ItemsWrapper-sc-1wdhdtf-2"]{content:"cmWeoQ,"}/*!sc*/ 50.IrpCG{display:flex;gap:3px 12px;flex-wrap:wrap;}/*!sc*/ 51data-styled.g24[id="styled__Items-sc-1wdhdtf-3"]{content:"IrpCG,"}/*!sc*/ 52.hruSyn{display:block;border:none;}/*!sc*/ 53data-styled.g25[id="styled__BlockLink-sc-1wdhdtf-4"]{content:"hruSyn,"}/*!sc*/ 54@media (min-width:769px){.PaASP{margin-left:auto;}}/*!sc*/ 55data-styled.g26[id="styled__SecondaryItems-sc-1wdhdtf-5"]{content:"PaASP,"}/*!sc*/ 56.jkrHkn{margin-top:24px;margin-bottom:56px;font-size:16px;}/*!sc*/ 57data-styled.g27[id="styled__Nav-sc-g87c0z-0"]{content:"jkrHkn,"}/*!sc*/ 58.hjUmKx{margin-bottom:40px;}/*!sc*/ 59data-styled.g28[id="styled__Header-sc-g87c0z-1"]{content:"hjUmKx,"}/*!sc*/ 60.fpALeQ{margin-top:16px;}/*!sc*/ 61data-styled.g29[id="styled__TopMeta-sc-g87c0z-2"]{content:"fpALeQ,"}/*!sc*/ 62.bWLCcb{margin-top:32px;}/*!sc*/ 63data-styled.g30[id="styled__BottomMeta-sc-g87c0z-3"]{content:"bWLCcb,"}/*!sc*/ 64.gCDoRG{margin:0;font-size:60px;font-weight:900;line-height:1;}/*!sc*/ 65@media (max-width:768px){.gCDoRG{font-size:40px;}}/*!sc*/ 66data-styled.g31[id="styled__Title-sc-g87c0z-4"]{content:"gCDoRG,"}/*!sc*/ 67.loPRVe{margin:48px -24px;max-width:600px;padding:16px 24px;border-radius:4px;background:#fffae0;}/*!sc*/ 68data-styled.g32[id="styled__MailchimpSubscribe-sc-g87c0z-5"]{content:"loPRVe,"}/*!sc*/ 69.jHbsYy{margin-top:48px;}/*!sc*/ 70data-styled.g33[id="styled__BlogFooterAccordion-sc-g87c0z-6"]{content:"jHbsYy,"}/*!sc*/ 71.kMmgzr{margin-top:48px;margin-bottom:16px;}/*!sc*/ 72data-styled.g34[id="styled__Footer-sc-g87c0z-7"]{content:"kMmgzr,"}/*!sc*/ 73.dhCohm{font-family:system-ui,sans-serif;max-width:600px;}/*!sc*/ 74.dhCohm h1,.dhCohm h2,.dhCohm h3,.dhCohm h4,.dhCohm h5,.dhCohm h6{font-family:'Bricolage Grotesque Variable',sans-serif;margin-top:2em;}/*!sc*/ 75.dhCohm h1 .anchor,.dhCohm h2 .anchor,.dhCohm h3 .anchor,.dhCohm h4 .anchor,.dhCohm h5 .anchor,.dhCohm h6 .anchor{border:none;}/*!sc*/ 76.dhCohm h1{font-size:32px;font-weight:900;}/*!sc*/ 77.dhCohm h2{font-size:24px;}/*!sc*/ 78.dhCohm h3{font-size:18px;}/*!sc*/ 79.dhCohm .media-container{margin:0;}/*!sc*/ 80.dhCohm .media-container img,.dhCohm .media-container video{width:min(max(100%,80vw),900px);height:auto;}/*!sc*/ 81.dhCohm .media-container img{border-radius:2px;}/*!sc*/ 82.dhCohm .media-container a{display:block;border-bottom:none;}/*!sc*/ 83.dhCohm .media-container_border img,.dhCohm .media-container_border video{outline:1px solid rgba(0,0,0,0.05);outline-offset:-1px;}/*!sc*/ 84.dhCohm .sidenote__heading .media-container img,.dhCohm .note .media-container img{width:100%;}/*!sc*/ 85.dhCohm .media-container__caption{font-size:13px;font-style:italic;margin-top:4px;}/*!sc*/ 86.dhCohm .media-container__caption em{font-style:normal;}/*!sc*/ 87.dhCohm .media-container_scrollable{width:100vw;overflow-x:auto;margin-left:-20px;margin-right:-20px;padding-left:20px;padding-right:20px;}/*!sc*/ 88.dhCohm .media-container_scrollable::-webkit-scrollbar{height:4px;background:#eee;}/*!sc*/ 89.dhCohm .media-container_scrollable::-webkit-scrollbar-thumb{background:#ccc;border-radius:4px;}/*!sc*/ 90.dhCohm ol,.dhCohm ul{margin:0;padding-left:32px;}/*!sc*/ 91.dhCohm p+.list_compact.list_compact,.dhCohm .list_compact.list_compact+p{margin-top:8px;}/*!sc*/ 92.dhCohm .list_compact li+li{margin-top:0;}/*!sc*/ 93.dhCohm .list_spread li+li{margin-top:16px;}/*!sc*/ 94.dhCohm .gatsby-highlight{overflow-x:auto;margin:0 -16px;padding:8px 16px;background:rgba(0, 0, 0, 0.06);border-radius:2px;}/*!sc*/ 95.dhCohm .gatsby-highlight >pre{margin:0;}/*!sc*/ 96.dhCohm .gatsby-highlight >pre>code{padding:0;background:unset;}/*!sc*/ 97.dhCohm .gatsby-highlight[data-word-wrap] >pre,.dhCohm .gatsby-highlight[data-word-wrap] >pre>code{white-space:pre-wrap;overflow-wrap:break-word;}/*!sc*/ 98.dhCohm code[class*='language-'],.dhCohm pre[class*='language-']{text-align:left;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:2;-o-tab-size:2;tab-size:2;hyphens:none;}/*!sc*/ 99.dhCohm pre[class*='language-']{white-space:pre;}/*!sc*/ 100.dhCohm pre[class*='language-']::selection,.dhCohm pre[class*='language-'] ::selection,.dhCohm code[class*='language-']::selection,.dhCohm code[class*='language-'] ::selection{text-shadow:none;background:#b3d4fc;}/*!sc*/ 101.dhCohm .token.comment,.dhCohm .token.prolog,.dhCohm .token.doctype,.dhCohm .token.cdata{color:slategray;}/*!sc*/ 102.dhCohm .token.punctuation{color:#999;}/*!sc*/ 103.dhCohm .namespace{opacity:0.7;}/*!sc*/ 104.dhCohm .token.property,.dhCohm .token.tag,.dhCohm .token.boolean,.dhCohm .token.number,.dhCohm .token.constant,.dhCohm .token.symbol,.dhCohm .token.deleted{color:#905;}/*!sc*/ 105.dhCohm .token.selector,.dhCohm .token.attr-name,.dhCohm .token.string,.dhCohm .token.char,.dhCohm .token.builtin,.dhCohm .token.inserted{color:#690;}/*!sc*/ 106.dhCohm .token.operator,.dhCohm .token.entity,.dhCohm .token.url,.dhCohm .language-css .token.string,.dhCohm .style .token.string{color:#9a6e3a;}/*!sc*/ 107.dhCohm .token.atrule,.dhCohm .token.attr-value,.dhCohm .token.keyword{color:#07a;}/*!sc*/ 108.dhCohm .token.function,.dhCohm .token.class-name{color:#dd4a68;}/*!sc*/ 109.dhCohm .token.regex,.dhCohm .token.important,.dhCohm .token.variable{color:#e90;}/*!sc*/ 110.dhCohm .token.important,.dhCohm .token.bold{font-weight:bold;}
110/*!sc*/ 111.dhCohm .token.italic{font-style:italic;}/*!sc*/ 112.dhCohm .token.entity{cursor:help;}/*!sc*/ 113@media (min-width:1025px){.dhCohm .sidenote{display:flex;align-items:baseline;width:calc(100% + 300px + 48px);}.dhCohm .sidenote__body{width:calc(100% - 300px - 48px);}.dhCohm .sidenote__heading{margin-left:48px;width:300px;font-size:13px;height:0;}.dhCohm .sidenote__remark{display:none;}}/*!sc*/ 114@media (max-width:1024px){.dhCohm .sidenote__heading{margin:8px 0 16px;font-size:13px;}}/*!sc*/ 115.dhCohm .toc{background:#fffae0;width:fit-content;margin:16px -16px;padding:12px 40px 16px 16px;font-size:13px;border-radius:2px;font-family:'Bricolage Grotesque Variable',sans-serif;}/*!sc*/ 116.dhCohm .toc.toc_with-header{margin:32px -16px;padding:16px 40px 24px 16px;}/*!sc*/ 117.dhCohm .toc ul{padding-left:24px;list-style:none;}/*!sc*/ 118.dhCohm .toc li{margin-top:8px;}/*!sc*/ 119.dhCohm .toc >ul{padding-left:0;}/*!sc*/ 120.dhCohm .toc >ul>li:first-child{margin-top:0;}/*!sc*/ 121.dhCohm .toc ul:has(> li:only-child > ul:only-child){padding-left:0;}/*!sc*/ 122.dhCohm .toc *:is(p,ul)+*:is(p,ul){margin-top:0!important;}/*!sc*/ 123.dhCohm .toc__header{margin:0 0 8px;font-size:26px;}/*!sc*/ 124.dhCohm .note{background:#fffae0;margin:16px -16px;padding:8px 16px;font-size:13px;border-radius:2px;}/*!sc*/ 125.dhCohm .note >.gatsby-highlight:last-child{margin-bottom:-8px;}/*!sc*/ 126.dhCohm *:is(p,.note,.sidenote,.gatsby-highlight,ul,ol,.media-container)+*:is(p,.note,.sidenote,.gatsby-highlight,ul,ol,.media-container){margin-top:16px;}/*!sc*/ 127.dhCohm blockquote:not(.sidenote__heading):not(.note){position:relative;margin:16px 0;border-left:#333 5px solid;padding-left:24px;}/*!sc*/ 128.dhCohm blockquote:not(.sidenote__heading):not(.note)::before{content:'â';position:absolute;left:-16px;top:0;display:block;height:30px;overflow:hidden;line-height:40px;font-size:60px;font-weight:900;color:#333;background:white;}/*!sc*/ 129.dhCohm mark{background:#fffae0;}/*!sc*/ 130.dhCohm hr{margin-top:32px;margin-bottom:32px;border:none;position:relative;}/*!sc*/ 131.dhCohm hr::after{content:'· · ·';text-align:center;width:100%;display:block;color:#999;letter-spacing:5px;user-select:none;}/*!sc*/ 132data-styled.g35[id="styled__Content-sc-g87c0z-8"]{content:"dhCohm,"}/*!sc*/ 133</style><style>.gatsby-image-wrapper{position:relative;overflow:hidden}.gatsby-image-wrapper picture.object-fit-polyfill{position:static!important}.gatsby-image-wrapper img{bottom:0;height:100%;left:0;margin:0;max-width:none;padding:0;position:absolute;right:0;top:0;width:100%;object-fit:cover}.gatsby-image-wrapper [data-main-image]{opacity:0;transform:translateZ(0);transition:opacity .25s linear;will-change:opacity}.gatsby-image-wrapper-constrained{display:inline-block;vertical-align:top}</style><noscript><style>.gatsby-image-wrapper noscript [data-main-image]{opacity:1!important}.gatsby-image-wrapper [data-placeholder-image]{opacity:0!important}</style></noscript>
133<script type="module">const e="undefined"!=typeof HTMLImageElement&&"loading"in HTMLImageElement.prototype;e&&document.body.addEventListener("load",(function(e){const t=e.target;if(void 0===t.dataset.mainImage)return;if(void 0===t.dataset.gatsbyImageSsr)return;let a=null,n=t;for(;null===a&&n;)void 0!==n.parentNode.dataset.gatsbyImageWrapper&&(a=n.parentNode),n=n.parentNode;const o=a.querySelector("[data-placeholder-image]"),r=new Image;r.src=t.currentSrc,r.decode().catch((()=>{})).then((()=>{t.style.opacity=1,o&&(o.style.opacity=0,o.style.transition="opacity 500ms linear")}))}),!0);</script>
133<style type="text/css"> 134 .anchor.before { 135 position: absolute; 136 top: 0; 137 left: 0; 138 transform: translateX(-100%); 139 padding-right: 4px; 140 } 141 .anchor.after { 142 display: inline-block; 143 padding-left: 4px; 144 } 145 h1 .anchor svg, 146 h2 .anchor svg, 147 h3 .anchor svg, 148 h4 .anchor svg, 149 h5 .anchor svg, 150 h6 .anchor svg { 151 visibility: hidden; 152 } 153 h1:hover .anchor svg, 154 h2:hover .anchor svg, 155 h3:hover .anchor svg, 156 h4:hover .anchor svg, 157 h5:hover .anchor svg, 158 h6:hover .anchor svg, 159 h1 .anchor:focus svg, 160 h2 .anchor:focus svg, 161 h3 .anchor:focus svg, 162 h4 .anchor:focus svg, 163 h5 .anchor:focus svg, 164 h6 .anchor:focus svg { 165 visibility: visible; 166 } 167 </style>
167<script> 168 document.addEventListener("DOMContentLoaded", function(event) { 169 var hash = window.decodeURI(location.hash.replace('#', '')) 170 if (hash !== '') { 171 var element = document.getElementById(hash) 172 if (element) { 173 var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop 174 var clientTop = document.documentElement.clientTop || document.body.clientTop || 0 175 var offset = element.getBoundingClientRect().top + scrollTop - clientTop 176 // Wait for the browser to finish rendering before scrolling. 177 setTimeout((function() { 178 window.scrollTo(0, offset - 0) 179 }), 0) 180 } 181 } 182 }) 183 </script>
183<script src="https://cdn.usefathom.com/script.js" data-site="EIKSECOJ" data-excluded-domains="localhost" defer=""></script>
183<script src="https://unpkg.com/[email protected]/dist/quicklink.umd.js" defer=""></script>
183<script> 184 window.addEventListener('load', () => quicklink.listen()); 185 </script>
185</head><body><div id="___gatsby"><div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper"><!--$--><div><div class="WidthWrapper-sc-1hg7f1n-0 fHUXzs"><div class="styled__Container-sc-1wdhdtf-0 jLAQgJ styled__Nav-sc-g87c0z-0 jkrHkn"><a href="/" class="styled__BlockLink-sc-1wdhdtf-4 hruSyn"><div><svg class="styled__LogoSvg-sc-lzfaox-0 jLbNpk styled__Logo-sc-1wdhdtf-1 hMAVWe js--site-logo" width="53.445835mm" height="53.445835mm" viewBox="0 0 53.445835 53.445835" version="1.1" id="svg8"><g transform="translate(-45.848515,-91.116368)"><rect style="fill:none;stroke-width:2.64583349;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect815" width="50.800003" height="50.800003" x="47.171432" y="92.439285"></rect><g aria-label="PERF PERF PERF" style="fill:none;font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill-opacity:1;stroke:none;stroke-width:0.26458332" id="perf-letters"><path d="m 61.316555,100.90596 q 0.98425,0 1.703916,0.32808 0.73025,0.32809 1.121834,0.93134 0.391583,0.60325 0.391583,1.42875 0,0.81491 -0.391583,1.42875 -0.391584,0.60325 -1.121834,0.93133 -0.719666,0.3175 -1.703916,0.3175 h -1.49225 v 2.04258 h -1.7145 v -7.40833 z m -0.09525,3.96875 q 0.772583,0 1.17475,-0.32808 0.402166,-0.33867 0.402166,-0.9525 0,-0.62442 -0.402166,-0.9525 -0.402167,-0.33867 -1.17475,-0.33867 h -1.397 v 2.57175 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path842"></path><path d="m 71.758666,106.93846 v 1.37583 H 66.0225 v -7.40833 h 5.598583 v 1.37583 h -3.894667 v 1.60867 H 71.166 v 1.3335 h -3.439584 v 1.7145 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path844"></path><path d="m 78.117927,108.31429 -1.42875,-2.06375 h -0.08467 -1.49225 v 2.06375 h -1.7145 v -7.40833 h 3.20675 q 0.98425,0 1.703917,0.32808 0.73025,0.32809 1.121833,0.93134 0.391583,0.60325 0.391583,1.42875 0,0.8255 -0.402166,1.42875 -0.391584,0.59266 -1.121834,0.91016 l 1.661583,2.38125 z m -0.03175,-4.72016 q 0,-0.62442 -0.402167,-0.9525 -0.402167,-0.33867 -1.17475,-0.33867 h -1.397 v 2.58233 h 1.397 q 0.772583,0 1.17475,-0.33866 0.402167,-0.33867 0.402167,-0.9525 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path846"></path><path d="m 83.148979,102.28179 v 1.95792 h 3.429 v 1.37583 h -3.429 v 2.69875 h -1.7145 v -7.40833 h 5.598584 v 1.37583 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path848"></path><path d="m 61.316555,114.13513 q 0.98425,0 1.703916,0.32808 0.73025,0.32808 1.121834,0.93133 0.391583,0.60325 0.391583,1.42875 0,0.81492 -0.391583,1.42875 -0.391584,0.60325 -1.121834,0.93134 -0.719666,0.3175 -1.703916,0.3175 h -1.49225 v 2.04258 h -1.7145 v -7.40833 z m -0.09525,3.96875 q 0.772583,0 1.17475,-0.32809 0.402166,-0.33866 0.402166,-0.9525 0,-0.62441 -0.402166,-0.9525 -0.402167,-0.33866 -1.17475,-0.33866 h -1.397 v 2.57175 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path850"></path><path d="m 71.758666,120.16763 v 1.37583 H 66.0225 v -7.40833 h 5.598583 v 1.37583 h -3.894667 v 1.60867 H 71.166 v 1.3335 h -3.439584 v 1.7145 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path852"></path><path d="m 78.117927,121.54346 -1.42875,-2.06375 h -0.08467 -1.49225 v 2.06375 h -1.7145 v -7.40833 h 3.20675 q 0.98425,0 1.703917,0.32808
1850.73025,0.32808 1.121833,0.93133 0.391583,0.60325 0.391583,1.42875 0,0.8255 -0.402166,1.42875 -0.391584,0.59267 -1.121834,0.91017 l 1.661583,2.38125 z m -0.03175,-4.72017 q 0,-0.62441 -0.402167,-0.9525 -0.402167,-0.33866 -1.17475,-0.33866 h -1.397 v 2.58233 h 1.397 q 0.772583,0 1.17475,-0.33867 0.402167,-0.33866 0.402167,-0.9525 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path854"></path><path d="m 83.148979,115.51096 v 1.95792 h 3.429 v 1.37583 h -3.429 v 2.69875 h -1.7145 v -7.40833 h 5.598584 v 1.37583 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path856"></path><path d="m 61.316555,127.36429 q 0.98425,0 1.703916,0.32809 0.73025,0.32808 1.121834,0.93133 0.391583,0.60325 0.391583,1.42875 0,0.81492 -0.391583,1.42875 -0.391584,0.60325 -1.121834,0.93133 -0.719666,0.3175 -1.703916,0.3175 h -1.49225 v 2.04259 h -1.7145 v -7.40834 z m -0.09525,3.96875 q 0.772583,0 1.17475,-0.32808 0.402166,-0.33867 0.402166,-0.9525 0,-0.62442 -0.402166,-0.9525 -0.402167,-0.33867 -1.17475,-0.33867 h -1.397 v 2.57175 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path858"></path><path d="m 71.758666,133.39679 v 1.37584 H 66.0225 v -7.40834 h 5.598583 v 1.37584 h -3.894667 v 1.60866 H 71.166 v 1.3335 h -3.439584 v 1.7145 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path860"></path><path d="m 78.117927,134.77263 -1.42875,-2.06375 h -0.08467 -1.49225 v 2.06375 h -1.7145 v -7.40834 h 3.20675 q 0.98425,0 1.703917,0.32809 0.73025,0.32808 1.121833,0.93133 0.391583,0.60325 0.391583,1.42875 0,0.8255 -0.402166,1.42875 -0.391584,0.59267 -1.121834,0.91017 l 1.661583,2.38125 z m -0.03175,-4.72017 q 0,-0.62442 -0.402167,-0.9525 -0.402167,-0.33867 -1.17475,-0.33867 h -1.397 v 2.58234 h 1.397 q 0.772583,0 1.17475,-0.33867 0.402167,-0.33867 0.402167,-0.9525 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path862"></path><path d="m 83.148979,128.74013 v 1.95791 h 3.429 v 1.37584 h -3.429 v 2.69875 h -1.7145 v -7.40834 h 5.598584 v 1.37584 z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:1;font-family:Montserrat;letter-spacing:0.26458332px;fill-opacity:1;stroke-width:0.26458332" id="path864"></path></g></g></svg></div></a><div class="styled__ItemsWrapper-sc-1wdhdtf-2 cmWeoQ"><div class="styled__Items-sc-1wdhdtf-3 IrpCG"><a href="/">Talks and Case Studies</a><a href="/workshops">Workshops</a><div class="styled__SecondaryItems-sc-1wdhdtf-5 PaASP"><a href="mailto:[email protected]">[email protected]</a></div></div></div></div><header class="styled__Header-sc-g87c0z-1 hjUmKx"><h1 class="styled__Title-sc-g87c0z-4 gCDoRG">A dive into Spotify performance at 1 am</h1><div class="styled__TopMeta-sc-g87c0z-2 fpALeQ">3 min read<!-- --> · Author:<!-- --> <a href="https://twitter.com/iamakulov" rel="author">Ivan Akulov</a></div></header><article class="styled__Content-sc-g87c0z-8 dhCohm"><div><p><em>This is a shareable version of <a href="https://twitter.com/iamakulov/status/1522008502398554113">an X thread</a>.</em></p> 186<p>Oh look, my favorite app Spotify being slow!</p> 187<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><p lang="en" dir="ltr">Not to pick on Spotify in particular, but it's interesting how slow some "desktop apps" to do things like switch between playlists that are already loaded on my machine. Feels more like a "website" than an "app" <a href="https://t.co/DiLksaHWTl">pic.twitter.com/DiLksaHWTl</a></p>— Geoffrey Litt (@geoffreylitt) <a href="https://x.com/geoffreylitt/status/1521971476965969920?ref_src=twsrc%5Etfw">May 4, 2022</a></blockquote> 188 189 190<p>Also itâs 1 am meaning itâs the best time to do some performance profiling.</p> 191<hr> 192<p>Spotify is an Electron app, meaning we can use Chrome DevTools to profile it. To enable Chrome DevTools in Spotify, I install <code class="language-text">spicetify</code> and run <code class="language-text">spicetify enable-devtools</code>.</p> 193<p>Yay!</p> 194<figure class="media-container"><picture><img src="/static/c1a79d1b0e83887ff2f70ab4669fdc71/0bbcd/1.png" srcset="/static/c1a79d1b0e83887ff2f70ab4669fdc71/0608e/1.png 225w, 195/static/c1a79d1b0e83887ff2f70ab4669fdc71/31401/1.png 450w, 196/static/c1a79d1b0e83887ff2f70ab4669fdc71/0bbcd/1.png 820w" alt="" width="820" height="652"></picture></figure> 197<hr> 198<p>Now, letâs go to Chrome DevTools â Performance â Record, switch between playlists a couple times, and stop the recording. This is what weâll get â</p> 199<p>What can we see here?</p> 200<figure class="media-container"><picture><img src="/static/6ec76f929f7b5357a858f0ff7bfc0aa7/7293b/2.jpg" srcset="/static/6ec76f929f7b5357a858f0ff7bfc0aa7/7dcb8/2.jpg 225w, 201/static/6ec76f929f7b5357a858f0ff7bfc0aa7/cb709/2.jpg 450w, 202/static/6ec76f929f7b5357a858f0ff7bfc0aa7/7293b/2.jpg 900w, 203/static/6ec76f929f7b5357a858f0ff7bfc0aa7/cad38/2.jpg 1350w, 204/static/6ec76f929f7b5357a858f0ff7bfc0aa7/60fbd/2.jpg 1724w" alt="" width="900" height="929"></picture></figure> 205<hr> 206<p><strong>1) Spotify uses React.</strong></p> 207<p>This <code class="language-text">t.unstable_runWithPriority</code> function in the flamechart is a key sign of React. Whenever you see it, itâs React running.</p> 208<p>Which means itâs not surprising that switching playlists is slow! With all my love for React, it defaults into slow performance.</p> 209<figure class="media-container"><picture><img src="/static/9c44d9796b1457f541f1445b1228b8f5/7293b/3.jpg" srcset="/static/9c44d9796b1457f541f1445b1228b8f5/7dcb8/3.jpg 225w, 210/static/9c44d9796b1457f541f1445b1228b8f5/cb709/3.jpg 450w, 211/static/9c44d9796b1457f541f1445b1228b8f5/7293b/3.jpg 900w, 212/static/9c44d9796b1457f541f1445b1228b8f5/cad38/3.jpg 1350w, 213/static/9c44d9796b1457f541f1445b1228b8f5/60fbd/3.jpg 1724w" alt="" width="900" height="929"></picture></figure> 214<hr> 215<p><strong>2) Thereâs not one but several React renders.</strong></p> 216<p>This is likely an example of the Cascading Rerenders antipattern (gosh I
216should write an article on this):</p> 217<ul class="list_compact"> 218<li>you await on several promises</li> 219<li>the first promise resolves â you render</li> 220<li>the second promise resolves â you rerender</li> 221<li>â¦</li> 222</ul> 223<figure class="media-container"><picture><img src="/static/1e69c4ae68ff58a09cfb61a4325435c4/7293b/4.jpg" srcset="/static/1e69c4ae68ff58a09cfb61a4325435c4/7dcb8/4.jpg 225w, 224/static/1e69c4ae68ff58a09cfb61a4325435c4/cb709/4.jpg 450w, 225/static/1e69c4ae68ff58a09cfb61a4325435c4/7293b/4.jpg 900w, 226/static/1e69c4ae68ff58a09cfb61a4325435c4/cad38/4.jpg 1350w, 227/static/1e69c4ae68ff58a09cfb61a4325435c4/251e3/4.jpg 1800w, 228/static/1e69c4ae68ff58a09cfb61a4325435c4/c893a/4.jpg 2290w" alt="" width="900" height="700"></picture></figure> 229<hr> 230<p>This is costly because:</p> 231<ul class="list_compact"> 232<li>some components end up rerendering multiple times</li> 233<li>thereâs on overhead of running every new React render</li> 234</ul> 235<p>Once you notice this and find the cause, you typically fix this with <code class="language-text">await Promise.all()</code> or <code class="language-text">unstable_batchedUpdates()</code> or whatever.</p> 236<hr> 237<p><strong>3) Thereâs also a bunch of Layout Thrashing going on.</strong></p> 238<p>All these violet rectangles take ~80 ms (out of the total ~440 ms delay). Not every one needs/can be fixed, but some definitely do!</p> 239<p>[Canât dive deeper into this due to a DevTools bug :( <a href="https://issues.chromium.org/issues/40835506">https://issues.chromium.org/issues/40835506</a>]</p> 240<figure class="media-container"><picture><img src="/static/87032b62ad423dbb13234e0892a8f972/7293b/5.jpg" srcset="/static/87032b62ad423dbb13234e0892a8f972/7dcb8/5.jpg 225w, 241/static/87032b62ad423dbb13234e0892a8f972/cb709/5.jpg 450w, 242/static/87032b62ad423dbb13234e0892a8f972/7293b/5.jpg 900w, 243/static/87032b62ad423dbb13234e0892a8f972/cad38/5.jpg 1350w, 244/static/87032b62ad423dbb13234e0892a8f972/251e3/5.jpg 1800w, 245/static/87032b62ad423dbb13234e0892a8f972/c893a/5.jpg 2290w" alt="" width="900" height="700"></picture></figure> 246<hr> 247<p>âLayout what?â Itâs great that youâre asking! Check these two great articles, my sir/madam:</p> 248<ul class="list_compact"> 249<li><a href="http://blog.wilsonpage.co.uk/preventing-layout-thrashing/">http://blog.wilsonpage.co.uk/preventing-layout-thrashing/</a></li> 250<li><a href="https://www.phpied.com/rendering-repaint-reflowrelayout-restyle/">https://www.phpied.com/rendering-repaint-reflowrelayout-restyle/</a></li> 251</ul> 252<hr> 253<p><strong>4) The largest React render takes 200 ms</strong> and renders a whole lot of small components, presumably the list of tracks.</p> 254<p>a) Why render all (checks Spotify) 82 tracks at once? Why not render just ten â and virtualize the rest?</p> 255<p>(Iâm sure there are reasons â genuinely curious!)</p> 256<figure class="media-container"><picture><img src="/static/ec6723556f41c50306c5927057df31dc/7293b/6.jpg" srcset="/static/ec6723556f41c50306c5927057df31dc/7dcb8/6.jpg 225w, 257/static/ec6723556f41c50306c5927057df31dc/cb709/6.jpg 450w, 258/static/ec6723556f41c50306c5927057df31dc/7293b/6.jpg 900w, 259/static/ec6723556f41c50306c5927057df31dc/cad38/6.jpg 1350w, 260/static/ec6723556f41c50306c5927057df31dc/251e3/6.jpg 1800w, 261/static/ec6723556f41c50306c5927057df31dc/c893a/6.jpg 2290w" alt="" width="900" height="700"></picture></figure> 262<p>b) 5% of the total time is spent calling <code class="language-text">formatDate</code> (presumably from <code class="language-text">date-fns</code>) over and over. But there are no dates in the UI!</p> 263<p>Mistake? Invisible component?</p> 264<p>Or can <code class="language-text">formatDate</code> be replaced with a cheaper <code class="language-text">date.getHours()</code>/etc + concatenation?</p> 265<figure class="media-container"><picture><img src="/static/035d6b8edeedc2892581b1d3d3c4d059/7293b/7.jpg" srcset="/static/035d6b8edeedc2892581b1d3d3c4d059/7dcb8/7.jpg 225w, 266/static/035d6b8edeedc2892581b1d3d3c4d059/cb709/7.jpg 450w, 267/static/035d6b8edeedc2892581b1d3d3c4d059/7293b/7.jpg 900w, 268/static/035d6b8edeedc2892581b1d3d3c4d059/cad38/7.jpg 1350w, 269/static/035d6b8edeedc2892581b1d3d3c4d059/251e3/7.jpg 1800w, 270/static/035d6b8edeedc2892581b1d3d3c4d059/c893a/7.jpg 2290w" alt="" width="900" height="700"></picture></figure> 271<hr> 272<p><strong>5) There are styled-components!</strong> And theyâre a bottleneck here! Oh boy, this is my favorite one.</p> 273<p>Look, so with styled-components, you write a lot of code that looks like this:</p> 274<div class="gatsby-highlight" data-language="javascript"><pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> Button <span class="token operator">=</span> styled<span class="token punctuation">.</span>button<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> 275 color: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token operator">=></span> props<span class="token punctuation">.</span>color<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">; 276</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre></div> 277<figure class="media-container"><picture><img src="/static/76919596b718685fd8f5d427fa289134/7293b/8.jpg" srcset="/static/76919596b718685fd8f5d427fa289134/7dcb8/8.jpg 225w, 278/static/76919596b718685fd8f5d427fa289134/cb709/8.jpg 450w, 279/static/76919596b718685fd8f5d427fa289134/7293b/8.jpg 900w, 280/static/76919596b718685fd8f5d427fa289134/cad38/8.jpg 1350w, 281/static/76919596b718685fd8f5d427fa289134/251e3/8.jpg 1800w, 282/static/76919596b718685fd8f5d427fa289134/c4f36/8.jpg 3104w" alt="" width="900" height="529"></picture></figure> 283<hr> 284<p>When you mount a <code class="language-text"><Button></code>, styled-components call a function called <code class="language-text">generateAndInjestStyles()</code>. It generates buttonâs styles and injects them into <code class="language-text"><head></code>.</p> 285<p>If you mount another <code class="language-text"><Button></code>, styled-components would reuse existing styles for perf reasons. Unless you change them!</p> 286<hr> 287<p>What happens if you render a bunch of</p> 288<div class="gatsby-highlight" data-language="javascript"><pre class="language-javascript"><code class="language-javascript"><span class="token operator"><</span>Button color<span class="token operator">=</span><span class="token punctuation">{</span><span class="token function">randomColor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span></code></pre></div> 289<p>?</p> 290<p>Each button will have unique styles. styled-components will have to generate and inject separate CSS for each button. This is cheap for one button, but for 100 of them, and on every render, this adds up.</p> 291<hr> 292<p>This is apparently what happens in Spotify (although of course with some different c
292omponent).</p> 293<p>The typical solution here is to use inline styles instead:</p> 294<div class="gatsby-highlight" data-language="javascript"><pre class="language-javascript"><code class="language-javascript"><span class="token operator"><</span>Button style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token literal-property property">color</span><span class="token operator">:</span> <span class="token function">randomColor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">></span></code></pre></div> 295<hr> 296<p>6) Thereâs a whole lot of other stuff going on in the performance pane. But with minification, itâs hard to figure out if any of it is actionable! (Also itâs 2 am so I gotta stop.)</p></div></article><div class="styled__BottomMeta-sc-g87c0z-3 bWLCcb">Published<!-- --> <time dateTime="2022-05-05T01:00:00.000Z">5 May 2022</time></div><div class="styled__Container-sc-1pidu4x-0 fTqJyl styled__MailchimpSubscribe-sc-g87c0z-5 loPRVe"><p>Performance articles, case studies, and more. A new email every once in a while:</p><form id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="styled__MailchimpForm-sc-1pidu4x-1 YNXaB" action="https://iamakulov.us15.list-manage.com/subscribe/post?u=d7d2af05c405078e8f6a48956&amp;id=6c7cabbc15" method="post" target="_blank"><div><input placeholder="Your email" type="email" required="" class="styled__MailchimpInput-sc-1pidu4x-2 ealAEm" name="EMAIL" value=""/><input type="submit" class="styled__MailchimpSubmit-sc-1pidu4x-3 celNKA" value="Subscribe"/></div><div aria-hidden="true" class="styled__HiddenDiv-sc-1pidu4x-4 hSVmgK"><input type="text" tabindex="-1" name="b_d7d2af05c405078e8f6a48956_6c7cabbc15" value=""/></div></form></div><ul class="styled__Container-sc-exfs5j-0 jViMaS styled__BlogFooterAccordion-sc-g87c0z-6 jHbsYy"><li class="styled__Item-sc-exfs5j-1 bHlTQw"><a href="/talks/web-perf-101/" class="styled__ItemLink-sc-exfs5j-2 chErgn"><span class="styled__Container-sc-1ekqqun-0 ewhQKw"><picture><source srcSet="/static/ebdda6f2dea722987bbbfe64f77a7713/1de70/web-perf-101.webp 231w, 297/static/ebdda6f2dea722987bbbfe64f77a7713/89631/web-perf-101.webp 462w" sizes="231px" type="image/webp"/><img src="/static/ebdda6f2dea722987bbbfe64f77a7713/64756/web-perf-101.png" srcSet="/static/ebdda6f2dea722987bbbfe64f77a7713/64756/web-perf-101.png 231w, 298/static/ebdda6f2dea722987bbbfe64f77a7713/09d6e/web-perf-101.png 462w" sizes="231px" loading="lazy" alt="" width="231" height="130" class="styled__Img-sc-1ekqqun-1"/></picture></span><div class="styled__LabelWrapper-sc-exfs5j-3 lacEJS"><span class="styled__Label-sc-exfs5j-4 kZXEoD">Web Performance 101</span></div></a></li><li class="styled__Item-sc-exfs5j-1 bHlTQw"><a href="/talks/react-concurrency/" class="styled__ItemLink-sc-exfs5j-2 chErgn"><span class="styled__Container-sc-1ekqqun-0 ewhQKw"><picture><source srcSet="/static/6c41576701f7901f2be352b4a89146c3/1de70/react-concurrency.webp 231w, 299/static/6c41576701f7901f2be352b4a89146c3/89631/react-concurrency.webp 462w" sizes="231px" type="image/webp"/><img src="/static/6c41576701f7901f2be352b4a89146c3/64756/react-concurrency.png" srcSet="/static/6c41576701f7901f2be352b4a89146c3/64756/react-concurrency.png 231w, 300/static/6c41576701f7901f2be352b4a89146c3/09d6e/react-concurrency.png 462w" sizes="231px" loading="lazy" alt="" width="231" height="130" class="styled__Img-sc-1ekqqun-1"/></picture></span><div class="styled__LabelWrapper-sc-exfs5j-3 lacEJS"><span class="styled__Label-sc-exfs5j-4 kZXEoD">React Concurrency, Explained</span></div></a></li></ul><div class="styled__Container-sc-fmk9on-0 cuFkco styled__Footer-sc-g87c0z-7 kMmgzr"><div class="styled__Credentials-sc-fmk9on-1 qJRRG"><span><a href="/">PerfPerfPerf</a> · 2017â<!-- -->2026<span> <!-- -->· License:<!-- --> <span class="styled__LicenseName-sc-fmk9on-3 ecDLDl"><a href="https://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA</a></span></span></span><span>ð¤</span></div><div class="styled__Legal-sc-fmk9on-2 eMPHzj">Sole proprietorship (eenmanszaak). Amsterdam, Netherlands. KvK no. 86522469. VAT ID NL004265772B46.<!-- --> <a href="/legal/terms/">Terms and Conditions</a>.<!-- --> <a href="/legal/privacy/">Privacy Policy</a></div></div></div></div><!--/$--></div><div id="gatsby-announcer" style="position:absolute;top:0;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;
300border:0" aria-live="assertive" aria-atomic="true"></div></div>
300<script id="gatsby-script-loader">/*<![CDATA[*/window.pagePath="/blog/spotify-1am/";/*]]>*/</script>
300<!-- slice-start id="_gatsby-scripts-1" --> 301
301<script 302 id="gatsby-chunk-mapping" 303 > 304 window.___chunkMapping="{\"app\":[\"/app-7c7e0ed1706f68ec735d.js\"],\"component---src-pages-404-tsx\":[],\"component---src-pages-index-tsx\":[],\"component---src-pages-talks-quick-apps-index-tsx\":[],\"component---src-pages-talks-react-concurrency-index-tsx\":[],\"component---src-pages-talks-web-perf-101-index-tsx\":[],\"component---src-pages-workshops-index-tsx\":[],\"component---src-templates-blog-index-tsx\":[],\"component---src-templates-legal-index-tsx\":[],\"component---src-pages-index-tsxhead\":[\"/component---src-pages-index-tsxhead-2126d4c0e02f8903fe65.js\"],\"component---src-pages-talks-quick-apps-index-tsxhead\":[\"/component---src-pages-talks-quick-apps-index-tsxhead-30b771e3aa76436f65b9.js\"],\"component---src-pages-talks-react-concurrency-index-tsxhead\":[\"/component---src-pages-talks-react-concurrency-index-tsxhead-1031fb7d597c3ca2967f.js\"],\"component---src-pages-talks-web-perf-101-index-tsxhead\":[\"/component---src-pages-talks-web-perf-101-index-tsxhead-4b5467be3f8cb064501b.js\"],\"component---src-pages-workshops-index-tsxhead\":[\"/component---src-pages-workshops-index-tsxhead-df6431b0b285543a848f.js\"],\"component---src-templates-blog-index-tsxhead\":[\"/component---src-templates-blog-index-tsxhead-3fe94935e24b77395474.js\"],\"component---src-templates-legal-index-tsxhead\":[\"/component---src-templates-legal-index-tsxhead-d2339914f3d2831f6f13.js\"],\"node_modules-gatsby-link-dist-index-modern-mjs\":[],\"src-components-Logo-index-tsx\":[\"/src-components-Logo-index-tsx-b3f4f80591c34dfcdb67.js\"],\"node_modules-gatsby-script-dist-index-modern-mjs\":[],\"src-components-Layout-GlobalStyle-tsx\":[\"/src-components-Layout-GlobalStyle-tsx-7a4e3f3590993d818200.js\"],\"src-components-talks-AnimatedSlide-index-tsx\":[\"/src-components-talks-AnimatedSlide-index-tsx-d13f034165ea3f07dafe.js\"],\"cache-slice-js\":[]}"; 305 </script>
305 306
306<script>window.___webpackCompilationHash="5aa3833b247eab3dbd36";</script>
306<script src="/webpack-runtime-eaec3bb8172c552516a3.js" async></script>
306<script src="/framework-f2732454a48ad2e2fc2d.js" async></script>
306<script src="/app-7c7e0ed1706f68ec735d.js" async></script>
306<!-- slice-end id="_gatsby-scripts-1" --></body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.