Skip to content

RFC: speeding up Node.js startup using V8 snapshot #17058

Description

@hashseed

I recently went through Node.js bootstrapping code, and think that we could make it a lot faster using V8 snapshot. I wrote a design doc that captures the main points.

This is somewhat separate from the discussion on using V8 snapshot to capture arbitrary initialized state, discussed here. The main difference is that the set of native modules is known upfront, and there is no ambiguity about the native bindings that need to be known to V8's serializer/deserializer.

I'm doing this as sort of a side project, so it may take some time for me to make progress. Any help is welcome.

Activity

  1. added
    discussIssues opened for discussion and feedback.
    feature requestIssues requesting new Node.js features.
    help wantedIssues that need assistance from volunteers or PRs that need help to proceed.
    v8 engineIssues and PRs related to the V8 dependency.
    on Nov 15, 2017
  2. added
    performanceIssues and PRs related to the performance of Node.js.
    on Nov 15, 2017
  3. deleted a comment from rehack on Nov 17, 2017
  4. mhdawson commented on Nov 17, 2017

    @mhdawson
    Member

    Sounds great. Is there a repo/branch people can take a look at the changes you have so far for this work ?

  5. hashseed commented on Nov 17, 2017

    @hashseed
    MemberAuthor

    I have a development branch here. All tests still pass, because they are not affected. Running node snapshot attempts to create a snapshot blob. It currently still fails, but I have collected almost all native references. There is still a long way to go though.

  6. juancampa commented on Nov 18, 2017

    @juancampa

    Hi @hashseed, this is amazing and very needed, thanks for working on this. I asked on #17103 but it seems pertinent to this thread (since it's an RFC) so I'll ask here as well.

    Would these changes allow for taking snapshots in arbitrary points in time? as opposed to right after startup? If not, do you mind explaining if such a thing would even be feasible. Seems like the guys from Chakra have been working on something like it for Time Travel Debugging (as mentioned by @mrkmarron: #13877 (comment))

    To elaborate a little, I'm thinking something like CRIU, where you can send a signal to the process (e.g. kill -USR2 <pid> or some other mechanism) and have the process serialize it's state (to a predefined location maybe) and optionally exit. Then later in time you could restore that serialized state by providing it to a new node process (e.g. node --restore <state-file>)

  7. hashseed commented on Nov 18, 2017

    @hashseed
    MemberAuthor

    It would, once finished, help achieve that goal. Current V8 API is not laid out to serialize arbitrary isolates at arbitrary times, but something in that direction would be thinkable.

    However, there are quite a few C++ objects allocated by native modules. Each module would have to provide a way to serialize/deserialize its objects, and we would need a way to dispatch to each module for serialization/deserialization. This hurdle applies to Node with Chakra too.

    Another issue is that there is no good way to serialize/deserialize the stack, including C++ frames and local variables that hold onto objects on the JS heap.

  8. mrkmarron commented on Nov 19, 2017

    @mrkmarron

    Hi @hashseed, I was able to take a quick look at the document and the commits. As you say it looks like there is a lot of work left but this looks like a great start. Please let me know if there is anything that might be useful to help and I will try to make some time. Otherwise, I'll definitely keep an eye on the progress here.

    Thanks for this effort!

  9. hashseed commented on Nov 19, 2017

    @hashseed
    MemberAuthor

    Hi Mark,

    this is more of a solve-issues-as-we-go approach. Once I have a roughly working version done, there will be some more careful auditing necessary to see which part of initialization needs to be done after snapshotting because they are runtime-dependent, for example gated by command line args. Maybe that's something you can dig into, if you have the time?

  10. mrkmarron commented on Nov 20, 2017

    @mrkmarron

    Sure, I have looked into this type of thing in the past. The two most common approaches seem to be either (1) making this type of startup a pure programmer responsibility or (2) using symbolic execution (ala prepack). Neither solution is 100% satisfactory but I'll try to spend some time investigating to get a better understanding of things.

  11. hashseed commented on Nov 20, 2017

    @hashseed
    MemberAuthor

    I updated the branch. So far running node snapshot creates a snapshot_blob.bin file into the working directory. With the file in place, running node uses the snapshot, deserializes an isolate and a context, and then immediately quits (because I haven't spent time on making the deserialized context work yet :D).

    For some reason I wasn't able to reproduce the 400ms start up for vanilla Node.js anymore, but rather 200ms. I wonder whether I made some mistake with the build. But when I instrumented my branch with uv_hrtime() I was at least able to reproduce 4x speed up.

    I'll carry on to make the deserialized context actually work.

  12. hashseed commented on Nov 20, 2017

    @hashseed
    MemberAuthor

    @addaleax @bnoordhuis @TimothyGu is there any reason we store the environment in a v8::External object to pass to function templates as data, instead of getting the current context from the isolate and the environment from there?

    v8::Externals are tricky to serialize. They should belong to the context. Function and object templates belong to the isolate, but can own v8::External objects as data. With the current API there is no good way serialize templates as part of the context.

    v8::External objects are also kinda hacky. They look like JavaScript objects, but are special in that they are context-independent and don't have a constructor.

  13. 94 remaining items

  14. added a commit that references this issue on Jul 4, 2020
  15. joyeecheung commented on Oct 4, 2020

    @joyeecheung
    Member

    Since the core bootstrap is now in the builtin snapshot, and we are working towards including more of the bootstrap into the snapshot, maybe it's time to close this and open a new tracking issue?

  16. gengjiawen commented on Oct 4, 2020

    @gengjiawen
    Member

    Since the core bootstrap is now in the builtin snapshot, and we are working towards including more of the bootstrap into the snapshot, maybe it's time to close this and open a new tracking issue?

    LGTM.

  17. joyeecheung commented on Oct 19, 2020

    @joyeecheung
    Member

    Opened #35711 for discussions around future snapshot work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    discussIssues opened for discussion and feedback.feature requestIssues requesting new Node.js features.help wantedIssues that need assistance from volunteers or PRs that need help to proceed.performanceIssues and PRs related to the performance of Node.js.v8 engineIssues and PRs related to the V8 dependency.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions