But it is a very low-level, internal thing. It was discovered when we started looking at async local storage, like, hey, we could use this to implement this model. but the performance of it is actually rather poor.
Promise hooks is an API built into v8, really intended to help with this type of use case. What it does is it sets up a series of callbacks that can be fired when a promise is created, when it's resolved, when it's just all the different lifecycle events of that promise. But that gets incredibly expensive when you're invoking that code every single time you create a promise, every single time you resolve the promise. And like I said, applications can create tens of thousands, even hundreds of thousands of promises in just, you know, a few moments of time. So that code ends up being extremely expensive to run every single time.
A key problem here is that we are propagating that context. We are copying those key values from one execution resource to the next. Every time the resource is, every time one of those continuations is created, not when the context actually changes, right? And that's the key thing because the actual contextual information that you're dealing with only changes very, very rarely, right? You're only dealing with a few, a few instances of these things. The values are typically set once during the, during this application. You know, right now, every time we create those promises, we're copying that data every single time and it gets very, very expensive very quickly.
So we recently implemented async local storage in cloud floor workers. This is a fun thing. We're actually getting, it's not going to be full node compatibility in workers, but we do have things like, we will have things like node dot or node colon F or not FS, but node colon net and node colon crypto, and a lot of these things, we are using the node specifier there. It is required just like in Dino. It is there. And async local storage is one of the first ones that we added. It just got enabled, I think like last month where it's available for everyone to use. But we did this without using async hooks or promise hooks. But at the API level what code uses, it is very compatible with what node has, but we've implemented it in a completely different way.
So how do we do it? We introduced this thing called an async context frame. Rather than storing all of those key value pairs on the actual execution resource, what we do is we create a frame only when the data actually changes. So initially when the application is running, there is no frame. We haven't set any values. The first time an ALS instance is used, we will create a frame and set that value and that frame actually maintains that map. The execution resource only maintains a reference to the current frame. So when that resource is created, we just will link it to whatever frame is current. We only create new frames when a new value is specified.
Comments