PageSourceSearch

https://3perf.com/blog/spotify-1am/

html 3perf.com collected 2026-10-03 19:46:41 UTC 44,502 bytes, 306 lines download raw bytes

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&#39;s interesting how slow some &quot;desktop apps&quot; to do things like switch between playlists that are already loaded on my machine. Feels more like a &quot;website&quot; than an &quot;app&quot; <a href="https://t.co/DiLksaHWTl">pic.twitter.com/DiLksaHWTl</a></p>&mdash; 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">&lt;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">&lt;head></code>.</p>
285<p>If you mount another <code class="language-text">&lt;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">&lt;</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">&lt;</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;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.