JavaScript Performance

Deoptimization, Deleting Properties

Steve Kinney

Steve Kinney

JavaScript Performance

Check out a free preview of the full JavaScript Performance course

The "Deoptimization, Deleting Properties" Lesson is part of the full, JavaScript Performance course featured in this preview video. Here's what you'd learn in this lesson:

The optimizing compiler optimizes for what it’s seen. If it sees something new, that’s problematic. Steve traces deoptimization in the example from earlier. Deleting properties has some strange implications on performance. Steve takes questions from students.


Transcript from the "Deoptimization, Deleting Properties" Lesson

>> Steve: Let's play with some other stuff.
>> Steve: I'm gonna do all those, and I'm gonna call one more time.
>> Steve: Because like this thing can do all sorts of things, right? The plus sign is versatile. I can add numbers and plant it in strings. This is the best function in JavaScript.

We'll go ahead and we'll do that.
>> Steve: All right, it was optimized, but I feel like that wasn't the full story. Right, what would happen, all right, let me do another flag and this is where we can all play together. Anyone wanna guess what trace deopt does?
>> Speaker 2: No.

>> [LAUGH].
>> Steve: At one point you are all like, this is how we all pay attention. At one point I am going to type in like trace deopt, or depot. Because I have done it 1,000 times, there is no reason I wouldn't do it in front of a lot of people.

Someone has to call me on that one when I look confused as to why things didn't work, okay. Cool, let's run that.
>> Steve: There's a bunch of stuff here. Deoptimizing the function, interesting. So it optimized and then it deoptimized. What if I take out this line? It only optimized.

I think we are ready to make a hypothesis. We're doing science by the way. Cool, so we added two numbers a bunch of times. And then we added two strings and that got us deoptimized. Anyone want a venture hypothesis? If not I have slides don't worry, no pressure.

I'm just gonna open the floor for hypothesis. Anyone got one? All right, mentally, like we have suspicions at least. May not be ready. I see people they've got their hands up the mouth up but they're not fully ready. There's no wrong answers. I mean, there are wrong answers cuz this is an algorithm, there's science here.

But we're amongst friends, right? Both chat room and here. Cool, so we have some hypotheses, very nice. Yeah, for those you're in the chat, I see the question. I got a slide, it's going to be good. All right, so we see that the two different things we're getting out of de-optimization unclear what's happening here.

All right, so that's a problem, so what happens, let's try something else up. I'm gonna do it twice.
>> Steve: We don't need this line right now, we know that that line is problematic. And we'll go ahead, and no benchmark. Let's not do anything with the trace ops right now.

>> Steve: It will take a little longer cuz it's, we're doing it twice. It's taking suspiciously longer.
>> Steve: I'm gonna go back over and see what's going on here.
>> Steve: We have to set.
>> Steve: We'll set the iterations back up.
>> Steve: Cool, took 47, just, mental note. 47 milliseconds.

Let's put that problematic line back in. Okay, almost, not double, almost double the amount of time, right? So even somewhere in the middle there we can see that like having different types of arguments past that function definitely, there's definitely a problem there. It definitely caused some kind of slow down, right?

Talk more about this later. We're just taking mental notes right now. We're doing science. We're filling up our lab notebooks underneath the golden rules and we'll make some test later, cool. All right, that was definitely, definitely a problem. Let's also run the code one more time. We're gonna do another little node trick is, we'll go ahead and we're gonna use some syntax you might not seen before, maybe have.

It's let's say NeverOptimizeFunction(add). Your like, why would I ever use this? Good news is that you can't, it's It's not real, it's kind of real, but it's not really real. So we'll say node and we'll say this allow natives syntax, which is basically this is for debugging. This lets you parse certain flags to V8 that will go ahead and get you further like debugging information.

