Video details

Michael Hladky - Concurrent Mode in Angular - Non-blocking UIs at scale | AngularUP 2021

Angular
03.21.2022
English

Concurrent Mode in Angular - Non-blocking UIs at scale "Runtime rendering performance and UI responsiveness of web applications are more important than ever – and the industry is well aware of it. Frameworks like React introduced new ways of addressing performance issues, allowing for faster UI updates, and with tools like Chrome's postTask() scheduling, you now have the low-level functionality to directly influence rendering performance.
Angular also has quite a few improvements to offer in this regard. To a great extent, those are made possible thanks to Angular Ivy. Indeed, with Ivy, we have new opportunities to influence rendering performance in Angular applications. Through those new APIs it was possible to introduce a completely new and super efficient Change detection mechanism.
In this talk, I will introduce you to the outcome of multiple years of research – Concurrent Mode in Angular.
Concurrent Mode gives us full, prioritized control of work on the main thread.
In the course of this event, we will: discuss use cases and measure performance impact see the possibilities of Concurrent Mode in Angular with real-world demos showcase a nice API to schedule tasks with explicit priorities Live in front of the whole audience, I will dig through the browser Flame Charts and explain the underlying principles in detail. Get a first glimpse of a completely new, future-proven, and innovative Angular." Michael Hladky-
Trainer and Consultant Michael Hladky is a Google Developer Expert (GDE), trainer, and consultant with a focus on Angular and RxJS. For years he has helped companies and developers to setup scalable architectures and performant processes enabling teams to keep up with state of the art development. A vibrant member of the tech community, he organizes multiple community events and workshops each year to give back.

Transcript

