Video Summary and Transcription
Performance is a puzzle that requires different approaches for different problems and sites. User feedback is crucial in evaluating performance, rather than relying solely on metrics like Lighthouse scores. Measuring performance and identifying issues can be done through tools like the performance tab and user timings. Understanding the main thread and using tools like React Profiler and Chrome Tracing can provide insights into performance problems. Optimizing performance involves doing less work, avoiding main thread blocking, and considering options like virtualization and Canvas. Communicating the impact of optimization to leadership and exploring different uses of Canvas are also important topics discussed in the Talk.
1. Introduction to Performance Talk
I'm here to give a talk about performance. Performance is not prescriptive at all. It's a puzzle, and I'll give you the tools to crack it. Different problems and sites require different approaches, from generic landing pages to complex applications like Photoshop in the browser.
I'm here to give a talk about performance. They asked me what, and because three-quarters of the things that I say come from like stepbrothers or Ricky Bobby, I was like, if you're not first, you're last. But then I thought about it, and it kind of works. If you've seen the movie, when Ricky Bobby's dad dips, the last thing that he tells him is, if you're not first, you're last, and he bases his entire life around it, and everything he does is based upon that shit, that firm belief in that, until later, when his dad comes back and says, what are you talking about? I was high when I said that. But that's a lot like web development in general now, where somebody will say something and Everybody gets on Twitter and parrots it and it's actually like 50% applicable, but largely bullshit.
I guess the point I'm making is, I'm going to talk about performance today, and performance is not prescriptive at all. Of course there's some things that you can do, some standards put in place, but largely it's a puzzle. It's research, figuring out what the problem is, and then coming up with a fix to that so I can't tell you there's any given thing. I'm just going to give you the tools that you can use to crack that puzzle yourself, and this is what I do almost every day, and it's fun as shit, so hopefully after this you give it a shot.
There's different problems, there's different sites, they do different things. In reality, what you have is you kind of have a sliding scale, from your generic AI thread boy landing pages, to shit like Photoshop in the browser. So when you're just making a landing page site, sure, a lot of these standard recommendations are applicable. But when you're making fucking Photoshop in the browser, obviously you're going to run into a couple different problems, because you're actually doing things, and you actually have users.
2. App Performance and User Feedback
When it comes to app performance, there's a sliding scale from generic landing pages to complex applications like Photoshop in the browser. While standard recommendations apply to landing page sites, more complex apps require different approaches. Lighthouse scores may not always reflect success, as companies like Amazon, Facebook, Twitter, and Target prove. Instead, it's crucial to prioritize user feedback and address their actual pain points.
In reality, what you have is you kind of have a sliding scale, from your generic landing pages, to things like Photoshop in the browser. When you're just making a landing page site, a lot of the standard recommendations are applicable. But when you're making something like Photoshop in the browser, you're going to run into different problems because you're actually doing things and you have users.
So what makes an app performant? If you ask a lot of people or Google, they're going to tell you about Core Web Vitals, loading, interactivity, visual stability. Everyone wants their Lighthouse score. But when you actually look at the Lighthouse scores for Amazon, Facebook, Twitter, and Target, they didn't get their Google Good Boy score. Yet, they make millions, billions of dollars every month. What matters is what your users think and what they're doing.
If you work on a thing, go to Twitter, search that thing, and then search 'sucks'. You'll see how users feel about it. Nobody's complaining about cumulative layout shift. They care about the actual experience. So it's important to focus on what matters to your users.
3. Performance Measurement and Optimization
Everybody wants their Lighthouse score, but what really matters is what your users think and how they feel about your app. The most performant thing you can do is have your app actually work. When it comes to problem versus optimization, sites need to load fast and avoid issues like crashes and slow performance. Introducing the MF system: measure and fix.
By the way, how readable is this? Is it kind of readable for everybody? Yeah? I'm like borderline nauseous, I'm inside of a ball. I don't know. Yeah, so everybody wants their Lighthouse score. But when you actually look at it, these are the Lighthouse scores for Amazon, Facebook, Twitter, I guess it's X now, I'll still call it Twitter, and Target, respectively. And they did not get their Google Good Boy score. But they make millions, billions of dollars every single month. So, you know, it largely doesn't matter. What does matter is what your users think and what they're doing. So if you actually, if you work on a thing, go to Twitter, search that thing, and then search sucks. And you'll see how they feel about it. And nobody's ever like, there was a fucking cumulative layout shift. No. So I used to work on Walmart, and I was like, yeah, let's say like Walmart website sucks. And in here, I'm actually impressed at this level of reporting here because usually they say it sucks, but this guy's like, it wouldn't even add to a cart. That's fucking actionable. I was trying to make a purchase for the last two hours, now it's out of stock. I love it. It's amazing. But the most performant thing that you can do is have your app actually work because that's what pisses people off. Facts. And if people don't buy shit then I'm going to have a job. Which brings us to problem versus optimization. If you have a site, obviously you're going to want to make it load fast, you're going to want to avoid reflow, proper image size, and not taking too long, but when you have a wild ass app, you can run into the kind of things like the app crashing, or it being visibly slow. I have this mythical shitty cell phone that stuff doesn't load on because I'm in the middle of the woods or some shit. Actual it's slow for a reason that's not the network. It mems out, or you drop frames. So, we want to solve those problems. And I'm going to tell you how. I'd like to introduce the MF system. Why is that funny? It's a simple thing that I like to call measure and fix.
4. Measuring Performance and Identifying Issues
Let's get started with measuring. The performance tab provides valuable insights into real problems in your app. The CPU section shows different causes of spiking, with red indicating issues. The network section highlights the different parts of your site and identifies shenanigans. Frames indicate frame rate performance, and extended periods of dropping frames are undesirable. User timings play a crucial role in performance evaluation.
You measure, and then you fix it. So, let's get started with measuring. Everybody who's tapped that performance tab say yeh. That didn't sound like everybody. This is the dopest tab there is, except for the console, which I use all the time instead of debugger. But if you actually hit that little record button there, and then go do some stuff on your site, it'll show you what is going on, right? And I know a lot of folks personally watch them be intimidated by this, because this shit looks crazy. It's a wild, wild visualization. But when you take the time to just sit and look at it and figure out what those things are, it can be unbelievably helpful in figuring out real problems in your app.
So I'll just run through it. Up here is your CPU. And you can see the different color things on that graph. That's like different things that are causing that. I'll get to that in a little bit. But this is where you can see CPU spiking. If you're having a bad one, I don't know if you can see, I can't really cursor it, but you see that like, pink with the red up there on the right. That's not good. Anytime there's red, that's not good. You don't want that.
Below that, right, there's the network. So you can kind of see it. And the cool thing is you see all the different parts that your site, that like, come together. But you get to see them broken out to see where the shenanigans are. These are frames. You know, you hear people talk about 60 frames per second. Here you can see your frames. And see if you're dropping frames or if you have long frames. If you have extended periods of dropping frames, that's jank and your site looks kind of shitty. You don't want that. Timings. Who here knows what user timings are? Say yeah.
5. Using User Timings and Interactions
User timings are the shit. You can add your own custom measurements using performance.mark and performance.measure. These measurements provide valuable insights in the context of everything else happening. Interactions, such as clicks and scrolls, are important for tracking down issues. The main thread is where you should dig in.
Yeah. Okay. User timings are the shit. So imagine you have all these things that you can look at and it's like, you know, It's cool, you can kind of deduce what's going on there. But imagine if you could add your own.
This is a lot. This is a lot of stuff on the screen. I just want to know about this one thing. What's going on here? Here's what you do. It's built in right on window. You say performance.mark. Then you give a start name. Then wrap that around whatever you necessarily want to measure. And then you call performance.mark again. And then when you call performance.measure, first argument is the name of the measure, and then the following two are the start and stop.
What that'll do is, in your dev tools, you're going to get this sort of thing, like those little yellow things. And it's going to be custom measurements that you're going to have in context of everything else happening. So you'll be like, oh, yeah, the fucking edit card doesn't work. That guy on Twitter was right. But they're great. I use them a lot. And you should try them, maybe, if you want to.
Interactions is the next one. And that's important for kind of tracking stuff down. You'll see there, and you'll see like a click or scroll. And that's like, now you're on the trail. Dig in. And where does one dig in? Right here. Motherfucking main thread. Sorry.
6. Understanding the Main Thread
The main thread is where the party's going down. It's where all of your actual code executes. Understanding the breakdown of what's happening in each block is essential. Yellow indicates JavaScript, while purple and green represent rendering and painting. It's important to identify who's responsible for any performance issues. A funny story illustrates the prevalence of wild JavaScript causing problems. Running a profile can provide valuable insights.
So the main thread is where the party's going down. That's all of your actual code executing. Like, you have network, CPU, and shit like that. But if you want to see what's getting called, main thread. You also don't want to block that guy.
So when you're in here in this main thread, you can zoom in and out of it, and look at it. And more importantly, if you're on this Summary tab here, you can click those little nodes, or boxes, or whatever, and right down here in the Summary tab at least, you'll kind of get a breakdown of what's going on in that particular block.
So you have yellow, and yellow is almost always JavaScript doing things. That's just JavaScript doing its thing. And then you have rendering and painting, which is the purple and the green. And that's like the browser working. That's not like React rendering. So that kind of helps you understand if this is taking this long, who's responsible? I'll actually tell you a funny story about that, because most of the time you have a performance issue. It's just yellow. There's a lot of wild JavaScript going on. There's just a lot of shit happening. And one time my buddy calls me up and he's like yo. He's like, can I pay you like 20 bucks to hop on a call and figure this out? This site is like, ground to a halt. It's like crashing. I don't know what's going on. I'm like really? OK. We'll take a look. Like don't worry about the 20 bucks. I got you, dog. So I hop on. And I'm like, first thing I do. Run a profile. So I do. And there's no yellow at all. It's all purple and green.
7. Understanding React Profiler and Chrome Tracing
I'm like, what the fuck's going on here? He literally crashed his website with CSS. Measuring is key to figuring out the problem quickly. The React profiler provides valuable insights into renders and updates, including what caused them. The React profiler API allows for specific profiling, with the onRender callback providing helpful information. Chrome Tracing is another tool available for investigation.
I'm like, what the fuck's going on here? What did you do? He literally crashed his website with CSS. He had some animation and it was like relatively positioned or something. And it was like reflowing and constantly janking because something was like rotating. I was like, dude. I've never seen somebody break their website with CSS alone. This is incredible. I'm like.
But you know how I figured that out? Measuring. Other stuff you can do here, you have your bottom up. All right? And in here, you can see your self time, total time. You can see what is actually taking long and that thing. So it's like you start at 10,000 feet, but then you can really narrow it out of the problem pretty quickly and see what's going on. Same thing with event log, which is a little bit more sequential.
This is a React event. So it would be weird if I didn't talk about the React profiler, which is super duper helpful. Here, you see a profile in the React profiler. And we have renders taking place. And the best thing about this, this is the best thing in the entire world. If you see there on the right side, it says what caused this update? Absolutely money, because it will tell you exactly what caused the update and how long it took. This is using Next.js, so very little updates happening, just those little rascals. But it says, right? So what that actually is, is it's a scroll anchor on a page. It uses an interaction observer to find out when it's visible. And then when it's visible, it writes the text out, like fucking James Bond or something. That's what's taking place there. So it's six renders, it was like six characters. In addition to that, you have the React profiler API, which is kind of cool. In here, you can wrap this tag around stuff, like if you just want to profile one thing specifically. And you have that onRender callback, which will give you duration, base duration, start time, commit time, yada yada. Very helpful in investigations. And then there's Chrome Tracing.
8. Using Chrome Tracing for Performance Analysis
If you have a real brain tickler of a problem and want to find out what's going on, you can use Chrome Tracing. It allows you to profile Chrome itself and see how the browser's interacting. It's pretty wild stuff. You should try it out.
How many of you say yeah if you have actually used Chrome Tracing before? It's that weird. Yeah, so if you have a real brain tickler of a problem and you want to find out what's going on, so if you go to Chrome Tracing just like that, like we would go to Chrome bookmarks or something, it'll open this up. And you can actually profile Chrome itself and find out what's going on under the hood with like the SKIA rendering or the C++. You can actually go and see, like, well, that might be the cause of this. This is how the browser's interacting. It's pretty wild stuff. You should try it out.
9. Fixing and Optimizing Performance
So that's measuring. To make it fast, do less work. Think about loops. Convert four loops to a map and a filter. Create an index for constant time lookup.
So that's measuring. And I'm going almost over time here. So I have to get to fixing pretty quickly. Again, this is not prescriptive. I'm just going to provide examples of things that you can do.
So really, really, really don't block the main thread ever, as little as you possibly can. And as far as, like, how responsive you want it to be. I'm sure a lot of people heard about the 100 millisecond rule that interaction should be faster than 100 milliseconds. And it's because that's where they feel instantaneous. And that's a good benchmark. A lot of the other ones, they say, like, 200 milliseconds, 100 milliseconds. Just make it fast.
And the way to make it fast, one way, is do less work. And I mean that. I believe in that, wholeheartedly. Do as little work as possible, like, computationally. So if you want to get something done, say, how can I do this as tersely as human possible? So think about loops. There was a funny tweet the other day. Somebody talking about a senior engineer fucking converts four loops to a map and a filter. I'm like, and then I come back and turn that shit back into a four loop. Because you only want one iteration. So I'll show you one example of how you can do less work. So a constant time lookup. Oh, it's funny slow as balls, right? Yeah. So in that one, you're doing a find on this item meta. The top one. So if you're doing a find, what if item meta is like 10,000 things? That's going to take forever. It's going to be slow as balls. On the bottom one, if you create an index, so you create a lookup table indexed by the key. Next time you do that, it's just absolute instant access.
10. Optimizing Performance and Server Deferment
Applying principles to avoid unnecessary looping and blocking the main thread is crucial for better performance. Using workers can be a good option, but be cautious with data serialization. Defer to the server for data transformation whenever possible. Next.js and React server components make it easy, but if you can't use them, consider writing a proxy or using workers.
And if you apply those kind of principles where you're not looping whenever possible, you're going to have a way better time. Other ways to not block the main thread. You could take it off thread to a brand new one called a worker. In here, this example. Can I get a yeah for anybody who uses workers? Wow, not many people use workers. It's a pretty good option, but don't pass a lot of data to and from because serialization makes it not work properly. I mean, it works. It's just slow. So you don't want that.
But like here, we're just passing back and forth from the worker this make believe like sort field and a start and stop. And it's like data windowing. Next thing you can do is defer to the server whenever possible. If you're transforming data in the client, you don't need to do all that. You can just do that on the server. And this example is a Next.js example. We're using React server component type stuff. That makes it really easy. But I can't use Next.js professionally, which makes me sad. But a lot of people can. If you read Twitter, you'd think that everyone is using it all the time. But they're not. Just this tweet right here. They're talking about the amount of single page apps that are still out there and people still use. My buddy Brad said at React training, he said 95% of his clients want a single page app training in how to do this. And here's Brad's clients. So if you find yourself in that situation, where you can't use it, you could always write a proxy in between whatever backend you're using and your frontend, where you could do the work there. Or you could do it in workers or other options. You can't always just use RSCs. I would like to, but can't. Sad.
11. Virtualization and Memory Optimization
Another thing we can do is virtualization. Instead of rendering all the items in a list, virtualization allows you to render only what is visible. This is particularly useful for large datasets, as rendering thousands of items can lead to memory issues in the browser. Data virtualization or a view server can take this concept further by offloading the rendering to a server, reducing memory usage in the browser.
Another thing we can do is virtualization. If you aren't familiar with virtualization, if you look at the one with the x on it, here's a list, and there's a bunch of stuff on the list there. And it renders every single one of them, even though you can't see them. What's up? What's up? What's up? Are you good? All right, all right, all right. I'm just trying to wrap this shit up. Do you need anything? No, I'm good. I'm good. Get them. Yeah, so when you render all those things, if there's like 10,000 things, it's a problem. Because you're rendering 10,000 things. In virtualization, instead of rendering 10,000 things, you just render what is visible. So you render four things. If you want to do that, look at a React window if you haven't used it. So you won't have problems if you have a drop-down menu with 10,000 things in it. Because it'll only show four at any given time. If you have 10,000 or 100,000 things, now you start to hit memory issues when you're mutating that or doing anything in the browser. So you can look at data virtualization or a view server, which takes that concept to a whole new level where this doesn't even live in the browser, it lives on a server. And you say to the server, can I get row one through 75? And out of 100,000 rows, it'll just give you those. So you also keep your memory low in the browser at the same time.
Additional Options and Main Thread Blocking
Additional options are pushing it to the edge. PartyKit is a multiplayer, real-time library with unbelievably low latency. If you're rendering a lot of things in React that can't be virtualized, consider using Canvas. It's great for improving performance. Measure your performance, explore the tools, and fix any issues. Avoid blocking the main thread by profiling it.
Additional options are pushing it to the edge. Has anybody heard of a fine library called PartyKit? Yeah. Yeah! PartyKit is awesome. It uses the edge, and it's a multiplayer, real-time. And I actually primarily work with real-time. I don't do fetches. It's all real-time. And it is unbelievably low latency. If you want to have multiplayers going at the same time, I recommend you check it out.
And it wouldn't be one of my talks if I didn't make the finest recommendation, which is use Canvas. Can I get a yeah for who uses Canvas? Oh, yeah. So if you're rendering a lot of things in React non-negotiably, like you can't virtualize it, you're going to have a bad time. I've had things where little indicators, there has to be like 2,000 of them showing on a whole ass page at a time, and you just can't virtualize that. And if you have 2,000 of those elements and they're constantly updating and stuff like that, you're going to have a really, really, really bad time in React, let alone just DOM. Using Canvas is great. You should try it out if you haven't. I have, like, six stuff rendering, and, like, under seven milliseconds. It's unbelievable. So yeah.
If you want to fix your performance, first measure it, then look into some of the tools that I showed you, and figure it out. Thanks for coming to my talk. Woo! Woo! Woo! Woo! Woo!
First question, any tips on how to avoid blocking the main thread and how to identify if and what is blocking it? Profile it, right? Yeah. Yeah, yeah, yeah. I mean, if you're having issues with the main thread being blocked, just do that profiler recording and you'll see it. It gets super duper red. It's red everywhere. Yeah. I feel your comment, like, it's super intimidating. The first time you open it, it's like no, no. But if you take a moment and take a deep breath and put on your big boy shoes, you'll be fine, right? I brought my big boy shoes today.
Communicating with Leadership about Optimization
When it comes to communicating with leadership about optimizing and over-optimizing, it's important to focus on real metrics and the impact on the bottom line. While some e-commerce websites see a direct relation between performance and conversion, other websites may have different priorities. It's crucial to understand the specific use case and the potential benefits of optimization.
They're foam posits. Nice. All right, next question from Richard. A question disappeared on me. How would you recommend communicating to leadership about not focusing on optimizing or over-optimizing? Say that again. How would you recommend communicating to leadership about not focusing on optimizing or over-optimizing? Not focusing. So there's no focus. It's like two separate questions. Yeah, it sounds like there's not enough focus within their, within Richard's organization. Avoiding over-optimizing. Yeah, I think that generally speaking, if you have a performance problem, you'll know it. And it's more of a bug than a nice to have, right? Like, I think, unless you're seeing real metrics tied to it, you really shouldn't give a shit about what the lighthouse is telling you. With that said, there's caveats to this. Like I said, there's nuance. It depends. Like some e-commerce websites, like every 100 milliseconds that it's faster, they make like 7% more sales or some shit. Yeah, it's a made up figure. There is direct relation of performance to conversion in like an e-com space. So like, yeah, for there it might make sense to aggressively optimize to do that kind of thing. Other things, you know, there's certain websites that I go to, I wait for a loading spinner for the rest of my life until it comes up. It's worth it. Yeah. Yeah, but you're mentioning the e-commerce example. And there was one example from Amazon. I don't know the exact figures, but it was like 0.2 seconds shaved off and boom, 7% or something like that. And I would like a 7% pay increase, right? And Amazon would like that. So if I could do that. I mean, if you run an e-commerce shop, if you make an internal tool for people, you know, you're not making any money. Yeah, of course, yeah. Your use case depends, yeah.
Using Canvas for Various Purposes
It depends. Ooh. It depends. That's a senior, bro. How do you use Canvas? Well, you go ahead and get that Canvas, and then you draw shit. There are many ways to use Canvas, such as charts, visualizations, data grids, audio plugins, synthesizers, and games. It's good to be bad. I have whole-ass talks on Canvas if you want to learn more.
It depends. Ooh. It depends. That's a senior, bro.
All right. Principle.
Next question is from Anonymous. How do you use Canvas exactly? Well, you go ahead and get that Canvas, and then you draw shit. No, no, no. Look at you. You're a bad influence. No, no, I love it. I love it. I'm going to ruin this man's life. This is like my 10th conference, and I've never sworn onstage, so thank you. Good. Yeah. Try it more. It feels good. It's good to be bad. How do I use Canvas? I use it all the time. So there's a lot of ways that you can use it, and a lot of things that you can use it for. A lot of things like charts, visualizations, data grids. A lot of time I'll make audio plugins or synthesizers in the browser and shit like that. And I'll draw a lot of that. You'll have waveforms or things like that that are really easily drawn by that. Anything that needs a rapid updating, I make games in Canvas. I have whole-ass talks on Canvas if they want to look into that. Yeah. So I've got a little website.
Building a Web Browser with Canvas
I know a website built with Canvas. Yeah, do you? Littleplugmirror.com. It's all Canvas. Yeah. I decided to make React Canvas, where you use the React Native API and code like it's React Native, but it renders to Canvas. Chrome uses the same drawing library as Flutter, Skia, and it draws with Canvas. You have control over browser layout, building a web browser inside a browser. I use Canvas like an asshole. Thanks for corrupting me, Ken. It's been a pleasure.
I know a website built with Canvas. Yeah, do you? Littleplugmirror.com. It's all Canvas. Yeah.
So a while back, I decided I was going to make a thing called React Canvas, where you use the React Native API. You have views and text and shit like that. And you code it like it's React Native. But it actually all renders it to Canvas. And it worked. And it was awesome.
And then, I started like you do the first 90%. There's the other 90%. So I start filling in the blanks. And what ended up happening? I'm like, holy shit. I'm building a fucking web browser. Seriously. So yeah, it's funny. I don't know if you know or not, but Chrome, under the hood, uses the same drawing library that, I guess, like Flutter or some other shit use. It's Skia, right? And if you look at Skia API, Chrome is literally drawing shit with Canvas. It's Canvas.
So you have control over browser layout. Just imagine if you were making a website and everything was absolutely positioned. So then, you introduce a layout solver, right? And then you say, hey, this thing is here, and this is the property, and this is supposed to be relative, and this is width 100%. Then, the layout solver's like, bet. It's going to be like x0, y10, width 463. And you're like, sick. I'll draw it like that. And then, next thing you know, you're basically building a web browser inside of a browser. It's crazy. Very Inception.
The question, yeah. I use Canvas like an asshole. Well, with that, that's all the time we had. So thanks for corrupting me, Ken. It's been a pleasure.
Comments