-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
bootstrap: reorganize the bootstrap process #27539
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
cc @nodejs/process |
Based on the GitHub reviewer suggestions...@addaleax @bnoordhuis @jasnell can I have some review please? |
Ping...I would like to have this landed first before moving to snapshot more of the bootstrap process (it won't be possible without changing the order of inspector and event loop initialization, really) |
Can this be broken down into multiple commits? That might make review easier... |
Ok, so I try not to mention this because it's what we (NodeSource) have signed up for in maintaining our own node fork/runtime (N|Solid)... however for Node 12 so much of the startup and related internals have been moved around so much that the rebase pain is quite immense. 😓 Are we really gaining much from doing these changes...? (I mean, this PR is particular..) |
@Fishrock123 This is required for including these parts in the v8 snapshot, see the design doc on the constraints the Environment needs to follow in order for it to be snapshottable. I think I've laid out the reasons for doing these in the PR message clearly enough, but to explain further:
On how this refactoring is used, see this for a prototype. The alternative to refactoring is..well, copy pasting all these code for the snapshot creator, and adding a bunch of deserialization in the middle, like what was done in the initial prototype of the RFC. That would not be maintainable, and may not really help with rebasing as there would still be conflicts with deserialization code. |
By the way, from my experience maintaining a similar fork in my previous job, one way to make the rebasing easier is instead of rebasing, squash the changes into commits that make sense, and cherry-picking them onto the upstream branches. This is especially important for paths like the bootstrap, because it has been quite messy - most things were done in a certain order for no particularly good reason but simply because it worked. The downstream patches likely follow the same kind of reasoning when they add stuff in the middle, so once someone tries to make the upstream more organized, there would be a lot of conflicts since the patches still relied on that disorganized state of things. It would be easier to bring the two together if the downstream patches encapsulate what they need to do in a few method invocations (with implementation details written in separate files to reduce conflicts), and when being cherry-picked onto the upstream, just insert the invocation to the new places where it makes more sense for these to happen. The worst that could happen is when you implement things right inside the upstream files in the middle of the code that's being refactored, and the downstream commits are mixed in the history with the upstream commits. Then it would very difficult to rebase once a refactored branch comes out (I had worked with that kind of git states before so I know how painful it could be). Although once the upstream starts to become organized, it tend to be easier to merge the two from then on because the patches are then inserted into logical places that tend to stabalize. |
Inline `ProcessCliArgs()` in the `Environment` constructor, and emit the `Environment` creation trace events with the arguments earlier. Remove the unused arguments passed to `CreateProcessObject()` since these are now attached to process in `PatchProcessObject()` during pre-execution instead.
Move creation of `env->as_callback_data()`, `env->primordials()` and `env->process()` into `Environment::CreateProperties()` and call it in the `Environment` constructor - this can be replaced with deserialization when we snapshot the per-environment properties after the instantiation of `Environment`.
- Split the initialization of the inspector and other diagnostics into `Environment::InitializeInspector()` and `Environment::InitializeDiagnostics()` - these need to be reinitialized separately after snapshot deserialization. - Do not store worker url alongside the inspector parent handle, instead just get it from the handle. - Rename `Worker::profiler_idle_notifier_started_` to `Worker::start_profiler_idle_notifier_` because it stores the state inherited from the parent env to use for initializing itself.
Split `RunBootstrapping()` into `BootstrapInternalLoaders()` and `BootstrapNode()` from so the two can be snapshotted incrementally.
ca713c3
to
8d400df
Compare
@Fishrock123 @addaleax @bnoordhuis @jasnell I split the PR into multiple commits, the descriptions are updated in the OP. PTAL, thanks! |
Pinging for reviews again...this has been open for over three weeks without any reviews |
src/node.cc
Outdated
Isolate* isolate = env->isolate(); | ||
Local<Context> context = env->context(); | ||
isolate_->GetHeapProfiler()->AddBuildEmbedderGraphCallback( | ||
Environment::BuildEmbedderGraph, this); |
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.
This is dependent on #if HAVE_INSPECTOR
now, but you can do heap dumps without the inspector, so should we maybe not do this here? (Sorry that I’m bringing it up again 😄)
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.
An right, maybe it also makes sense to move it back to InitializeDiagnostics
and then we invoke InitializeDiagnostics
before InitializeInspector
. The other part of InitializeDiagnostics
is adding GC callbacks for dtrace, I think it also make sense to do that before starting the inspector agent.
8b92cc7
to
bd13830
Compare
Landed in f0018a5...0778599 |
Inline `ProcessCliArgs()` in the `Environment` constructor, and emit the `Environment` creation trace events with the arguments earlier. Remove the unused arguments passed to `CreateProcessObject()` since these are now attached to process in `PatchProcessObject()` during pre-execution instead. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
Move creation of `env->as_callback_data()`, `env->primordials()` and `env->process()` into `Environment::CreateProperties()` and call it in the `Environment` constructor - this can be replaced with deserialization when we snapshot the per-environment properties after the instantiation of `Environment`. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
- Split the initialization of the inspector and other diagnostics into `Environment::InitializeInspector()` and `Environment::InitializeDiagnostics()` - these need to be reinitialized separately after snapshot deserialization. - Do not store worker url alongside the inspector parent handle, instead just get it from the handle. - Rename `Worker::profiler_idle_notifier_started_` to `Worker::start_profiler_idle_notifier_` because it stores the state inherited from the parent env to use for initializing itself. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
Split `RunBootstrapping()` into `BootstrapInternalLoaders()` and `BootstrapNode()` from so the two can be snapshotted incrementally. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
Inline `ProcessCliArgs()` in the `Environment` constructor, and emit the `Environment` creation trace events with the arguments earlier. Remove the unused arguments passed to `CreateProcessObject()` since these are now attached to process in `PatchProcessObject()` during pre-execution instead. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
Move creation of `env->as_callback_data()`, `env->primordials()` and `env->process()` into `Environment::CreateProperties()` and call it in the `Environment` constructor - this can be replaced with deserialization when we snapshot the per-environment properties after the instantiation of `Environment`. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
- Split the initialization of the inspector and other diagnostics into `Environment::InitializeInspector()` and `Environment::InitializeDiagnostics()` - these need to be reinitialized separately after snapshot deserialization. - Do not store worker url alongside the inspector parent handle, instead just get it from the handle. - Rename `Worker::profiler_idle_notifier_started_` to `Worker::start_profiler_idle_notifier_` because it stores the state inherited from the parent env to use for initializing itself. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
Split `RunBootstrapping()` into `BootstrapInternalLoaders()` and `BootstrapNode()` from so the two can be snapshotted incrementally. PR-URL: #27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
This patch reorganizes the bootstrap process so it's easier
to snapshot it incrementally.
src: inline ProcessCliArgs in the Environment constructor
Inline
ProcessCliArgs()
in theEnvironment
constructor, andemit the
Environment
creation trace events with the argumentsearlier. Remove the unused arguments passed to
CreateProcessObject()
since these are now attached to process in
PatchProcessObject()
during pre-execution instead.
src: create Environment properties in Environment::CreateProperties()
Move creation of
env->as_callback_data()
,env->primordials()
and
env->process()
intoEnvironment::CreateProperties()
andcall it in the
Environment
constructor - this can be replaced withdeserialization when we snapshot the per-environment properties
after the instantiation of
Environment
.src: reorganize inspector and diagnostics initialization
into
Environment::InitializeInspector()
andEnvironment::InitializeDiagnostics()
- these need to bereinitialized separately after snapshot deserialization.
instead just get it from the handle.
Worker::profiler_idle_notifier_started_
toWorker::start_profiler_idle_notifier_
because it storesthe state inherited from the parent env to use for initializing
itself.
src: Split
RunBootstrapping()
Split
RunBootstrapping()
intoBootstrapInternalLoaders()
and
BootstrapNode()
from so the two can be snapshottedincrementally.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes