 Beyonce will sing him on stage, let's go. All right, thank you all for hanging in there. I'm Alex, thanks Huijing. I do a bunch of things in this world. I'm a Mozilla tech speaker and a Mozilla raps mentor and what that means is I help other people volunteer for Mozilla, that's how I met Huijing. We have a bunch of people in Singapore ready if you wanna contribute with me up. Because I like the idea of a paycheck. That's gonna get recorded. Because I like the idea of a paycheck, I'm a JavaScript developer advocate at Nexmo. Has anybody heard about Nexmo before? Okay, Huijing, yeah. Huijing also works there, Huijing also works there. And I'm gonna talk to you about hands-on performance debugging tonight. Why am I doing this? Before being a developer advocate, I've spent seven years of my life building websites. Well, no, most of the time I spend debugging websites. The building part is easy. So I'm gonna try to debug the performance of a website. Now here's the kicker. I'll let you choose the website. I'm gonna debug tonight. There's no slides, everything is hands-on and I'll let you choose the website. So who wants me to, who has an idea for a website that can debug? Can I say Facebook? Facebook. No, okay. Okay, this is gonna be personal now, but then you'll see my Facebook profile. Okay. Carousel. Can someone help me type the U.N. alphabet? Yeah, dot.com. Okay, dot.com dot.sg. Right, so this is how it looks like. Right? Now, if I open DevTools, like everybody, when it talks about performance, it talks about how fast it runs. Let me tell you something. No matter how fast your JavaScript is, if it's 20 megabytes, it's still gonna be a good five seconds until it downloads. So when we talk about performance, I have three things I look at. And the most important thing, the first thing I look at is how fast is your user getting all the assets needed to run the website? No matter how fast your website is when it runs, it still needs to be all there for it to run. Now, I'm gonna do a clean one. Let me just, right. And I'm gonna look at the requests this page is doing. Now, because we live in the age of HTTP2, and you'll see most of the things in here have the HTTP2 header, it's being paralyzed. So there used to be a problem before HTTP2 with 1.1, where the browser can only do six connections at a time and whenever it connected to a new resources, it used to go to one by one by one and a lot of them were blocked in the queue. Now, you'll see if I go to my request, a lot are still blocked. The reason is HTTP2 works like a funnel. Instead of going to the server and saying, hey, I want this resource, you get it back, you go back again and say, I want this resource again. The round trip time doesn't happen now. You go and say, I need all these resources and then you open a funnel and it starts streaming all the resources to you. That kind of eliminates the problem with the rule of six. You can have one connection per host instead of having six connections at a time to the same host. The problem is there's a new rule of six. You can only have six hosts at the same time. The browser can only still do six connections. So when you have things like this that loads, oh, let's see how many domains. So it loads like eight domains. That means one of the domains, which is the main one, is gonna hold up one of the connections plots forever. And then the others get filled up when it hits six hosts, bummer. So this one actually has a lot of block times. If you look at the individual request, you can see the headers that it has. Headers are not really that important for performance, but you can look at the timings. The way an HTTP response works is you go to your DNS, your DNS gives you the actual IP address of the resource. You connect to that. You do the TLS handshake if it's HTTPS. After the TLS handshake, you send the data and you say, hey, I want this from you. Then you wait around for a bit until the server actually prepares what you need and then you receive that data. And if you look at my HTTP response, one random one, it's actually blocked in the queue. The first block part means there's too many connections happening on the browser, so I'm being blocked. I need to wait for an available connection slot. After that, the DNS resolution is fast. The connecting bit is quite okay, but the TLS handshake is taking a lot of time. Now, the reason why the connecting and TLS setup actually take a lot of time, usually it's instant, is there's, I'm being replicated to one of the servers that are not really close to Singapore. And means going to the domain name registrant and getting all I need takes a bit of time. Sending data and receiving data is instant. Do I wanna know how big the image is? 500 bytes. So the sending and receiving data is instant because it's so small, but I'm waiting around for the server for a good 20, 25% of the time. I'm waiting around for the server and it means the server isn't really fast. If the server was faster, I didn't have to wait around 10 milliseconds for it. Or even better, if it was static, I wouldn't have to wait at all. I'm getting an image that dynamically generated here. So if I improve all this, let me do size. So if I look at sizes, one of the, right, one of the ones that actually matters, it's one of scripts, it's 300 kilobytes. If I were to improve this, the whole load speed of the page would improve. Now this is an amazingly well-performing website and I have 1.38 megabytes of data to transfer and it finished in about a second. Facebook, for example, isn't as fast as this. So you look at the pages, like you look at the web page and the resources it loads. And that's the place where you can shave the most resources out of it, because if it loads in, so for example, there's this myth out there on the internet, that if your page loads faster than two seconds, your user is gonna think, well, it came from cash. It needs to refresh on it and it is the server again. But there's also the thing that's not the myth. If your page is slow and takes 10 seconds to load, your service has to be amazing for people to actually keep coming back to your website. And unless you're providing something that's actually indispensable, people are not gonna use it. Do I wanna know what Carousel does? Let's see what Carousel does. Cars and property fashion, home or living. It's a marketplace. Okay, okay. You came here without knowing what your host did? Okay, Chef Hans, who works for Carousel around here? Okay, right. So we looked at the network and how it loaded everything. This one was one of the very, oh, right. Looking at the network request, actually it's one of the really fast websites and it's performing well. One of the things I personally don't like about it is it loaded all the DOM content it needed from the first try and then it started loading a bunch of additional resources and it kind of doubled the load time. If you do server side rendering with all this, you can load everything in one go and DOM content loaded and load time kind of happens simultaneously and then you start with running your website. Because this one kind of loaded an empty shell, brought some more things and then started going, right? So I looked at network performance and this is where you can shave literally seconds off of your website's speed, which I think compared to in the grand scheme of things is the biggest chunk of it. What happens if you have a really good performing website like this one and you've managed to shave seconds? There's two more tools I'm gonna use. One of them is performance and the other one is memory. If you go to the performance, what performance does, it does performance profiling. The way performance profiling works is, it looks at the things that are running to make your website and then it starts recording them and then once you stop recording, you've got your profile or your snapshot of the profile. It looks at things like painting, memory, DOM interactions, everything. Now, because I'm really lazy, I'm gonna do one profile and how to do a profile is I'm gonna start recording performance. I'm gonna scroll around for a bit and then I'm gonna do a hard refresh, right? And after I've done this, I'm gonna stop recording performance. If you want to do this in an actual useful way, you should record more than one snapshot because the exceptions happen on a one by one basis. The data you get is exhaustive and you never know if this was a fluke that happened now or if this is something that keeps happening because you can't enhance the performance of a website 100%. You'll always have things that are browser dependent, client dependent and all that. So you'll record, my recommendation is record at least three of those, make a baseline out of the three and work with those. Now, if you're working a distributed team, if it's more than one developer, you can actually save these, save them and then import them later. So your entire team can work on the same profile that you're working on. The problem with the profiles is even the same machine, even the same things, recording two of them has a lot of variation and you need to focus on the common bits. Now, if you look at what I did, oh yay, set timeout. Everything that happened is kind of recorded. Every event that happened is recorded. So for example, there's a set timeout that keeps running and it's gonna show up in my page. I've got a bunch of DOM events here which is basically, why do I have a message? I have a bunch of DOM events that were triggered by the set timeout. And then as soon as I started scrolling through it, I started recalculating the styles on the page and applying the changes and then it did a repaint on my page. You've seen when I did the scrolling bit, it did a little flash, a little white thing. That's because a paint happened. I've scrolled some more, I've scrolled some more and this is what happens. Everything is color coded. So I see the DOM events and the set timeouts. Now, looking at this, there's a lot of DOM events for me just scrolling and none of them is the scroll. Most of it are messages being passed through the set timeout. I'm guessing you're doing long polling. What I would do is I'd keep the DOM events to a minimum. I tried to do set timeout. See, now I get to the scroll bit. This is user generated. This I did. The other bits, the message, that was me. That was the page. That's hogging up the memory that could be used some place else. As soon as I, let me, as soon as I do the refresh, you'll see, as soon as I do the refresh, you'll see my events start changing. I've got DOM events associated with the refresh and then I've got all these styles being applied. I have to say whoever's building this website, I've done this a few times by now. I haven't seen as many recalculating styles and the playing styles changes as you have. Congratulations. One of the biggest caveats, one of the biggest problems is, if you go down towards the very end of my recording, you'll see a bunch of recalculating styles applying changes. Nope. Okay, so I'm guessing the Carousel people don't really like me. I wonder what's happening. Right. Does the Carousel WiFi see 7.9? Yes, yes, yes. They've heard me in the back. 7.6. No, but the point is Carousel has been doing very well. Everybody please applause for Carousel. Wonderful front-end team. I have to admit, I've done this at JS Hong Kong a month ago, you can see the video on YouTube. Compared to that, this website is amazing. Amazing, applause. So what you see in most websites is this little part at the end, where you keep recalculating styles, reapplying the new styles, recalculating styles, reapplying the new styles. And that takes an incredible amount of time and resources from the graphics card. This is what happened when I did the actual refresh, which was a bunch of JavaScript was being called and a bunch of function calls happened. And that means the website, the load performance isn't amazing because you're doing a bunch of stuff when the user loads your page. If you did server-side rendering, you'd negate all that, you'd do all the initial work on the server, and you'd keep your client light and performant. And that means you could skip this entire bit of the client being laggy and painting and reflashing and painting and reflashing to never happening. Well, you'd run into this, which is a different thing, and you can't really deal with painting and reflashing and when you have a JavaScript website. You can avoid that entirely when it's static, when it's dynamic and things appear and disappear on the page, you can't really do that. For this, you can't really avoid it. Now, if you wanna look at other types of events, come on, oh, right, you can see the stuff in Red Hat to do with JavaScript memory management and stuff like that. For example, you can see DOM content loaded, which you can see even the line of JavaScript that made DOM content loaded trigger. One of the good things is you only see one of DOM content loaded, which is an improvement. There's websites out there which have multiple DOM content loaded, like this one. So what happens here is whenever you keep seeing the little icon in there, circling again and circling again and circling again, it means you dynamically input some HTML or JavaScript or CSS into your HTML document and the HTML document had to go through the entire document and reparse the DOM content in it and you'll see this DOM content loaded twice. Now, we'll assume you actually took care of the DOM content loaded bit and it works really well. This website, for example, has not a lot of performance problems, right? Let's see what happens when I look at specifically memory performance. So right now, I looked at network performance, it's really fast. It gets my elements on the client fast enough to run. I look at performance, performance isn't bad. JavaScript performance isn't bad. It keeps loading the stuff into the DOM which can be avoided. You can have server-side rendering so the JavaScript doesn't load out the JavaScript at runtime, which again, not bad. What happens when I look at memory? Because I've improved everything I can. I've improved speed, loading speed, I've improved running speed. What happens if I keep my website running for more than a minute, for more than a few seconds? I've got this one running in here for like a good four minutes now and if I look at the memory tab, I take a snapshot of my memory that literally goes and looks at my entire webpage and maps it to memory consumption and memory usage. It literally says, right, this little bit is taking up this much memory. Now, if you're running a good memory management on your JavaScript, that means using delete on your objects and stuff like that that you don't need, you shouldn't see the script part being so big. Well, you can avoid it. The object bit is the one that's the biggest variable. That's where your running JavaScript actually is stored. So for example, you can see you've got objects, a lot of functions, a lot of array. You're actually using call a lot, which I'm guessing it's the framework you're using and you should stop using call because that keeps memory tied in. The strings are basically everything that's not an object. You can't deal with that when you have big scripts, you have big strings. And this is the DOM. Basically, the shape of the DOM or the shape the DOM has to maintain in memory in order for it to work and interact with each other. Whenever there's an event happening, it goes to that part of the memory. The other thing is JS object group and JS shape. It's actually classified as other and that's because with the browser right now, being able to run things like WebAssembly and running C under the hood, there's a few things that permeate through JavaScript and go down to base functions of the operating system. And the other bit is JS implementation that's for example, this one's written in C that permeate through the browser. You can't do anything about that because it's the JavaScript things that you're using or the browser is using to render it. If you're using anything that's cutting edge or modern, you'll end up doing this. I see I have 36 seconds left, please. So in terms of this, you could balance out the script's bit to be a lot less and the object's bit to be a lot less. And that means every time your website is running or the more your website is running, the less memory it consumes so it doesn't lock up your entire thread. With 15 seconds left on the clock, I want to say thank you all. And I think I still have like five seconds to take a selfie if that's okay. Can I see you? Yeah. Right, questions? Thanks for doing my job for me, for like, auditing my website. This is what I actually do. My team, my team, not me. We have a team. Just now you were curious, you said that this website is good because it recalculates styles a lot. What do you mean by that? Is that a good thing, bad thing, and how do I? It doesn't recalculate styles a lot. That was what I said. It's good because it doesn't recalculate styles. I see. So you start recalculating styles and applying them when you start injecting things into your DOM that have styles attached to it. So inline styles, for example. Whenever you put something on it with inline styles, that's when you start recalculating a lot of shit. And a bunch of the framework you're using out there, i.e. React or whatever, when they add the inline styles, I know, I'm sorry to bash on the other speaker. But when you're, because the way the browser works is it has your document, it has your CSS, and then it starts mapping your CSS to your document. The second you introduce something new in the styles or something new in the HTML that affects styles, CSS specificity changes, and he goes, ooh, I have no idea what's happening because it can't diff stuff, so it has to recalculate everything. So whenever you introduce stuff like, right, I want a new button here on this page, or I want this property, this theme, I want to apply a new thing. For example, Mike was talking about teaming. Whenever you have a website that does teaming, it usually means it loads the default team and then it loads the second team. And when things happen. Yes, exactly, now with that, now with that. So when things like that happens, recalculating styles happens a lot, and that's bad because that's, it's not really performant, it's not really efficient, and a website can hold, you can avoid all that. I think I'm gonna stop here. This is very friendly, gentlemen. It's very friendly, super friendly. A applause, please.