-
Notifications
You must be signed in to change notification settings - Fork 30.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
module: allow multiple chain #53332
module: allow multiple chain #53332
Conversation
`module.register` not supported when called from worker threads with this commit it only works for the main thread.
Co-authored-by: Geoffrey Booth <[email protected]>
Review requested:
|
This comment was marked as outdated.
This comment was marked as outdated.
In today's loaders meeting we discussed #53200 using |
db2acc1
to
55501e8
Compare
@dygabo @GeoffreyBooth @mcollina I've updated the PR with the feedback from the loaders' meeting. I've also updated the PR description above with the changes in the behavior of the new functionality. PTAL @dygabo There is only one test failing, and only in worker mode. I realized it happens due to the hang you described in #53200 (comment). Do you have bandwidth (and rough ETA) to fix it or do you want me to take care of that as well? |
I also put some time into it over the past few days but I have no immediate good news about it. It is difficult with the primitives that we have in this case to cover the usecase and come up with a race-free implementation of this. I still dig into the native code trying to come up with a solution but at the moment I am not very optimist about a satisfying result. EDIT: of course, if you have ideas and can work on it, I am happy with it. You could even push to my fork if you want. |
This comment was marked as outdated.
This comment was marked as outdated.
62388b1
to
4d7d078
Compare
4d7d078
to
12cdaeb
Compare
@dygabo @GeoffreyBooth @mcollina I've included this PR not to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
@alan-agius4 can you take a look?
@po there seem to be some related test failures https://ci.nodejs.org/job/node-test-commit-osx/59113/nodes=osx11-x64/testReport/junit/(root)/es-module/test_esm_hooks_chains/ |
I'll take a look soon. PS: you got fooled from my multiple nicks, isn't it? XD |
Are we really sure that this single thread for all customization hooks is the way to go? In my opinion the isolation topic is only partially solved as all hooks for all workers run in the same thread.
By the way, how is the behavior if the hook thread exists?
|
We can discuss it, though this PR is probably not the best place. Maybe #50752? The intent with moving the hooks off-thread was primarily so that the hooks could apply to CommonJS while still being async. Isolation from application code was viewed as a nice side effect, though not a primary goal. Even in the current behavior, separate hooks in the same chain still affect each other, because we have only one hooks thread for all hooks, not separate hooks threads for each set of registered hooks. The reasons for wanting one hooks thread for N application threads, instead of N hooks threads for N application threads, is performance (surely one thread is faster than N) and because most common use cases want shared state for the entire process. A TypeScript transpiler wants to cache its transpilation results globally, and not need to retranspile the same file N times for N threads. |
Depends. For CPU bound work it's slower as only one CPU can be utilized by one worker. But memory wise it's better. As long as current users of different loader chains like @alan-agius4 can't confirm that this limited isolation is fine I see the risk that this again breaks a lot users similar as the last try to go to a single thread did it. I agree that there are a lot valid usecases for global states but last approach clearly showed that there is more. Anyhow, if all are sure that this is the way to go I still miss a well defined error handling in case one of the hooks shows a problematic behavior. |
Yes would be totally fine for our use case. |
Closing as hooks are going back in thread. |
This PR is based on and includes commits from #53200.
Description
This PR introduces the following changes:
context
parameters to theinitialize
hook. The context contains the registering thread ID.initialize
's data to thecontext
's properties passed to theresolve
andload
hooks.How do "hooks chain" work?
Rather than maintaining a single chain of hooks for all threads as it is today, this PR introduces the concept of separate hooks chains.
Each thread has a separate chain registered inside the hooks thread. This chain is either copied from the parent thread when the thread is spawned or created from scratch if the thread is the first one calling
module.register
within the application code.This also covers the case where the
process.execArgv
contains--import
or--experimental-loader
. Since the chain copied from the parent already contains the (already initialized) hooks the duplicate register detection will prevent the arguments to be processed again.Thanks to
threadId
and theinitialize
's data this PR also covers the case where user want to use a singleton hook shared across threads. All these properties allow the hook to work differently depending on the context. Also, this will ensure that modification made to either parent or children after initialization don't affect other sibling threads.The only case not covered at the moment from this PR is the one in which the user want a worker thread to start with an empty chain. This is already in theory achievable as we already have the methods to empty a chain, but these methods are not exposed externally. Once we expose those, this case will be covered as well, leaving no other open cases I'm aware of.