Identifying the Bottleneck0:00
(upbeat music) Okay, so we identified that online count is the most expensive component in this app because it makes a database query. It literally makes a blatant database query, which again, is supposed to represent slowness in a component, you'd probably not put a query like this right in a component. I don't know, maybe you would. All right, so what this does is it shows us
I don't know, maybe you would. All right, so what this does is it shows us the current online user count. It goes in the database and it looks for users last logged in at timestamps and it makes that assessment, okay? So that's expensive, 205 milliseconds is spent on it. No bueno, we have to fix that, okay? So when you want to optimize something with Blaze, you wanna reach first for the most effective thing,
Considering Folding First0:39
So when you want to optimize something with Blaze, you wanna reach first for the most effective thing, which is folding. Folding will make everything the fastest because as you saw, that's pre-rendering. There's zero overhead, almost zero. So we wanna fold, but you can always just think about, now that you understand how Blaze works, you can think about it logically. Like, can we fold this component?
you can think about it logically. Like, can we fold this component? Because if we do, whatever is contained in here is going to be basically frozen in time. And as you can see, this is kind of a time-sensitive thing. It tells you how many current users are online right now. So you should develop this instinct that that's not really something you should fold. I'll demonstrate that to you just so you can get more of like a feel for it.
Folding Breaks Freshness1:18
I'll demonstrate that to you just so you can get more of like a feel for it. Okay, so I say fold true, I do A, V, C, okay? I refresh the page. And let's see how many users are online, 55. 'Cause it is actually changing every minute. So whatever, 55 users, okay? Now, I'm going to Artisan Logout. I added a little command that just wipes all of the user last login dates.
I added a little command that just wipes all of the user last login dates. Now we refresh and take a look at this. It still says 55 users are online. Even though in the database, I know that's not true. And if we search through our storage framework views, those cached views, and let's search for 55 users, you'll see that there it is. We folded that component. So it's frozen in time, the snapshot is right here.
We folded that component. So it's frozen in time, the snapshot is right here. 55 users online now instead of the database query. So for as long as this app lives on the server without the view cache being wiped, this is the value that will be stuck there. So obviously it's much faster, like look, you don't even see it in here. The whole page loaded in 121 milliseconds instead of 240 or something like that.
The whole page loaded in 121 milliseconds instead of 240 or something like that. So we saved the time, but obviously we broke it because we can't fold. So I hope that really sinks in that like, you always want to reach for folding, but you have to think through, can this thing be frozen in time? Is there things that are dynamic? Is this relying on what the current URL is?
Is there things that are dynamic? Is this relying on what the current URL is? Is this relying on something from the database? Basically, if this is its own little world, is it looking outside itself to the greater universe? Like this, like looking to the database, then yeah, you shouldn't fold it. But if it's self-contained, then you can potentially fold it. There's other things to think about, which we'll get to.
Using Memoization Instead2:55
then you can potentially fold it. There's other things to think about, which we'll get to. But it's all logical with all the knowledge that you already have from building that toy component. So we can't fold it. This is where we, this is where memoization comes in. Memoization is basically a fallback that's like, maybe there's still some optimization we could do if we can't fold. And so this is a case where we can memoize
if we can't fold. And so this is a case where we can memoize because memos only last per request. If you recall, it's like caching, but it only caches for the duration of the single request. And we don't need that information to be fresh for every instance of that component rendering, just for the whole instance of the request. So we can change this to memo to do AVC, and now refresh the page.
So we can change this to memo to do AVC, and now refresh the page. And we should get pretty much the same performance benefit we do, except it says zero users online now, which is great. And I can see the database. So I didn't wipe the view cache. I just reseeded the database. And you can see that this value changed. It is live, and we got all of that performance gain, which I think is so fun.
Memoization Limitations3:49
It is live, and we got all of that performance gain, which I think is so fun. But let's talk about when you can't use memo. So memo is really good for instances where A, you can't fold, then you should try to use memo. But there's certain things that you shouldn't use it with. Let me open up where it's used right here. So this is the context file and we have XOnline count. The first thing is memoization does not work with slots. So if you use slots of any kind, if I save this and I refresh,
The first thing is memoization does not work with slots. So if you use slots of any kind, if I save this and I refresh, you'll see that the performance goes back down. And the reason is, is if you think about it, if we cached, we would have to somehow cache the component output, and we would have to know if you use something dynamic inside of your slot. And if you do, we would have to use string replace. I don't know, it would be complicated. In theory, we could support it,
I don't know, it would be complicated. In theory, we could support it, but it would be way too complicated. So for now, if you're using memo, we don't support slots. So that's the one big trade-off. The second one is if you're using something that changes all the time. Like if you're using props that change all the time, 'cause if you recall, when we memoize, the cache key that we use is the name of the component
'cause if you recall, when we memoize, the cache key that we use is the name of the component combined with a hash of all of the props that you pass in. So this way, if you have Fubar and Fubaz, these are gonna be two separate cache entries. And if you're not reusing the same cache entry, you're not getting the value out of it. So we're inside a loop, a for each loop of users. So let's scroll up here and just see that. For each users, okay?
So let's scroll up here and just see that. For each users, okay? So if I say that user is equal to user, like this, now I refresh the page, you're gonna see that we don't get any performance benefit. And that's because we're creating, we're actually getting worse performance. We're creating a cache entry and caching the output of this for every single iteration, right? Does that make sense?
of this for every single iteration, right? Does that make sense? Where if this is the same value, like if it's user foo, which is not even a value prop or a valid prop, if I refresh that, we do get the performance benefit because these are gonna be repeated. So use memoization as a fallback to folding. Don't use it if you're gonna need slots. Don't use it if you're going to have the, like this component be like changed all over the place.
Don't use it if you're going to have the, like this component be like changed all over the place. But if it's a repeated component, and if you're not using slots and you can't fold, we use memo, at this point you're probably like, so when is it even useful? I tell you, it is useful sometimes, but the only place we truly use it exclusively in Flux is our avatar component. It is perfect for it because avatars get repeated
is our avatar component. It is perfect for it because avatars get repeated all over the place. And because of the way we set up our avatar that does all these complicated things like dynamic colors and things, we can't codefold them. So we can memo them and we get good performance benefit because of that. So all right, that's memoization. Let's get into folding.
Transition to Folding Deep Dive6:42
So all right, that's memoization. Let's get into folding. The final frontier will really understand folding and all the ins and outs and little gotchas and ways we can work around it to make everything foldable and make your whole site lightning fast. Let's do it.