Okay. So welcome to my talk, Angular Concurrent most highly performance and non blocking UIs. Today I present from Tahiti, which is like 12 hours in the past from inside rendering in comparison to server side rendering. And if you really want to know which server side rendering, I mean, yes, I mean the really good old server side rendering with PHP and my Income character. Today I will talk about the client side and I will not talk about the stack or the framework. I will really talk about the rendering process itself. To give you a first sneak peek how rendering in the browser works and how I try to fix that, let me show you a quick demo. So I have two applications here. One of them is a real world application with movies and another one is a demo application where I can really stress out the problem. Let me go to the first one. Let me open up the performance panel here on the left. A little bit bigger. Yes. And let me hit the record button and then we'll stop this recording. The recording takes a little bit of time, but when you stumble, we can see a very specific problem. If you don't understand fling charts, don't worry too much. You will go into detail with all of the stuff that you see here. But for now, please watch out this red bar here that you can see at the top whenever I navigate to a new page. And you can also if I Zoom in, recognize this red bar over here. There is a task and this task is marked with a big red bar at the end and a small triangle. This is called a long task. This task here took nearly 300 milliseconds and in those 300 milliseconds our screen was frozen. I can place it on application here and I can do that again. I hit the record button here and then I hit on the native element and then it really freezes. Totally. This is a little bit more stressed example of a lot of elements and a big list and this is even more blocking. I guess this block over this problem that I want to fix for you and I want to present a solution. Let me first introduce myself. My name is Michael Martin. I'm a trainer in consultant with the focus on Angela and especially on performance. And now back to the topic. Let's talk about looking at the browser in responsiveness. And first let's go to our good old server side rendering. I called this respond on the request and I will tell you a rendered to the client. So if you remember, in the good old days you have small buttons next to the list. So when you want to search a list, you would have to click the button, send the request to the server, get the newly rendered list back, and then you could click the button again, send it to the server render on the server and you get that newly rendered list from the server page. This is quite annoying, but where we are coming from, if you look at this graphic on the left side, you have the event and if you click a button, you could work. In this case, we don't execute the work right away. We just put the work into the future. So this is our package of work that gets shifted in our case here in the next element frame. And later on we perform our tasks in the browser and compared to our calendar, the Gray boxes are the days and the browser. We have set time off, micro tasks, post message request animation, frame request idle, callback and post. A lot of different methods that you can use to schedule work, show you where they would end and you can see depending on the different method after the claimed event that you can see here in the middle. This is one fundamental piece that we need to understand when thinking about Mount blocking UIs. The manager and its frames is the next chapter. And here we basically go through in a little bit more detail on what the main thread is and what a blocking is. First of all, let's talk about tasks in the mainstream. If you remember the calendar and the calendar unit, we could look at this unit here is of course we could also go even more detailed. We can have units out of ten minutes. I guess most probably the manage and the smallest units of times are tasks. And I cannot really do anything else by sitting in one of those tasks. I really have finished those tasks until I go to that next task. Those smallest pieces of tank look in the problem. You saw it maybe before. These are those. And every single grade lock is one piece, one unit of work that the browser has to process. And then next thing, for example, use the interaction or more work. Those are the smallest pieces of work in a browser that you cannot really keep. You have to perform them after to understand some examples of my own life frame drops for humans vulnerable. So what could I do to produce a frame problem in my life? Well, the first thing is I have work to do that takes longer. The talk takes a little bit longer than I expected and then the next talk that would be after me in the future. So the other person, the next talk can start. And this is not really good because we have an overlap. Here another thing, schedule work in the future and then I could schedule this work at the same time, let's say a meeting at the same time where another meeting was scheduled and then it collapses and I again produced a frame drop. One of my most favorite things, how I can produce a frame drop in my life is when I estimate properly for small cost, right? So what I normally do is I look at the task, calculate how long it takes, and for me when I start the task and I process, it takes so long that I see the end of this blue box here. So this is a frame drop in real life, let me show you how a frame drop looks like in the browser. So you remember that green boxes in one of those Gray boxes is called a task, a unit of work that you cannot really split into two. And while this work is ongoing, you cannot do anything else. And a frame drop means a task that took longer than 50 seconds. I don't want to go production detail on the 15 milliseconds. I have a different talk that is focusing more on the performance and also APIs, but just that, you know, this is the time that Chrome and also the long task API determines as too long and within that time you cannot really interact. So 50 milliseconds are good and everything else is in addition to the 50 milliseconds, which is very bad, which is a long task. The work present in this task are two different things. On the left side we have scripting work and on the right side we have recalculates. In this today's talk, I will focus only on scripting work because I have different talks that really focus on recalculations and other layout metrics. We will just learn how to tag our eyes in with scripting work, how to deal with scripting work, with your learning. And as you can see in this more graphic already we have a small queue, a small queue of pieces of work, and this work gets processed one piece after another. I can cancel work and I can prioritize work. Through our research of the RX Angular team, we did a lot of different things in the past, one and a half to two years and one of those really good outcomes was the RX form, a structured directive that was basically born as we analyzed the performance bottlenecks of list in Indula normally is an injury or a structure. Resurrective, especially leg statistics are one of the least performance things that you can use in Angular in general in any framework. And if you look at the native implementation, we see that every single list item in this list has to get processed in the past, which means there is no way to stop rendering and do anything else. In the small frame chart here on the right, you see that at least with a lot of extensive list items will block the screen for a long time. And this leads to very, very bad user intact, especially on navigation. This is the stuff we saw before. Another real life example on what could a really long list cost is this picture here. As you can see, this is a tremendous huge locking path, but the stream is frozen for multiple seconds. Really, really bad experience and this is quite common in bigger application, especially if you don't really care about performance. You will get those bottlenecks very soon. What we did is we made a case study out of it. We said let's create a list. Let's create a small table. The table has five sales and ten rows and then we initialize this webpage. We click to update everything in table cells four times in a row. And then we start and improvise to update these table cells as fast as possible. Here at the top we have the flame chart overview and we see that initialization is fully blocking. Every click for an update is fully blocking and especially when we really demand the browser and we run this interval as fast as we can to update. You also see every single update blocks. Here another closeup on our blocking tasks, and this is of course very best. What we did is we came up with strategies where we could say okay, let's render the list items, but only as many items as they would fit in a part that is less than 50 milliseconds. And if the next item would take more time, we stopped work. We schedule the rest of the render into the future and then we go on with this rendering stuff. In the next task in between, the user always can click, drag, tag and interact with our page. This means it is really annoying blocking UI in our case study here disabled with the list, we replaced the Ng four with our structural interactive that implements Concurrent mode for Angular. It is called RX Four. It's present in the RX Angular library that you can download on NPM. And on the left side you have a small tiny blame chart that already pieces what we did. And here you can see no matter how big the list would be, we only render as many items as they would fit into a single list. But we have a close look on the case study for this demo table. Here we see that with this technique and only two characters of code change, the location is fully non blocking. Every single click in our UI is fully known Brocking and with the integral where we have like the highest stress momentum for the browser, in this case study we see that even those updates, the browser has pretty much no brain drop at all and we have really smooth interactions and updates. This is incredible cooling and we basically wrote down everything needed for this in our GitHub issue. So if I open up the GitHub issue and quickly show you our research paper, you can see that we really wrote down anything you bought. I make it quicker now because it's a long document, but here we discuss all the bottlenecks in the RX four, what features we have to implement, what we already did, what challenges we had to solve error handling and then of course the comparison of all those scheduling. This is only one example that you can use into a concurrent mode. Let me give you some more examples before we go on. We basically this is basically the comparison again because it is so beautiful. The difference that I cannot stress is enough. If I click on the next page, I will elaborate how we did that. So at the top you see this native Angular implementation and that blue boxes is considered a blue box is only in the list or as one component in a page component. The Gray box, same as in the flame charts of the browser performance tab is a task means a pen where the browser cannot do anything else but processing the work that is present in this specific task. And at the very top you already know from the frame chart is a frame drop. At the very bottom we see the implementation of RX Angular. Rx Angular implemented something that's called concurrent mode and this is a technique that you basically can tell English, but not only English. Also pretty much any work that you want to perform, but it could perform in pieces that are smaller than 15 milliseconds that will not produce a fringe load. And with this technique, if you look here, we basically take a little bit longer before packages, but in between our user is always able to interact with our website. Our user can always click drag, tag or scroll. This is what we need, especially on mobile phones where the performance is really bad by default. I would say those techniques will really help us to get a better vital score, a better ranking and also a better user experience. Let me show you some demos before we go on. I have this app. This movie's app also exists in react by the way. Identical layout, identical content, identical Http request. It was a small performance specialist. We will publish our work on this in the future, but for now I will show you only piece. The piece will be applied concurrent rendering to this app as I already showed in the flame charts. When we look here and I will try to Hover so that we can see when I click the mouse and the content switches those red bars appear and then the image is render and if I click them out again the other menu edit them, another appears and then after the rendering is done the page shows the update and I can again interact with my website. Let's Zoom in a little bit and take a closer look. Here we have a 300 millisecond task and if I try to analyze it so 150 more than half of this is caused by scripting work. The other half and this is a trick that I looked for but in another one is caused by recalculating styles and layout which will not get sourced by today's implementation. But only the next part. And if you can look at this pattern, it's a very significant piece here. In this task, we already see that there are a lot of different things performed in a row. I can try to go down. And maybe I can also see that we have here some components that gets rendered at the very bottom here. Those purple boxes are components that get rendered. So we see that this work gets executed over and over again. We have a tick and we have a tick changes that in this place that the browser performs. Change the text. Let's jump into our website, into our source code. Let me try to Zoom in so that you can properly see everything. And I will do two things. First, I will go to the movie list and I will Zoom in. And in our movie list, we see this Mg four here. This Mg four takes an observable, in this case tracked by just a little bit better performance. But as you saw, it's not enough. We still have these blocking frame drops. And what I will do is I will refactor this list to get more blocking. I will do that with a library that's called RX Angular. Rx Angular templates, to be more specific. And this library provides us a structural directive that is called RX four. And the RX four directive enables us basically servers really intelligent way of rendering. So with this list here and with another list in my app shell, which is present a little bit more down, let me search for ng four. Here we go. I can also RX forward it and I can remove the asing pad. If those two tiny changes really characters, I will do the measurement again. Let me make it a little bit smaller. Let's see if it works. Okay. And if I now look at those navigations here, we see that when I click in here, the new items directly pop in. One after another, the images load and the items appearing task. So I can really Zoom in into this piece here. And as you can see, the click here took 35 milliseconds, which is really amazing. It could be a little bit better. Of course, like something under ten milliseconds would be optimum, but 35 is still really good. And then the whole list gets initialized. But rendering list items here, again, we see the changes one, two times. And then before the task gets blocked in, we schedule the rest of the work into the next task. And here we see the next task. In this case, we don't render two, but three items on to three, as you can see here. And then the rest of the stuff is scheduled in the next task. And if I Hover over that, you see that every task here is less than even 30 milliseconds. So average sales of the tasks here are between 18 and 20 milliseconds, which is as male Finn. This is one way how you can use Angular current mode and another way is a little bit cooler. Not cooler, but more interesting. Our Explorer directly renders au right? So we could also refactor the whole thing and we could use another directive. The RX less directive is directive I introduced last year, or one and a half years. And this also basically helps us to pass an observable directly to back. Pretty good. So this could also be one way of basically this value to the page and then everything that is in this container and in our case it is the full Excel would get rendered in a special technique in one chunk. And if there is too much we would move the rest into the next chunk. And this is done with the value which is called here fuel state. But let me give you another really cool link if you don't want to render a value but just chunk up the work. And here in this case I have a navigation. And in this navigation part I have another big list and I have a lot of items. And let's say I don't want to apply any data here. I just want to chunk up this piece of logic, this piece of components. I could also use the RX length directive here. And instead of testing a real value which would look like this, I could also pass an empty array, basically an Iterable piece that has no venue. This is a small trick or hack. And with this word trick and hack, I can chunk the whole navigation, this piece of Dome here into a separate task. And that could appear on multiple places. As you say, chunk up my component shell. For example, I could chunk up the header, chunk up the size menu, and chunk up the main content in different steps. And then I would end up in a way better performance. I could wait until the page loads and then I could again navigate back and forth. As you can see, there is no difference, no visual difference. But if we take a look at our measurements and maybe I can show you previous measurements, you see that there is really heavy impact. This small drop down at the top shows old and new measurements. And as you can see on my old measurement has a lot of blocking frames and my new one has only little ones. And those little ones were the ones that are less that I fixed now with the RX left one last demo before I hand over to the next speaker here. You don't have to wait forever. So I navigate away. Now I click frozen, click frozen. So this is the normal behavior. Now let me do the exact same thing with Angular Cocurrent mode, which is this item here. So I go to the empty page and then I click back, click back. So there is instant response. You don't even really feel any different and this is just because we really type up the work and the browser has time to breathe and the user has time to interact and scroll with our website. Again, this is really an amazing feature that you can directly use in your applications. You can use it in lists, you can use it for static single values with the RX leg and you can also use the RX leg to chunk up basically any piece of bone or component structure you like. Enough with the demos. Let me come to an end and you would want to check out is called RX Angela and we have three packages, RX. Angela CDK which is our component development kit. In this case we include all the strategies for concurrent rendering, all template management one and a half years ago and then we also ship Rick angular the first local state management was present in angular that was delivered I guess two and a half years ago. So as you can see the soldiers and performance train is a train that I'm on for quite some time now. This is only the tip of the ISB already and I will shoot new features in the coverage of upcoming months. That's it so far. If you want to say especially to our consumers, that is also a very, very good job please go to our GitHub Rick angular and give us a start. We really appreciate it again here. Rx angular templates the package that includes all the structural directives. Take a look, check it out. It's a really cool thing next to the state management that also basically helps you a lot and that's it from my end I want to say thanks for your time saying that you have interest on performance. Here is a link to the repository as I said make us happy. Every step star makes us more happy. If you want to contact me for performance audit, contracting make your product faster, more impact. Effective to say better shoot me email or pin me directly on Twitter I hope you liked it and that's.