So here what we wanna do is, we effectively, we're gonna use this, you saw it was prefixed with a percent sign, right? This is cuz that's not valid JavaScript, that will work with this flag on, the code will not run without the flag on, it's basically a way to trigger stuff so you can kind of see the effects.

So we'll go ahead, say that, I'll call benchmark 235 milliseconds. We ran it twice before at 41, right? Clearly, that optimization is useful and we should totally keep it. Yeah, if we never optimize the function, it is definitely way slower. So we know that there are some things happening here even when I got deoptimized once.

It seems like got reheated back up. We can see that non optimizing it ever is not a great thing. And like that is also like a sales pitch. Like this is a simple add function. You can imagine what a much more complicated function. If we can optimize those.

You can see up to 100 X more performance. Cool. Let's look a little bit deeper. We're actually going to go to a different file now, this one that's called add. And you see here we have a function. We're going to use another special native syntax here called optimize function on next call.

Anyone want to take a wild guess what this function does? For the freebie. [LAUGH] Someone [LAUGH].
>> Speaker 2: It doesn't optimise the next fuinciton?
>> Steve: Well the next function on the next function?
>> Speaker 2: Yeah.
>> Steve: Yeah.
>> Speaker 2: The second call.
>> Steve: Well on the next call.
>> Speaker 2: Okay.
>> Steve: Right.

It will be optimize at that point. Now we need that allow At one point I'll forget to pluralize natives as well, so somebody who's in charge of that one. Had and will also,let's throw in the trace opt. Cool, we can see that it was optimized. Which makes sense even though we only ran it once.

Like a function usually is not optimized the first time it is run, because going to the optimizing parlor isn't free. Right? There's work that happens there. And what happens when we do work? It takes some time. Right? So we hope that if we're going to do work by sending it to the optimizing parlor, it goes faster.

And then what happens if we turn this into a string per se.
>> Steve: We'll also trace deopt.
>> Steve: I guess i've ruined it by telling you. We'll also trace the deoptimizaion this time. You can see that we deoptimize that function just after one time calling it with some different arguments.

Right. We don't know what's happening again. But I think we are getting to the point where we are ready to, like, think a little bit about this. Cool. Let's go back and talk about what we just saw. So this function, we've seen it before. Except this one has a syntax error and won't run.

So don't look at that side. We still have it went to the optimizing compiler. We got this faster version. A version that was you know the difference between 47 milliseconds and 235. But like that's the stuff that is happening is going to we saw that. This is using the thing that we said before, and there's bullet points called speculative optimization.

We use the interpreter cuz the interpreter is ready to go. But it doesn't know anything about our code, so it's not as fast as Turbofan is. The optimizing compiler It needs to know. JavaScript is not a typed language. It doesn't know that it's gonna get two numbers every time, right.

So what happens is the interpreter is like I would handle this. I would do a bunch of hard work. I will look everything up It's all gonna be fine. It goes and it gets ahead and it's doing it the slow way. Eventually it's like hey it's generating these feedback objects that are going to turbofans like, I think I know enough about how people are calling this add function that I think that I'm ready to make the decision.

It always gets two numbers, right? And once we know enough about it we can assume that even this untyped wild west of a programming language That yeah there's not type, no guarantees, but we're pretty certain that numbers are going to get passed in every time and that's when it becomes a candidate for being optimized.

And if a string slips in there? All right what happens? As I [LAUGH] everything I thought happens isn't true. Right? So, at that point, we get the red arrow. Right? And at that point it's like, listen, I made all these assumptions, I thought it was going to be numbers.

I don't know what's happening any more. Ignition you take this back. I clearly can't handle this. Which when we go back to the byte code, right? The optimizing compiler optimizes for what it's seen but if it sees something new That's problematic right it turns out that like a few times it will alright I'm ready to re-optimize if that happens enough times cuz like that cost is expensive the de-optimizing compiler which is like I don't touch this function anymore right you get it?

