 So, Paul, when we're building websites and tools, we want things to be fast. We want the page to load quickly. We want the user to have a good experience, to be happy when they use our site. But somewhere along the process when we're building our app, things start to get slower and slower, and I don't really realize it right away, but then all of a sudden I reach this point and I'm like, oh, my app is slow. Yeah. And then, I mean, you're like, you've got two problems. You've got poor performance, and now you've got the challenge of actually having to try and fix it. And like, from measuring correctly to understanding enough about the internals to make, you know, an educated guest to actually try that out and doing something like, it's not easy. Like, it's, this path is hard. Yeah, performance is hard. So, I'm Paul. I'm Sam. We're really into performance, like we're performance geeks, I guess. Geeks. Yeah, geeks. I don't know. Sure, performance nerds, you like that better? OK, anyway. Yeah, we're going to tell you about some tools, techniques, approaches, and workflows on making measurable and effective improvements in performance. There's some fresh tools. Fresh tools. Of course, fresh tools. Fresh tools. All right, cool. Before we get into some of the real world products, I want to kind of step back a little bit. You could think of performance as the art of avoiding work and making sure that any work that you do is as efficient as possible. Those are some sage words, Paul. They are sage words, so nice. Paul Lewis, actually, for this one is real good stuff. It's good. Yeah. So, I want to touch on kind of like the effective workflow for diagnosing and understanding performance. So, it all starts with the user. The user is the most important thing. You've got to consider where are they beginning and what is success to them. That is kind of your bounds for investigation. So, I sort of like put myself in that user head space. Yeah, you could like get like in the head, like right up in the, between the head space. Like his glasses and where his head is. Effectively, you could do that. Yeah, if you want. I'm in the head space. I got it. Great, I appreciate that. After that point, next thing is to measure. Measure with the profiler. Get an understanding of what sort of time we're looking at. This is key. You say that, like measure, but like meters, yards. And milliseconds. Nanoseconds? Sam, I'm doing a slide. After this, you interpret costs. You understand kind of like categorize, characterize the sort of work that is happening. Understand it. After this, identify the bottleneck. Drill into like what is actually happening. You might use specialized tool for this. Drill in and at that point, you can try a fix. You have a hunch, give it a shot. And for me, it's like, I just, I have a hunch. I sort of guess, just change something, refresh, change it again. Yeah, you wouldn't want to like... That's my trying. You wouldn't want to go like directly from measure to like try a fix. You don't want to like skip the rest of that. But yeah, and we always end up and we're like, that looks like it might work and that's fine. But then the key thing here is that you've got to return back to measuring again. You take that exact same thing that we were looking at before. You measure it, you understand what sort of change, what is the delta of the change that we actually made? So, okay, so I found this function that takes 10 milliseconds to run. I'm like, oh, I can go JS perf crazy on this and drop it down to one millisecond. Like this is awesome. But then I look at my total time to run and it's two seconds. Yeah, 2000 milliseconds and we made a nine milliseconds, like 2000 milliseconds down to 1,991. I mean, it's something. It's something. But... Oh, wait, right, because I'm in that user headspace. Yes. Behind the glasses. I'm like, oh, I can't even notice that. So it doesn't matter. You what? It doesn't matter. Well... I mean, to the user, it doesn't matter. Those nine milliseconds. Absolutely, absolutely. Like, what is going to be most effective for them? All right. So with that out of the way, let's get into some real stuff. And I think we're going to start out with the site Android Auto. Yeah. Website. Cool. All right, let's dive into it. All right. So I was looking at this site the other day on my phone and I loaded it. They were just, like, reloaded the page? Yeah, just Command R. And I saw that when the page loads in, I sort of see the spinner and then this green thing pops up and I see a header. Yeah, if you could, like, describe what is happening right here in kind of poem form for me. The green fields flow in. The spinner... No, OK, fuck. So, yeah. So we got this, like, situation. We got the top coming in. We got the bottom. We got this thing in the middle. And we're just waiting for the spinner, right? Yeah, and as a user, I'm like, I can't really touch this. I shouldn't touch this because it's spinning. It's loading. I'm just going to wait for it. Sure. OK, so I figured that, OK, there's probably a big image that's downloading and it's just taking a really long time. And so I'm waiting for that, probably. Yeah, yeah, yeah. So let's look at the timeline. OK. So I have this timeline recording that I did when I reloaded the page. And we can scrub over this. And we sort of see that initially we get this header painting in pretty much right away. And then we see our spinner. Actually, Sam, there's like a lot happening here. Yeah. Can you just, like, briefly tell me what all is going on? Sure. So here's, like, our JavaScript that's going on, our main thread activity. Good. Then here's, like, we see our frames per second and the green and then the red is, like, frames that took a while to paint. Like it. OK, but we'll just ignore most of that for now. Sure. So we're just going to go back. The screenshots. Yeah, just this film. Seems good. So here's that green field that you mentioned. Just sort of fade. Yeah, that's right. Poetic. I see why you wanted it. That's nice. Let's see our spinner. And then. Spinner. Then we get our image. OK. And, you know, that's, like. How long were we spinning? Let's see. So we're going to. Like, three seconds. Hold shift. Hold shift. Shift key. Drag. And we get to see how long that took. Yeah, good three. Almost three seconds. Three seconds of spinner. Spinning. This must be loading something big. I imagine, this is my guess, the header image, this shot with the car is, like, two megs or something. Like, I forgot to compress it. Yeah, it's just huge. All right. But, like, OK. So, but I'm not, I don't know that yet. So I want to. Guess. Guess. OK. So what do I do now? Wanted to figure out. What I recommend to you is there is a check box at the top of the screen now? Network. Network. Uh-huh. Good. Promising. Do it, do it. Whoa. All right. OK, so I see I have more in this crazy view. Uh-huh, uh-huh. Let's check this out. So basically here, we have the exact same network waterfall that you might see over in the network panel, but now integrated into this view. So the colors are pretty much images are generally green. Style sheets are purple. Script is yellow. Kind of matching the colors of the rest of the flame chart. But the nice thing here is we can begin to kind of coordinate what is happening on the network side of things and then the actual execution of what's happening on the main thread. OK, so we know that the image loads in around here. So let me find that, let me find that image. Scroll to the bottom. The 1 megabyte image. So you're saying that nothing on the network is happening between here and here? Nothing on the network is happening. We have two seconds of just nothing. Yeah. OK, let's look at the last thing to load. Sure. OK. Last thing? Click that. Yeah, we can bring up the bottom and see kind of a preview. OK, so that's an image. There's that one. There was the other one. Yeah, let's see what this, oh, yeah. Oh, there it is. OK. There we go. All right. There's our image. That's our image. It finished right here. Yeah, but then it didn't actually show up for 1.5 seconds. Hi. OK. Not sure. Yeah, that seems strange. So I guess at this point, we're a bit confused in this situation, right? Yeah, I don't know what's happening. We didn't build this site, unfortunately. And it's not every day that you're profiling in a site that you didn't have a hand in. So we had to do a little bit of digging in order to find what the story is with this image. Yeah, OK. Let's hop to. So let's look at the image. Yeah. OK, so I just hit Command-Shift-C, or you can use this. Yeah. Grab the element. And here's our banner image. Yeah, can you zoom in just a touch? Yeah. All right, check this out. See those data breakpoints? Yeah, I see those. I bet you got some kind of responsive images. Oh, right. Like media query thing. Yeah, yeah. OK. So they don't load the 2 megabyte image on your phone. Right. So they're probably using JavaScript to start that request, which is why it happened a little bit later on the page. They could be using a platform feature for resources. But they use JavaScript. Something, yeah, it's fine. OK. But now we need to understand what the connection is to the loading, the spinner. Yeah, like some JavaScript is doing something, right? Yes. I bet you, your bottom dollar, that if you, one of these classes here, JS header animate image, if I were to look at anything in particular, it would be that. All right, so I see it. I have it. Now what do I do? All right, go up to the, actually, use the new command menu, command shift P. Nice, nice. Hit search, type search. Yeah, yeah, we got a few things in here. So this is just going to search across all kind of the capabilities of the DevTools, just, you know, and keystrokes, and kick that up. It's just going to bring up the search across all files that we have. And, yeah, yeah, search. OK, cool. We have two results. Two results, looks like the page, our document, and one in some JavaScript. So again, let's check out what's going on in this JavaScript. OK, so it looks like the code's minified. Hit the button. Let's pretty print that. There we go. There we go. All right, good. All right, so we got this JS header animate image. Looks like it's signed to this. Yeah. Let's just hunt down kind of what happens here. Pink. OK, so we're in this function load content? Yeah, all right. So to be honest, I'm going to break a little bit here. We have done this before. It's not totally surprised to us. We have investigated this. There's a good amount of code here. And since Sam has understood what it does now, he's now going to explain to you what he has learned. OK, so we look at this. And we see we have a set interval here. So every certain duration, we're going to fire a function. Yep. And then I see this 1E3. 1E3. So I said, Paul, what does this mean? Because I know you've got like a math major or something. Yeah, yeah. It is called exponential notation. OK, and I did not believe him. So I copied that. And let's see. We go into our console here, and we just sort of paste it. Oh, it's 1,000. 1,000. Well, that is a fancy way to write 1,000. 1,000? Yeah. We have a set interval for every 1,000 milliseconds. Yeah, so every 1,000 seconds. What are we doing? And then we're checking to see if this header image has a class of loaded. Every second, we just pull to be like, hey, you loaded? Nope. Hey, you loaded yet? Nope. Hey, you. Yep, OK. Good. So then we're loaded, and then what? OK, then we're using this tween library, which is doing some animation. A little bit of transitioning. Fancy. And I saw we have a delay and this opacity. The delay, 1 millisecond? Yeah, I thought that too. And then I looked at the docs. That's a second. We're polling once a second to see if it's loaded. Yep. Then it's loaded, and then we're like, OK, great. I'm glad that you finished downloading. I'm glad that we have identified that you're loading. Now, before I fade you in, I'm just going to just pause and just hang out for a little bit. Just hang out for a second. For a second. Just chillax, wait, and then we'll fade it in. Yeah. That's fascinating. That is good. My dad once told me, he gave me some good advice for my career. He said, whenever there's problems, issues, a good way to rephrase the situation is instead of using negative words, you can say there's a lot of opportunities. And so I think we could all agree that there are some opportunities in this area where we could try some things. Potentially, we could improve this. Yeah, I think that there's some things. OK, so this accounts for why we have that gap. That big gap, yeah. Like that two-second gap of nothing happening. Yeah, so I think that many of us could identify a better way of handling this, not so bad. Before we move on, we've looked at the load aspect of this page, but I want to touch on a little bit of the interaction stuff. Sure. All right, check this out. I come back to timeline, I clear this up. And I want to look at some of the scrolling performance, the interactions, once I start using the page, right? Yeah, it makes sense. Good. Scroll down to the bottom, yeah, some of this stuff. It doesn't feel so bad like where I am right now. In fact, yeah, OK, yeah. So what I'm going to do is just capture a new recording. I'll just turn that guy off in the sky. There we go, cool. And record. And I'll just scroll, fling it. And I want to sign up for the mailing list, because why not? YOLO. Good? Good reference. All right, check this out. But what we have here, some new stuff. So along the top, right here, if I scroll in, always mouse wheel, mouse wheel is the trick. We have just identified what interactions are actually happening. Yeah, see the words there. Yeah, exactly, yeah, yeah. So yeah, exactly, fling. So scroll, I have my finger down. I'm moving it, fling, I let go. And it's just kind of gliding. Flinging. And we can even go over here. This actually, here is the response. You've heard us, we've talked about rail, measuring response. And so this is actually when I clicked on the sign up link and saw that. So we can open up the main thread again and kind of see this is all the JavaScript that was running. And if I zoom back in, I can open up and see some of the detail on this guy. And so check this out. So this is the actual gestures that the browser is handling kind of under the hood in order to handle this input. So what's that like that red line? Oh, I got it. So the red line. The red line, if we actually bring this up here, says time waiting for main thread. So what happens is basically the browser receives the tap. And then it's like, cool. But I just need a second because I might be busy and I have to have a moment. And then I'm going to totally evaluate this on the main thread and run the event handlers to handle that. So it's kind of like, hey, I just tapped you. But this is crazy. So execute your event handlers on the main thread, maybe? Yeah, I think it's like that, pretty much. We can rename that, right? Yeah, we could just put that whole description right here. Yeah, it makes more sense. Yes, sure. OK, good. So the other nice thing here is to kind of bring it back to what we were looking at before with the network activity, I hit that sign up form. We kind of waited, and then it's like, oh yeah, cool. You're all set. If I bring back network, the nice situation is we can also see a little bit of what is happening. So here you can see it on the minimap. You can kind of see the blue bar right here is actually, well, it's kind of the mini view of the network. And we can always open up to see some of the details of all of that. So it's nice to kind of get the interaction between main thread, network activity, and back kind of into a single view. Yeah, that sounds awesome. Seems good. Next one? Yeah, Android.o. All right. All right. This site, you introduced this to me. Tell me about the story of what we're going to look at. Yeah, my friend Tracy sent me a message, and he said, hey, I think my site is kind of slow. And I loaded it on my phone. I was like, yeah, it seems kind of slow. Can you take a look? I said, sure. So let's take a look. Yep, yep, yep. All right, so I have it loaded here. Who's that guy? It's me. Who's that guy in the picture? It's me. That's cool. All right. All right. Normal looking web page, right? Like, I don't know. It's like a bloggy content. A lot of videos, some podcasts, some stuff. Pretty normal. What do you want to look at? Well, let's just reload this page real quick. And I'm going to have the timeline go here. Yep. I just want to show you how it feels. Should we just say command R? Command R. And just capture the page. So it's loading. Cool. Still notice the spinner going? Yeah, it's still there. OK. So what's happening? I think it's finished. And this is, again, this is on my laptop. Yeah. Like with good Wi-Fi. Yeah. So it took a little over 10 seconds to load. 10 seconds, yeah, yeah, about that. For all of the stuff to finish. Yeah. But though if we look at kind of what's happening here, we roll that out. It looks like this image finally came in right around here, like eight and a half, eight seconds. Sure. And then some other stuff. No, but like when I look at this, I see this crazy amount of yellow. And I don't understand what's going on. Yeah, like there's a lot of pastel colors. What is happening? I'm not quite sure. So I'm just like, what? Yeah. Yeah. Actually, the different colors, it's colored by file. So each file gets a different color. Then kind of get a sense like this is this file, this is this file. OK. So there's a lot of files operating a little JavaScript. That's correct. Yeah, yeah, yeah. So I look at this and I say, OK, there's a lot of JavaScript. I can dive in and look at each function, but that would take a while. So I kind of want to group. Yeah, you probably wouldn't want to just start looking at this 20 millisecond slice. So we want to get kind of an aggregate view. If you wanted to kind of see that, try this. Hit the bottom up right down there. OK, yeah. So what we have here is this is basically a summary of all of the costs of that ran on the main thread. And this is across everything. So you might be familiar, say for instance, if we kind of flip this off and go over to no grouping whatsoever. If you use the Profiles panel and done kind of like a typical JavaScript profile, you'll see like the bottom up view and these are the JavaScript functions, et cetera. What we have over here, well, one thing when you do that, at the very top, you always see program and parentheses. And you're like, I don't know what that is, but it seems to be taking a lot of time, right? So that is actually revealed all here. So this tells me that we're executing a lot of JavaScript. Yeah, we're executing JavaScript. We are doing garbage collection. We're doing layout and recalc style and person style sheets, all these things. In addition to just running JavaScript functions, so there's a lot. So yeah, a good amount of work, all sorts of things. So this is a bit higher level than the diving in. A good amount. A good amount. OK, sure. But yeah, you switch that dropdown back to a grouping by domain because in this way, we can kind of just see by file, by domain, where our costs are. Good on a site like this where there's files coming in from different places. So we have this YT, which is YouTube, right? Yep, YT image is YouTube. And then we're spending almost two seconds in Add This code. Yep, yep. And we also got Chrome extensions on here too, which is nice because sometimes you want to actually see how much, like, what affect Chrome extensions that you have installed affect your page. That's a little handy. But yeah, these Add This and YouTube seem like a little higher. I get YouTube because these players, they have to construct each player and OK. But the Add This is weird to me. And I was playing around with the site and I saw that there's a button over here where you can click on the podcast and you get this little Add This widget behind a button. Wait, wait. The Add This cost, it's like two seconds. It's for, like, the share buttons that are kind of behind this click. Yeah, so it's a feature that's behind a click that, you know, primus users won't use. All right, OK. Two seconds. All right, all right, well, that's something. Well, Tracy wanted you to dig into this, so what do we do next? So what if we were to just disable the whole podcast stuff and just see what it feels like? It'd be good to just identify. We want to kind of reduce down and identify our key bottlenecks. And so yeah, it'd be good to take it out of the picture. So if we wanted to do that, what we could do is there's an experimental feature called request blocking where we can just say, like, just block these requests from going out completely. Oh, that sounds perfect. All right. So I'm guessing we'd go to network panel. And then look for pods. OK, so this seems to be the URL for these players. So you can right click and block request domain. And it's just going to kind of, yeah, the browser's going to not be able to issue these requests. So should we reload and capture the new thing? Yeah, let's do that. And I see that number jumped up to 13 here. So it's probably working. Yeah, exactly. Another thing that I will point out on our way over is we're doing this right now on our laptop. And the experience on a phone, like this is a responsive site, like it's the exact same thing that runs on a phone, it'll probably take a little bit longer than this. Like a little bit means a lot of it. Yeah, absolutely. So there's another new experimental feature that we can check out, and it's CPU throttling. So just like network throttling before, we were slow down things. Now we can actually slow down how much time everything from JavaScript to layout takes to evaluate inside the page. So I don't need to plug in my phone to sort of experience what it's like on a phone? It'll slow it down, and that's useful. You should, if you care about performance, still plug in your phone. But this will give you a nice push in the right direction. Yeah, it's cool. All right, so we go back to our bottom up group by domain. Yeah, so we blocked all those requests. And at this, we removed this. We did remove this. I like the joke. I worked on it. It's growing on me. I like that. All right, what are we at as far as time and all this? So we dropped down to seven seconds now. Until main thread is kind of chill. Yeah, until main thread's idle, and I'm going to guess that things were ready before. That's not bad. All right, good. But we're still paying this YouTube cost. Yes, the YouTube cost is a little bit interesting. And I think, how is the embed done here? There's just the iframes. Iframe, iframe, iframe. It's typical iframe embed. Right. Yeah, but putting myself in that user headspace, I was thinking as a user, I typically want to interact with the first video first, and maybe not the last one right when the page loads. So what if we were to throttle the instantiation of these and sort of lazily load them using something like Intersection Observer? Like, when they entered the screen, we could build them and defer the work. I love all of that. You should do that. OK. Turns out I did. All right. Good, good. Very good. So you want to show us? Yeah, I have it running locally with the patch. So you just got this private GitHub, and you just like cloned it, made a patch. Wasn't that big? No, it was really small, actually. I think it's just here. It's just like, I mean, this is a total hack, but we loop over all these videos, and we just build the player objects. Yeah, yeah, yeah. Do a little, you know what you could have done instead of set timeout in 150? Do a little 1.5.e.2, a real class here. That would have been cooler. It's a dimensional notation. That would have been cooler. All right, so that's easy enough. Yeah, let's measure and check it out. Yeah, let's do a little timeline. OK. A little bit, yeah. Yeah, it seems better already. It does seem cutoff. I don't know what's up with that cutoff bit. But like, based on this, it looks like our page, like that one that first frame gets painted in there. Yeah, just like from the top overview, it looks completely different here. OK, and it's sort of hard to keep this in your head to look before and after, so we made some pictures. So before it looked like this, like, we were really doing a lot of work. Yeah. Yeah, a lot of work. A lot of work. Work, work, work, work, work. That's good. Yeah. Doing some, and then afterwards, we dropped it down. And the nice thing here is, so there's the aspect of the fact that there's doing less work, and that's important. But we're also, like, at the same time as evaluating how much work we're doing, we're also looking at kind of how visually available is the page. Right, yeah. And like, a combination of things, right? Because if there's too much work, then as a user, you're not going to be able to scroll, interact with it immediately, because we're busy waiting for the main thread to call me, right? So here we brought it down, and yeah, not bad. We went from nine seconds to that paint when a user could think that they could interact with it. Four seconds. Not bad, not bad. Not bad. Not bad at all. All right, so Sam and I, we like web stuff. We like doing these websites. Like many JavaScript people in the room, we also do a lot of JavaScript work on the server side, node. We've been building some projects recently, and we like to use tools to make sure that the code quality is really good. One of our favorite tools is ESLint. ESLint's good. Make sure the code looks the same everywhere. I love it, because we were fighting about line lengths and quotes. Two spaces, two tabs. Yes, yes. It's nice to put that all to rest. But we run ESLint sometimes, and we run it on our project, which is not like crazy huge. No, it's like a couple hundred files. And it felt like it was not going kind of the speed that we wanted. It was seven seconds, actually. Time did. Yeah. Seven seconds. So we wanted to, like, this happens to us, and because we are kind of performing to geeks, you? Geeks. Yeah. You can't help sometimes. You're like, I was doing something, but I got to go figure out what's up with it before. You were texting me at 1 AM, and you were like, Sam, why is it so slow? I think I think it. Maybe. No, that wasn't it. So what we're going to show you, we're going to try and look at this together. But I do have to put out a little disclaimer. Wait, did they announce this yet? So I need you guys to keep. We're going to show you. If you can keep a secret. We're officially announcing this thing, like, tomorrow. But you get a little bit of sneak preview today, if you're quiet. So we're going to show it? So yeah, yeah. Basically, we wanted to take the developer tools and the profiling experience and these tools that we know from the client side and be able to use them in this back on experience with Node.js. So we're going to go check that out right now. Yeah, that's good. All right, so I have our project here. Yeah, this is ours. And I just want you to experience this lint. Hook it up. You ready? Hook it up. Running, right? Yeah, it's running. Yeah. That's good. That's good. I won this. I won the staring contest right there. You did. That's all I did. I couldn't take it. All right, we're finished. Took a little bit. That's a little bit. Yeah, anyways, yeah, it took some time there. Yeah, so this is let's actually measure it with a profile. Yeah, it was a little bit faster. Let's measure it with a profiler to see what's really going on. All right, so I'm using my Node binary and I'm passing two flags inspect and debug break, which is going to pause us on the first line of the program. And I'm just running our lint. Yep. So, OK, I get a URL here. So I can open that in Chrome. I have it open already. And we'll just reload this page. So we connect to our Node. So what we have here is the Chrome DevTools, modern Chrome DevTools. Inside of Chrome. Inside of Chrome. And we're just talking directly to Node.js. So this is my Node program. Or this is ESLint. Yeah, yeah. Notice, like, Node elements tab, whatever. Like, we don't need that. Yeah, that's pretty cool. We've got a job to do. We've got to figure out what's going on here. Profile this. Let's profile it. OK, so I'm going to go over to the Profiles tab and I'm just going to record this CPU profile. And as soon as I record the CPU profile, as soon as you hit start, yeah. It's going to unbreak point. It's just going to run our program. So let's watch for when our program exits so we can stop our profile. And we'll go ahead. You know that if you can use Command E to start and stop these as well, if you don't want to click. Little pro tip. Done. OK, let's take a look. OK. Ooh, look at that flame chart. That is a great flame chart. All right, some good colors on here. But that's a lot of work again. 12 seconds of work. 12 seconds. Yeah, yeah, wow. OK, so interesting. All right, we want to just characterize the shape of this. At the end over here, we got kind of, I don't know, we got this green kind of world and process text. And we're parsing probably the files. Like we're looking at what's going on in the file. Like we're actually interpreting them and linting. Yeah, like the stuff. OK, so it was in way out. Good. And now I see this other group here, Globsync. Globsync, big group. Globsync. What's Glob? I think it's what gets all the files. It says, give me all the files in the project. Pass them down. Got it. Lint some. Just give me the files. Give me the files. Hook it up. But this is six seconds. There's a lot. What's happening at the bottom of this? Like what is the actual stuff that is taking time? OK, zoom way in. Zoom a bit in. All right, it looks like we're doing like a reader and reader and Golobstar. Let's click in. Just click? Yeah, sure. Yeah? Wait. Seems good. Is this nice? This is the source code. Yeah, yeah, yeah, it's the ESLint source. And we're just going to view it now from the profiles. Yeah. Oh, that's pretty cool. It's nice to have that in Node. Yeah, it's good. Now, I think I don't spend as much time in DevTools as you, but these colors in the side look new. What is this? Yeah, this is brand new. This is line level annotations of all of the performance work. So basically, if you're over and you've taken kind of like a JavaScript profile and kind of you see all this stuff, the self time is the amount of time that you actually spend doing work inside of that function, those specific things, right? So we take those numbers and we actually say, hey, I want to know. I want to see what that looks like against my source code. And so like Globsync, right? And I'm just going to click in and see actually what is happening there. But not only per function, but at the line level as well. So we're able to see between functions and lines where I'm spending time on the CPU doing work. So it's kind of like a perf gutter. It's like we put the performance work in the gutter of the editor. It's like a perf gutter. It's like a perf gutter? Perf gutter. Yeah, it's like a perf gutter. Perf gutter. I like that. We can call it that, right? It's a thing. OK, I named it. IO 2016 Perf gutter. We're doing the work here. We're doing the work. Perf gutter. And actually in the other files that we have, the numbers are smaller, right? So all the work is happening in here, like in the kind of globbing we're moving around the file system. Paul Lewis once said, the performance is the art of avoiding work. And I feel like that is some work that we can avoid, right? Do you have any ideas on how we could, you know? Well, let's zoom way out here. And sort of look what's going on. And we see that it all kind of starts in this list files to process function. Stops down into this anonymous function, so let's click in again and see just what's happening. And this is a lot of code. It took me a while to read it. So you made me some artisanal, handcrafted, Paul Irish graphic. What's going on here again with the help of my graphics? Yeah, you're welcome. OK. So this is what's happening in that function block. We call ESLint, which is going to learn our code. It calls glob.sync on our project and gets all 26,000 files of JavaScript, which include node modules and all the vendor stuff. Yeah, third-party stuff. And then it passes each one of those files into this filter, which it reads in our ESLint ignore to know what to not pass on, like node modules. And then at the very end, we get 30 files. It's like, lint these 30 files. Does it, yeah. So that's something. That's cool. That's one way to do it. That's fine. Is there any way to improve it? Well, I was looking at the glob options because doing the filtered ourselves seems like too much work. And glob takes an ignore. Ooh. You can give a black list of what should be ignored to the glob function. Yeah, so it's like, hey, should I even look at the node modules folder? And it just doesn't. It doesn't. Oh. That seems like a good approach. Yeah, it does. So ideally, it might look like this. We call ESLint. It reads in our ESLint ignore, constructs this filter object, it passes that to our glob.sync, and we get 30 files. Yeah. And the nice thing here is that we were looking at all that self-time doing the traversal and stuff. Now it's like, node modules? Nope. I'm going to skip that big bunch of files and stick to the project. OK. So that seems good. Let's try it out and measure it and see. So I have a branch where I've actually made this patch already. I like it. OK, here we go. So let's rerun our profile and see what kind of impact this had. Run it. So back to that measure step, right? Measure it again. So here we are in the source. Let's start our profile. You know you can hit Command D. OK, we're finished. Wait, wait, wait, what? Yeah, we're done. Wow. OK, cool. Yeah, I still see that green area where it's doing the linting at the end and then that bit before where that bit before it. But there's no blob anymore. I mean, I think it's in here. I think it's there. Oh, there it is. Oh, wait. That's nice. 144 milliseconds now. That's good. And so before we're looking at, well, it's like 11 seconds in total for that run. That's pretty good. All right, cool. So for our project, we'll just hack that thing. Yeah, I can email you the patch. OK, I'll play it. Maybe we should contribute it back to the community. I have to open a pull request. It's the right thing to do. I have to take pictures and attach them and write words and choose at least four emojis. There's some work there. I know we're busy with this, but maybe later, you could do it. OK, I'm just going to say that I started. I started doing it. Oh, good. Like, sooner the better. All right, you want to do it now? Yeah. Do it now? Yeah, I would just do it now. OK, here we go. Oh, all right, rad. All right, so note the unicorn emoji. Always the unicorn emoji. Those are good. Smart stuff. Not bad. So interview, Paul, what did we learn today? Yeah. What did we go over? Good amount. From being able to coordinate between what's happening on the network activity in the main thread, understanding, categorizing the kind of work that's happening, understanding the interactions that the browser is receiving and coordinating that with my work, and then being able to take all that kind of performance stuff and then actually be able to use the same kind of stuff in Node.js. It's pretty awesome. Some good stuff. Some good stuff. So yeah, we're really excited about some of this stuff. Happy for you guys to start using it. Let us know what you think. Some good things. If you have any questions, you can find us on the internet. That works. Yeah, cool. Thank you guys very much. Appreciate it. Thank you.