| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Thanks for looking at this. Do we not risk getting a very long chain of PromiseWrap objects that prevents all the promises in the chain from being easily garbage collected? I was thinking it might be better to use the asyncId of the parent, rather than the PromiseWrap itself. If the user want to walk the .parent chain they can just store the information in a Map. There is also the problem of resource.parent.parent being misleading if the PromiseHooks were enabled late. By returning the parent id it will always be correct and if the user enables PromiseHooks late they just don't have the information to walk the .parent chain, which is a reasonable consequence. /cc @JiaLiPassion |
Sorry, something went wrong.
|
Also, cc @Fishrock123 who was the first to request this. |
Sorry, something went wrong.
|
@addaleax , thank you for implementing this. @AndreasMadsen , are you suggestion to pass the asyncId of the parent promise in init hook like below? const parent_promise = new Promise((resolve, reject) => {resolve(5);});
const promise = parent_promise.then((val) => {return val;});
function init(id, type, triggerId, handle) {
process._rawDebug(`id: ${id}, type: ${type}, triggerId: ${triggerId},
handle.promise: ${handle.promise},
handle.parentid: ${handle.parentId}`);
}the output will look like id: 2, type: PROMISE, triggerId: 1, handle.promise: {status: 'pending'}, handle.parentid: undefined
id: 3, type: PROMISE, triggerId: 2, handle.promise: {status: 'pending'}, handle.parentid: 2
And if application want the promise object, they can keep a asyncId and promise map |
Sorry, something went wrong.
Yes. That is exactly what I mean. |
Sorry, something went wrong.
|
@AndreasMadsen , got it! I still try to understand the C++ code, |
Sorry, something went wrong.
|
@AndreasMadsen @JiaLiPassion Updated!
If you have any questions, please ask them, here or in the diff – whatever you want to know, a lot of other people will also like to know. |
Sorry, something went wrong.
@addaleax , got it! |
Sorry, something went wrong.
There was a problem hiding this comment.
What is the cost of this? If there is any I don't think we should add it. The result is given as the first parameter in init anyway and we generally don't document that getAsyncId exists.
Sorry, something went wrong.
There was a problem hiding this comment.
I thought it’s nice to have for consistency, but removing it is trivial. I’ve removed it for now, we can always revisit if necessary.
I haven’t measured, but I can’t really imagine it’s costly – it adds a method to the prototype, which should be practically free.
Sorry, something went wrong.
There was a problem hiding this comment.
My V8-C++ knowledge might be lacking, but why do we check that resource_object_value is an Object and then cast it to an Object.
Sorry, something went wrong.
There was a problem hiding this comment.
.As<Object>() is not a cast in the JS sense of the word; you can read it as telling the engine “I’ve made sure that this is an object, now can I please use it as one?” (i.e. calling handle.As<T>() is undefined behaviour if handle is not actually a T)
Sorry, something went wrong.
There was a problem hiding this comment.
Ah, similar to reinterpret_cast.
Sorry, something went wrong.
There was a problem hiding this comment.
In addition a Debug build it asserts, so instead of simply crashing b/c it was cast to the wrong type it'll actually say you've screwed up.
Sorry, something went wrong.
There was a problem hiding this comment.
Code LGTM. Since zone.js will be dependent on this, I think should document the PromiseWrap resource object.
Sorry, something went wrong.
|
@AndreasMadsen I’ve added some documentation… PTAL |
Sorry, something went wrong.
There was a problem hiding this comment.
Maybe we should add PROMISE to the provider list in async_wrap.
Sorry, something went wrong.
There was a problem hiding this comment.
I’ve kept it out of it because it doesn’t quite qualify as “provided by the built-in Node.js modules”, but if you think it’s better, I can just drop this sentence and reword the existing text a bit
Sorry, something went wrong.
There was a problem hiding this comment.
No just leave it out for now. @trevnorris suggested that maybe we should add all types to the Providers list. See #13287 (comment)
Sorry, something went wrong.
There was a problem hiding this comment.
Hm. Seems we don't even include Timer or TickObject in that list. Or even as a side comment.
Anyway, only argument I'd have for adding it to the above list is because it shows up in process.binding('async_wrap').Providers. But that's not a strong argument. I'll leave this up to you.
Sorry, something went wrong.
There was a problem hiding this comment.
I think we should delete the list. The user shouldn't really on a defined list of types because the Embedder API allows for extra types.
Sorry, something went wrong.
There was a problem hiding this comment.
@AndreasMadsen The reason I decided to pass the "type" (history note: using Provider was not the name I wanted to use, but switched long ago b/c of pressure to change on the PR) was for to allow filtering resources. I'd like to have a list of all "core types" (which would include TickObject and Timer) and I'd expect module authors to document their own "types".
Though because this relies a bit on internals could we put a note like "subject to change in future major (or minor?) releases without deprecation"?
Sorry, something went wrong.
There was a problem hiding this comment.
We already have a note saying resource objects are not to be trusted:
... The API for getting this information is currently not considered public ...
I guess we can be more specific.
Sorry, something went wrong.
There was a problem hiding this comment.
@addaleax , sorry for very basic question, why we add
MakeWeak(this);in this PR, since now we only keep the asyncId of parent promise here, is there any GC issue if we don't call MakeWeak ?
Sorry, something went wrong.
There was a problem hiding this comment.
This question is not basic – it’s something I didn’t quite figure out until a couple days ago myself. And I’m not sure whether you’ve seen it, but the current MakeWeak call is being removed here, too: https://github.com/nodejs/node/pull/13452/files#diff-5e552c79e1538215f1621d1774852e71L315
The thing is, MakeWeak is a not the best choice of name. What it actually does is to set the 0th internal field of the associated object to the passed pointer, and then mark the handled contained in the Wrap object as weak and set a destroy callback for V8 to call.
And it needs to then make handle weak, because otherwise all V8 knows is that there is a persistent handle to the object; it doesn’t know how we use it, so it can’t garbage collect it. By making it weak, we tell V8 to destroy it once there are no other (non-weak) handles left, and to run our registered destroy callback (which will delete the C++ instance of PromiseWrap that we are using).
I agree, it’s all a bit tricky to see through. I’m mostly moving it here because that helps with avoiding duplication, and because that’s how we use it elsewhere in the code as well.
Sorry, something went wrong.
There was a problem hiding this comment.
@addaleax , thank you for the explanation. I just read MakeWeak API and node_object_wrap.h, and I will continue to learn about it.
And I am not quite understand is why we don't need the MakeWeak call before this version?
Sorry, something went wrong.
There was a problem hiding this comment.
And I am not quite understand is why we don't need the MakeWeak call before this version?
It was there, it was just called after the constructor instead of being a part of it: https://github.com/nodejs/node/pull/13452/files#diff-5e552c79e1538215f1621d1774852e71L315
Sorry, something went wrong.
There was a problem hiding this comment.
@addaleax , oh, yes, it was there, thanks. Currently I have no further questions!
Sorry, something went wrong.
There was a problem hiding this comment.
The thing is, MakeWeak is a not the best choice of name. What it actually does is to set the 0th internal field of the associated object to the passed pointer, and then mark the handled contained in the Wrap object as weak and set a destroy callback for V8 to call.
And... I'm to blame for this one. In fe2df3b I carefully went through to make sure Wrap() and ClearWrap() were called for all applicable instances forgetting that 3.5 years ago for whatever forsaken reason when I implemented BaseObject (d120d92) I made MakeWeak() automatically Wrap() the object. This was a horrible mistake on my part
Basically I would be happy if we removed the call to Wrap() in BaseObject::MakeWeak().
I just read MakeWeak API and node_object_wrap.h, and I will continue to learn about it.
Be careful. AsyncWrap doesn't use node_object_wrap. It uses base-object
Sorry, something went wrong.
There was a problem hiding this comment.
Be careful. AsyncWrap doesn't use node_object_wrap. It uses base-object
thank you for pointing out this one.
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM.
I set it to semver-minor since this is an API change, although technically we make less than experimental guarantees about the resource object, so an argument could be made for semver-patch.
I think we should remove the type list. The user shouldn't really on a defined list of types because the Embedder API allows for extra types. However, it is not related to the PR.
Sorry, something went wrong.
👍 (@AndreasMadsen If you put comments in the "review summary" I can't 👍 them) |
Sorry, something went wrong.
I know. I prefer it this way :D evil laughter |
Sorry, something went wrong.
Sorry, something went wrong.
There was a problem hiding this comment.
nit: this is only used in the if statement below so mind just making it:
Local<Object> resource_object = resource_object_value.As<Object>();
Sorry, something went wrong.
Use `PromiseWrap` resource objects whose lifetimes are tied to the `Promise` instances themselves to track promises, and have a `.promise` getter that points to the `Promise` and a `.parent` property that points to the parent Promise’s resource object, if there is any. The properties are implemented as getters for internal fields rather than normal properties in the hope that it helps keep performance for the common case that async_hooks users will often not inspect them.
Sorry, something went wrong.
There was a problem hiding this comment.
Thank you much
Sorry, something went wrong.
Use `PromiseWrap` resource objects whose lifetimes are tied to the `Promise` instances themselves to track promises, and have a `.promise` getter that points to the `Promise` and a `.parent` property that points to the parent Promise’s resource object, if there is any. The properties are implemented as getters for internal fields rather than normal properties in the hope that it helps keep performance for the common case that async_hooks users will often not inspect them. PR-URL: #13452 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Use `PromiseWrap` resource objects whose lifetimes are tied to the `Promise` instances themselves to track promises, and have a `.promise` getter that points to the `Promise` and a `.parent` property that points to the parent Promise’s resource object, if there is any. The properties are implemented as getters for internal fields rather than normal properties in the hope that it helps keep performance for the common case that async_hooks users will often not inspect them. PR-URL: #13452 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Use `PromiseWrap` resource objects whose lifetimes are tied to the `Promise` instances themselves to track promises, and have a `.promise` getter that points to the `Promise` and a `.parent` property that points to the parent Promise’s resource object, if there is any. The properties are implemented as getters for internal fields rather than normal properties in the hope that it helps keep performance for the common case that async_hooks users will often not inspect them. PR-URL: #13452 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Use `PromiseWrap` resource objects whose lifetimes are tied to the `Promise` instances themselves to track promises, and have a `.promise` getter that points to the `Promise` and a `.parent` property that points to the parent Promise’s resource object, if there is any. The properties are implemented as getters for internal fields rather than normal properties in the hope that it helps keep performance for the common case that async_hooks users will often not inspect them. PR-URL: #13452 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Use `PromiseWrap` resource objects whose lifetimes are tied to the `Promise` instances themselves to track promises, and have a `.promise` getter that points to the `Promise` and a `.parent` property that points to the parent Promise’s resource object, if there is any. The properties are implemented as getters for internal fields rather than normal properties in the hope that it helps keep performance for the common case that async_hooks users will often not inspect them. PR-URL: #13452 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Use `PromiseWrap` resource objects whose lifetimes are tied to the `Promise` instances themselves to track promises, and have a `.promise` getter that points to the `Promise` and a `.parent` property that points to the parent Promise’s resource object, if there is any. The properties are implemented as getters for internal fields rather than normal properties in the hope that it helps keep performance for the common case that async_hooks users will often not inspect them. PR-URL: #13452 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
| Back | FazBrowse Home | New Git URL |
As discussed in #13367. /cc @nodejs/async_hooks
Use PromiseWrap resource objects whose lifetimes are tied to
the Promise instances themselves to track promises, and have
a .promise getter that points to the Promise and a .parent
property that points to the parent Promise’s resource object,
if there is any.
The properties are implemented as getters for internal fields
rather than normal properties in the hope that it helps keep
performance for the common case that async_hooks users will
often not inspect them.
Checklist
Affected core subsystem(s)
async_hooks