 Welcome to this very special extended holiday edition of Supercharged and Paul. Santa Louis here, ready for Christmas. Santa, I recognize that name. And this is the show where I take the sites that you've submitted and I go through them and I try and find and fix performance issues. And today's no different, yay, merry Christmas. It's Slack, that's what we're gonna look at today. I like Slack an awful lot. And we have a Chromium Dev Slack, which will be the target for our performance profiling today. So I know I said to them, is there anything in particular that you're seeing and that you think we should look at? And they went, oh yeah, actually, there's this quick switcher, if you hit Command K, it takes a long time for it to come up on screen and we don't really know why. Fair enough, okay, well we'll start there. But as it happens, I think there might be a few other things that we see along the way. It's a bumper, it's the right time of year to give you extra. You know, I mean, look in the stocking, what's there? Oh, scrolling issues, oh, what's in there? Layout thrashing, oh, worst Santa ever. Bring me the mince pies, oh, oh. So what we'll do, we will hit record and we're gonna hit Command K and then we'll stop recording, yes. And we see the key down event over here and they are absolutely right. It is just shy of half a second in JavaScript terms here for the key down event. So the key down is me pressing Command K and it coming up on screen. So let's have a look at why. Well, I see these red triangles in the corner and I see a recalc style followed by a layout. So calculating styles on the page, followed by laying out elements on the page, followed by calculating styles on the page and then laying out the elements on the page, which seems superfluous at best. And actually, each one of these is really quite expensive. Like this first one is 93 milliseconds in calculating styles. So if we click on it, yeah, you see, just shy of 9,000 elements have been affected by this style change. That's an awful lot of elements that could be affected by a style change. You know, if you're gonna make some style changes, it's often quite good to be very specific about the styles that you want to apply, but it may just be that there's a lot of elements being added in this case, say to the page, for example, the quick switcher elements and that might be what the issue is because it's preceded by a power's HTML. So that makes me think there's new HTML coming in, it has its style calculations and then we force a layout as well. Same kind of deal except this has got 13,000 elements in play and again, 93 milliseconds and this is a fast desktop machine. This would be brutal on other devices. So big problem here then I guess. Now the good news is underneath, we actually start to get the call stack. So we can actually start to figure out why what was it that was called into that was triggering this problem and this is it here, there's clicking on apparently this anchor with book snag. I'm not sure what the deal is there, but it goes to jQuery, something to do with that. I'm not sure what that is. Then bootstrap with its modal and then modal show, modal backdrop, okay. And then eventually it seems to trigger and show. So something in this interplay between the roll-up client, the roll-up core and the bootstrap. Now it's gonna be very specific to them. Let's have a quick look at modal show just out of interest and it's minified. So again, for them out today would obviously go to your unminified and have a look around, do the same thing again. But if we start to see things like, yeah, add class, we're making a style change. We're basically making style changes. Yeah, we're reading a class. It has class fade, add class. So you start to sort of build up this picture fairly quickly that there's a check on styles followed by a mutation of styles. And then if somewhere later in that call stack, somebody else is reading a style and then writing a style, that's exactly what's gonna land us in this problem. Let's say it's their code. So I'd say, look, go and have a look at this. The call stacks are here. They will recognize their own code, I'm sure. And then it's a case of trying to pick it out and say, well, we should do all our reads up front, then all our writes. Libraries like Faston will do that for you, but you can still do it yourself. Just make sure that you're orchestrating your code very carefully. It can be tricky and that's why Faston exists because it will help you do that. And a lot of people use it very successfully. So that would be how I'd start for them. But while I was here, I noticed this update layer tree that comes straight after. Updating the layer tree is how Chrome organizes basically all the layers in the page. So where everything needs to sit in relation to everything else. And that's 73 milliseconds. That's monstrously long, really long. And again, especially so for such a powerful device. So what's going on? Well, layers is the answer, but how do we find out more about this? Well, we have a tool. We have a Chrome Dev tool. That's why it's called Chrome Dev Tools. Tools inside the tools. Switch on the paint profiler, hit record again. And what we'll do is we'll do a bit of a scroll. And I can tell you that that is pretty bad. We have to wait when we've got the paint profiler on. There's an awful lot of extra information that's coming in. So it does take a long time to pull that data in and actually parse it and get it ready for us to have a look at. So we have to do the happy dance. It's beginning to look good. Look, it's here. So what we can do is we can see six frames, five frames a second. And that's where the paint profiler on. So it would probably be near nine, 10 frames a second. Certainly not the 60 frames a second that we'd want. So if we click on the layers, the frame at the top, we get this layers tab that we can click into. This layer information is not yet available, but it does come up eventually. There we go. And we can make this a bit bigger. There we go. And we start to sort of see what all the layers are. That's all these boxes on the screen. And I'll tell you what we'll do is we'll just move ourselves back and we can spin this out into 3D space. Woo-hoo! Who doesn't love that? Nobody. There we are. Rotate. There we are. Look at that. That's great, isn't it? It looks like basically every single item in the Quick Switcher is getting its own layer. And that's going to be expensive to manage, I would imagine. We can confirm that, though, because what we can do is we can hit Escape and we would go to the rendering options. If they're not there for you, then you can go to More Tools, Rendering Settings, like that. And you can switch on Show Layer Borders. And yep, sure as we would expect, each one of these items in the list has got its own layer. And in fact, even the status icon inside has also got its own layer. And we can spin this down as well and inside the Omnibox, which is what that is. Yep, there we are. Omnibox item and then the presents. So basically the status. Now if we click on one of these items, we can see the reason that it got its own layer. ScrollParent is not an ancestor. No idea. Might overlap other composite content. Now that one, I can guess. That's basically, something's got a layer and one of these list items might overlap it. Okay, and then it says cannot be squashed because this layer has a different clipping container than the squashing layer. Yeah, this one. This one took me a long, long time to figure out when I was looking at this. I was like, oof. Yeah, even though I had to speak to a Chrome engineer and I was like, just what, huh? And they gave me a few hints and got to the bottom of it, which is good. It's kind of, kind of, is it going to work out? Who knows? It was an exciting time for me. It was. You always like that with performance work. You get thrown something and you're like, do some forensics. Will you solve the puzzle? Who knows? It's very exciting. That's why I do this. It's the question whether it is noble or in the mind to suffer the slings and arrows of outrageous fortune or to take arms against the sea of troubles and by doing so, back to the task at hand. Well, it turns out if you look at the container element. You have to scroll up for that apparently. There's a lot of them. There's a lot of them. I'm going to get there eventually. Got there. Okay. Omnibox results is the container element that's doing the scrolling. It has width, it has a height, but it has overflow y scroll and overflow x hidden. It's clipping that list, which is great. That's what we'd want it to do. That makes perfect sense. However, every single item inside the list, it too has overflow hidden. So each item is clipping its contents and what Blink does it goes, well, that's got its own clipping because it's overflow hidden. That clip doesn't match the parent's clip. Therefore, I'm just going to assume that it has to have its own layer because of that. So if we switch off overflow hidden on the children, all those layers disappear and we're going to get one big layer, which is probably going to be better. We'll switch on the timeline again, switch off the paint profiler so that it doesn't take all the extra information we don't need and we'll record and we'll scroll. Now we're getting something like 30 frames a second. So we're up from about, well, it's five, six, could be nine or 10 without the paint profiler, up to about 30. So definite improvement by having, in this case, one larger layer rather than, you know, hundreds or thousands of smaller layers. But that's still not 60 frames a second, which is what we'd want. So I see a lot of purple in this chart at the top and certainly that matches up with, yeah, about 12 milliseconds here of update layer tree, which is down from 20 odd, 24, 25, I think, to 12. So it's definitely better, but it's still not good. It should be a fraction of a millisecond, ideally speaking. So let's see if we can figure out what's going on. Well, again, we can switch on the paint profiler, do a quick run and see what's what. All we need is one of these frames. We'll go and wait for the layers. There we go. And we can see, we can actually see the list there. We'll reset the transform. You can see the list of items in the quick switcher. And yeah, you see here it's 66,266 pixels high. That's enormous. That's a huge layer that needs to be handled. And it's just probably putting blink under pressure. We can prove that, I think, by going through to the elements. And what we'll do is we'll select the Omnibox item and we will say display none. And that's going to give us nothing in the list, which is not so great. But what we can do is we can go and we can override that for a few of them. And so that we've got something to scroll. This is going to take us a minute or two. So we've got a few in the list now. So we've enabled like 10 of them or something like that. And so this list is basically nothing like the size it was. And we'll do another timeline recording. And we'll switch off the paint profiler here. We'll just have a go without. And we'll stop that. And yeah, we're basically at 60 frames a second now. And the update layer tree's gone from that 12, 13 milliseconds down to 3 milliseconds. So it's clearly the size of that layer is a big, big factor. But that still bothers me because it's still 3 milliseconds and it should be a fraction of a millisecond. So something outside of this quick switcher is probably causing an issue too. And my hunch is, having looked at this before, is it's going to be the actual content of the page. In fact, we can confirm that because what we could do is we could do a paint profile and we'll do a quick scroll of the page content. It is 60 frames a second. So we could stop here and that would be okay. But I would imagine that since this update layer tree is still quite big, we should see if we can figure it out. And yeah, so looking at this, the page dividers, we've got a message scroller div is 12,544 pixels. And the actual day divider, which seems to be the previous day's content, that is 12,000 pixels. That is 12,000 and so again. And by 10,000, so those are huge layers. And you can see that actually here. If we, let me get rid of that and we will zoom out. There we go. Yeah, there's the actual page in the bottom corner and this is what it is. I mean, even, there we are. That's what it actually looks like. There's the page content. We have another one here and the footer as well. For reasons I'm not quite sure why, but it seems to be that it is massive as well. So I guess if I were them for this and the quick switcher, I would say go to something that's like a recycler view where you've got a few much smaller DOM and your recycling elements. That means that the layout should be cheaper. The style calculations should be cheaper. Everything should be cheaper. And you can use something like request idle callback to only do those mutations to the DOM when the user's in idle and if you need to put up a spinner or something like that. Okay, but maybe you'd sort of take a slightly more nuanced approach where you use request idle callback or if it's getting quite pressing, you just do it immediately and you take the hit and maybe your frames per second will just waver a little bit. But it's certainly going to be a lot, lot better than having this huge set of layers that is just putting a blink under pressure here. So there you go. A bunch of stuff. The layers panel, the paint profiler, just dev tools in general and scrolling performance issues. Definitely want to take a look at this holiday season. If you find yourself with scrolling performance issues and it's not something like paint, it might be something like your layers. Check that out. Have a great holiday and I'll see you in 2016. It's exciting. Brand new year. It's a leap year.