Then that number I'm not gonna say the number right now because it changes but like after a certain number of times of getting like Strings when you were expecting numbers like you would end up in a basically a loop of like okay optimize the function cool it optimizes it alright it's getting hot again like optimize the function know another string slipped in it's only gonna play that game so many times right?

And then eventually it's like I don't optimize this function I've been down this road I'm not interested anymore it's not the life I live anymore. Right. So, like if our code has a wild number of different variables then it is totally possible that it just gives up. Cool.

So we now know, we know a little about strings and numbers, right? But clearly there's more to JavaScript than strings and numbers so we're going to jump in and play around with a little more code. All right. I'll answer one question and then we'll get back to it.

Cool. So there was a question of like how many times a function has to get called. That's not necessarily at all. It depends on how many times, like, it's not, that changes. But of the, like, we don't personally call a function a lot of times. Right? But we don't always, like just cuz we don't write the function doesn't mean, like we don't know what it was called, right?

So for instance, we know in React that render method is called "Anytime State Changes" in our application, right? So that render method could get called "anytime", especially if it's stated in the application component that's getting passed down. Right, render's getting called, even if we never write render more than once.

So there are parts of our code that end up getting called a lot, right? If you think about that flame graph that I showed earlier of my own application, that flame got down and deep and there were a lot of little pieces. The top pieces were pretty big, but there were a lot of little pieces that were getting called repeatedly That I was actually surprised by when I went to do that investigating [INAUDIBLE] so sometimes like code that we don't think is getting called a lot versus state changes in our application do.

All right, cool. So let's take a look at some more code redo,
>> Steve: Cool
>> Steve: Yeah.
>> Speaker 2: If you're using something like flow where you're defining the types. Is that's something they optimize or can like handle and like be aware of or?
>> Steve: Yes.

That was also a question like recent. Like anything where you can enforce. That you're always trying to hand the same types in will effectively speed up It is less likely that you'll end up with code that is not of that type, right? Yeah, like we write in TypeScript, it get's compiled.

It is JavaScript. Could something happen where it gets down twice? Totally. Yeah, using TypeScript, Flow, ReasonML will all definitely like You are helping turbo fan help you at those points, right? So there are potential performance gains in those cases. All right, so let's actually go ahead and jump back in a little bit, we're gonna change this a little, so we're gonna lose our good old fashion add function.

We could always write it again. I feel confident that I know this code like the back of my hand.
>> Steve: All right, cool. So you could say
>> Steve: Let's make a JavaScript class.
>> Steve: They'll take x and y
>> Steve: This.y = y. All right cool and we're just gonna go ahead and we're gonna JSON a string of [INAUDIBLE] a bunch of times.

So while there are iterations we'll say
>> Steve: Equals the new point. 2 and 4. We could use the iteration number. We could do whatever we want. It's code.
>> Steve: All right let's go ahead and let's run that.
>> Steve: That's taking a really long time. You can see it took about 5 seconds.

In that case I think we've made our point. Let's go ahead with like slightly less. So, it's a million. Cool. So here we can see about half a second to class. And is not easy. There's a lot of rules there. It's not the simplest thing in the world.

>> Steve: But let's say that we set. It, as our exercise, and we'll make a new point, and we'll set point y to be undefined. Right, mm-hm, okay. We'll try it again. About the same. Right, there's a like, it's a computer. There are things doing, things happening on the computer.

Your computer might be faster than mine, see slightly different numbers. But generally speaking, we're in the same ballpark, right. Okay, that's cool, what happens when we delete that? Instead of setting it to undefined, we'll go ahead and delete it. About the same, okay. So why we can delete it we can set it to undefined.

Seems pretty interesting. What about x?
>> Steve: So that's undefined. Okay you're like great I'm watching the same numbers over and over again. Let's go ahead and delete x.
>> Steve: Wow,
>> Steve: That shot up. That's interesting right? Okay. We've measured something. We've noticed that thing has happened. Now we have to try to deal with it.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now