Sessions is temporarily moving to YouTube, check out all our new videos here.

Angular2 vs React, Initial Performance Review

Aristos Markogiannakis speaking at JS Monthly London in October, 2016
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

The guys at BT have been busy playing with AngularJS2 and have are ready to share some initial performance results and show how well Angular2 compares with React.


I was thinking, "What should I do?" So I came with up with idea of doing a comparison between Angular and React in the beginning. But then I thought, like, "No, this is too boring. I have to involve everything." So involved view and we involved Angular: One and also Vanilla. They're are too many, as you saw on the previous slide, but we didn't know which one to choose. We are working with Angular and React. We are a company that we want to know what we are using and why we're using it. So part of that is very important for us that we do something based on performance, because we want to make sure that the [inaudible] are entering quite fast. And so, I starting point. We are doing the performance test on all of those frameworks that you can see on the screen, so the main question is how to do it. The simplest way, in the browser. So how can we do it in the browser? We can go and just push the button and just try to count it. It's impossible, but we can always try that. We went other, different route. So what we did is we are using a server, [inaudible] server, using the sockets. The sockets are the main thing here, so all of those clients are using the [inaudible] of the sockets, IO. They're connecting to the server, doing the handshake, saying, "Hi, I'm a client framework Angular, View or React." And whenever that is established, they are ready to go. So the solution for the clicking the button on each of those clients is instead of clicking anything on those sides, we have our main dashboard to drive it. So from the main dashboard, you have buttons. So on the buttons we can say, "I want to send more data." And whenever you hit this button, the server...the emit will go to the server and the server will emit at the same time to all of those clients the new data. Then what is happening next? Whenever all the clients have the data, it's been emitted, they have it, it's being's, first of all, it's adding it, for example, to the scope or setting to the state of React or any other way in other clients. Also, during the emits, the server is doing a timestamp, so we have to measure how long the connection took because sockets are not instant. They're very fast, but they are not instant, so we always have to measure that. Whenever data is acquired, every of those clients is doing the timestamp as well to measure, actually, the time from the data that has arrived to the render finished. Then the render process is happening when the render is done, the done emit is being sent over back to the server and the server is passing this back to the dashboard. - [David] Hi, I'm David. So as [inaudible] just talked to you about the server and the way that datas can be passed, we also decided to go for a common UI layer, so that when you view it on the screen, we'll show you the demo in a bit, you'll see that they're very similar looking, to try and remove complexities about individual frameworks. So the way we're doing it is we're going to have a flight destination, so the data we're going to use is dummy data. It's redundant, doesn't really matter what the data is. We've chosen to use flight destinations and connections, so we're going to get a stream of data or we're going to get a dump of data, like a load of data at one time. We're going to be able to add data of flight destinations and flight connecrtions. And the way we're going to process this is every single framework or Vanilla, if you want to call that a framework. I don't think it is, but it's going to have a flight destinations component, and that's going to have it's own connection to this common socket layer, so it's going to be waiting for an emit from the server saying, "Here's some data, here's some flight destinations." Then it's going to go through and it's going to loop through in its own way in different frameworks to produce on the GUI different blocks of flight destination data. So you got flight destination one, two, three, etc., etc. And within this, there's going to be another component called flight connections component, and this could be a directive or component inside React. And each one of these is also going to have its own link to the socket's common layer. So this will allow us to effectively test not just getting data and processing it, but also how exponential data happens. So if we have 10 destinations, we're going to have 10 destinations and 10 flight connection components. And then say we then stream 10 connections. That gives us 100 pieces of data, which gives us some very interesting results. And as you can see, every single one will be using a common socket layer, so we're removing the complexity of sockets out of the framework into a common layer, so we can really test how the frameworks deal and what sort of extra stuff's been adding to the frameworks. Does it slow it down? Does it speed it up? And gives us this driven idea. So I'm going to pass it over to Josh now. He's going to talk about the processes we're going to take within the data flow. - [Josh] So I've just got a screenshot here. I apologize if you can't see that at that back. But it doesn't matter too much, we'll show you in a demo. But this is a screenshot from the View app, but this is the initial...each framework has its own app class, I guess, that initializes the framework. We import our shared sockets library at the top, and all we have to do is create our new sockets instance with our framework name, in this case, view. We wait for the socket to be ready, and then we start our app. So in the View's case, you have to create a new instance of View, but in Vanilla, there's no such thing. But this is basically the basis for each framework, and it's common throughout each one. So that's how we make our handshakes. And each one is slightly different, but they all have a similar theme. They all have this sockets.get almost like a wait function. So we have a get emit, we get add emit and a stream emit. So a get is like a dump of data. It completely wipes what was ever there before. So you might have 100 flight destinations that suddenly adds to that data. So if you've already got 50 and you add another 50, you now have 100, how that renders. Then you have a stream which is exactly the same as add, but it's on a timer, so it might be every second, every two seconds. You might want to add five every two seconds. We can control that from our dashboard, and this is the rendering cycle. So kind of following on what I was just saying, so we receive data from our socket, we render it on the screen. I mean, this is easier. We'll all discuss our experiences with each framework, but this is different for each framework. We have life cycle call backs for things like React and View. We don't have things like that for Vanilla. We don't have things like that for Angular one, but we've managed a way to try and keep that consistent. And then we have former server that we've got that data and the graphs of that data, and then we can see the results. I'll go through mine first. So I was in charge of developing the Vanilla version, so this probably might be a bit interesting. You may think, "Okay, we're using components. We're using child components. This doesn't sound very Vanilla." So I decided to use Web Components, which allows you to do a similar thing to what we were trying to...what you'd expect to do in things like React. So in a web component, this is using ES6. It has a constructor. You don't really need to worry about it. It doesn't actually fire. This might have changed in the newest version of Web Components, but this one, nothing happens in that constructor. Everything happens in this attached call back. That's when our element, our flight destinations component, is added to our HTML. So I have a template file. This is just a standard piece of HTML which is using the template element. I clone it. So I make a reference to what I'm interested in. So we need to have a counter for how many destinations we've got in the View. We need to have a body. So this is just what...oh, dangerous. This is what I'm going to use for each flight destination. I have a React-like state, where I'm going to store things. You don't really have to worry about too much else, but I'll show you where I was connecting to my socket. So each component's going to have something that looks similar to this. Can everyone see this, by the way? Can I have a nod, yeah. I add some data list, and so I wait for all this destination dump. I wait for some additional data, and I wait for a stream. And then all I do... I'll go through additional stream. This is more interesting. I do a loop through the response that I get, so I do a forward fall loop, so you're may be wondering, "Okay, this is an array." I'm writing ES6. Why am I not doing a 4H? 4H was slower for me when I did this. I also did a backwards four loop, so also a little bit slower. In retrospect, I've actually found it is a quicker way. You don't actually loop through an array, you create a string, add to a string, turn that string into a HTML, put that on the screen, it's faster. And then I render it, so I go through each...if I open my render method. I clone a new template. I query the areas I'm interested in, so the from and the to date, and that's Stansted to Lisbon. Put the data in, pend it to a fragment. A fragment is just like a piece of DOM that's not actually attached to the View. And once all that data's been added is that fragment, just that one fragment to the DOM. And then once that's done, I run update it. That let's this know when I'm done. And I scroll to the bottom. That's my very quick overview of Web Component. - And Vanilla. - And Vanilla. - Now View. - Now View. Just to make sure, we're not going to go through each framework because you'll be here all night. - You can come talk to us afterwards if you want to... - Yeah. - All right, so you can be actually quite surprised, but there is nothing actually to talk about on View. It's very simple. On View, you have a hook which is created. On the created hook, I'm hooking... I'm binding all sockets here, so you have get all data on destinations, add destinations and stream destinations. So as I was saying before that...where is that? Timestamp, so we are doing the timestamp to measure the time for the render, just the render without the sockets. Now the other timestamp is actually inside the rest, which is coming from the server. The same thing is for destinations. Add, stream destinations, and that was never finished, so we don't need that. And then another hook. When the DOM has changed, so when everything is updated, so at that point, what we are doing is we're sending the done emit back to the server and inside we have, first of all, client ID, so who you are. The next one is the type, so we keeping this to make graph a bit more nice. So that is actually what type if was, so it was set, add or stream. Next is the count, so we like to know what is actually happening, just to make sure that everything works fine. So how many destinations we have in total, and how many destinations has been send over in the current emit. And then the timestamps. So that is the heart of the application, and the first is emitted so that is [inaudible] from the server, before render that we took on the time when we get new data, and after render, which we're doing right now, and actually that's all...something. Okay, so here you can see our dashboard, and first thing is active connection. So all of those are green because all of those are just connected right now. It's something will disconnect, they will be shown as a gray. There is a button to open, but we already have it prepared, because there's quite interesting thing, actually, of those test needs to be on the View. If something is on the background, performance is dropping a lot because browser's not giving the full processor speed to that page, so the results are actually fake. David, can we make it half? All right. Can you hit the View button to refresh it? We have the View there, so you can see that that actually works. The socket is something that refresh, request, and the view's refreshing. Can you refresh all of those? Something small to just speed up the work on it and showcase. All right, next one is step one, destinations. So this is how we can actually set something. So set destination means it will override the whole data we have, if we have 500 destination already and we send over...if you do set for 10, it will override everything, and you're going to have 10 only. Then we have add destination. You can see how it works. So first of all, quickly, there is a count to make sure everything works correctly. There is 10 as well, but that's overlay extra. Can you move it to the...that, yeah. So everything is on 10 right now. Can you add 10 more extra destinations? All right. Can you scroll down now? Can you show us the graph? So that is our graph. Few things to mention here. We're going to cue Angular soon enough because it's very hard to see other things. Milliseconds and here. What that is is actually how many times we actually send the data. So that is like a package bundle account. We just hit the update three times, so we have things up to that point. Can you mouse over the points here? You can see some more specific data when you mouse over. Okay. Ah, that is also good point, actually. So we have render and render sockets graphs. So those are the differences between the latency. So sockets take some time, not much, but still, they do, so to prevent that, we have two graphs. So they're on render and the socket is the time to connect and the render time, and that is just the render time. Okay can we cue Angular: One? Actually, wait, wait. Sorry. Can you go here to this one? Let's try to stream something first. So can you put one through five here? And stream progressive. - [Male] [inaudible] so it's... - We want to see that, at least for now, for the first try. Can you click? And scroll down. So this is how it works. So just quickly, what is a stream and stream progressive stream, is we trying to stream everything at the same time. How many the clients can get...they will progress is a little different, so it will send a new data request to the client, then it waits for the client to actually render this data, and when that is done, it's sending the done response back to the server and at that point, the server is giving new data, not before. So those are two differences between stream and stream progressive. My PC is probably dying on it, so can we kill some of those? So if you can kill Angular: One. Something out...what do you want to kill? One extra thing. Vanilla is actually quite interesting, so...okay, let's keep that...can we kill View and Angular. too, for now. Can you refresh the dashboard because it just...can you refresh the dashboard? Can you refresh them as well? Yep, great. All right. Can you scroll to the top quickly? Can you open the View quickly? All right, go back to the...don't move it. Can you send over the stream for 20? And stream...just stream, yeah. That is odd. Can you stream a bit more? Give it to 100 and stream progressive. We going to have to refresh the server, the View is quite slow, right? Can you make a focus on the top for the View? The View top. Can you go back to the dashboard? If something is on the top that is not being focused, it's really slow. So that is actually a fake result that we discovered. That's why we're writing those on the separate tabs, to make it fairly correct. - [Male] Obviously, if you're on a Mac, even if you have a tablet from here, it's the last window, if it's being covered by three other windows, [inaudible] less memory, starts screening. - This is only in Chrome. - We haven't really tested it in Firefox or Safari. - That's right. - [inaudible]. - That is another point, you can easily run it on any browser, actually. - Do you have it finished yet? - Yeah, it's still doing...can you pull it to the focus or we will never finish it. - There you go, you see how it suddenly speeds up. - Yeah. Okay, let's close this down. Refresh the dashboard, just to save some clear data. Refresh those too, quickly. All right. Can you set the count for 100? Set destinations. Set, set, set, set. Scroll down. All right. That doesn't look too good, so it seems like Vanilla is really fast. Unfortunately, it is. But if you can add more...can you add another... no, set destination one again, 100. Another. One more time. Set. Yep. Can you scroll down? That is something quite interesting. So you can see how much React is actually improving. So whenever the DOM elements already exist, you can see a big improvement. That is happening for React, View, and I think Angular, too, as well, when in Vanilla you actually don't see too much improvements at all. And if we going to set... can you do in 600? Set, five times. Five times. At this one. Remember that at that point, we don't have nested components. So for Vanilla, that is very easy thing to do. Whenever we [inaudible] with nested components, that will be different. Can you... let's try it. Can you set this connections counts to 10? So now we won't have only 10 connections. We going to have 10 connections times 600. Can you set that? - You got a cup of tea ready? - Can you scroll down? There is a chance that it will kill both, but... - You were quite optimistic, though, with 600. - I've tried it before. - [inaudible] Vanilla. - May not [inaudible]. - Yeah, React. [inaudible]. We've had crushes on them. You may have to wait, but it will finish. Vanilla will just [inaudible]. - So without waiting, can you restart the... yeah, just kill. Just kill. Can you restart the sockets up? Yeah, refresh it. Refresh. Refresh. Yeah, anyway. Can you set it to 50? - You want destination set? - Yeah. Set destinations. Wait for it, and 10. Can you scroll down? So this is how it looks. So... yeah, it's still not big difference. The best thing is to try to play on your own with it. We have different results any time we want to run it. It's not always the simple answer. All right, can we change to Angular and React then? That was quite surprising for me, so actually View seems to be one of the fastest things here. Can you put 100? Three hundred. That should be still fine for those. Don't stream. - Set? - Yeah. Don't show that because that is latency, so it's [inaudible] it could be a fake. All right, scroll to the top. Can we add 50 more? So 50, add. So you can see how React, View and Angular are improving. They are not running everything from the beginning, they are just adding a few thing to whatever they already have. All right, let's try with the stream, so 50 is fine. Let's change that to five per emit, and stream progress if... Now if you can add two connections. So that is the step where we are actually going for next step components. Set. - On 400. - Let's try. I have really big faith in it. Can you add more? - You're killing me. - Can you just hit add? Add connections. - Hang on. React is not going. - It has some problems. But actually, that could not be the fault of React on it's own. - That was asking a lot, to be fair. - Yeah, that was asking a lot. - You can restart the server. - To the refresh. - Restarting the server will be enough. David, can you refresh the server? You have a call online. Okay, that's fine. Refresh. Let's work on some lower data, then. Set 10. And add 10 connections. So those results are really surprising in most cases. The thing that you have to remember is that it's rare that we going over 50 milliseconds. So in normal life, you will never split the difference. So that's why it could vary. Whenever we going to add too much, then probably the sockets are just [inaudible] and they just crash. That could be one of the reason why we cannot work on more data. Let's make a... probably last thing, which is a stream. One hundred for stream progress if... it will take a while. Scroll down. - Okay, so there was some findings, but as has already been mentioned, these are very variable results. You'd have to do this about 1000 times and try and do an average, I think. But there were some consistencies. Vanilla was unsurprising as always. But when streaming, because it's just adding one on a time out. There's no complexity there. It's what it's good at. It's what it's designed to do. Vanilla does not perform well if you drop 5,000 or even 500 DOM elements to the View, whereas React and others always consistently perform better. View was probably the most surprising. It's the most minuscule, minified output compared to the other frameworks. Compared to Vanilla, that's quite shocking. To me, I think that's quite impressive. I know it's consistently fastest. It was always... yeah, the closest to Vanilla, I think. We should probably explain why we excluded Angular: One. Angular: One... I mean, I don't trust our results. I mean, it's very, very hard to test Angular: One because there was no life cycle to it. You have to kind of fudge it, for want of a better term, because there's so many digest loops. You have time outs. You have to rely on all kinds of fun things to get Angular just to emit back when it's finished rendering. So this is the best we could get it, but we excluded it, purely because you can't see the results the other, otherwise. But that was our findings. So in the future, we're not scientists. Don't use this. Take this with a pinch of salt. Don't make it determine what you're going to use next at your work. Our bias is we use React, we use Vanilla, obviously, because it's JavaScript, and we also use Angular: One. So View and Angular: Two we don't use, so naturally, there's probably going to be improvements that could be made to those two. But more testing, and I know there's been varying results from other testers that have done the same thing. As I say, take this with a pinch of salt, but we'll open up the repo soon. You can add your own framework, another one comes out using the same tool, and see how it builds it. And there's at least four, I know it was probably mentioned, but at least four [inaudible] developer positions at [inaudible] currently. ♪ [music] ♪