Repository navigation
Research Discussion: Faster startup with dynamically generated custom v8 snapshots #9473
Description
Activity
Well,
vmalready has a way to produce/use binary code cache data. Is that what you're after or ?- addedquestionIssues asking questions about Node.js.Issues asking questions about Node.js.feature requestIssues requesting new Node.js features.Issues requesting new Node.js features.and removedquestionIssues asking questions about Node.js.Issues asking questions about Node.js.
on Nov 5, 2016 @phestermcs It's probably not a V8 snapshot proper. The
vmoptions I was referring to specifically werecachedDataandproduceCachedData. Also, see this V8 blog post about it.- ghost changed the title
[-]Discussion: Faster startup with auto custom v8 snapshots[/-][+]Discussion: Faster startup with dynamically generated custom v8 snapshots[/+]on Nov 5, 2016 At a high level I'm wondering if my understanding is correct, that a v8 snap is a heap dump that can be reloaded into an isolate, and that when a new context is created in the isolate it starts with modules already jitted, having come from the snap.
That's correct. A snapshot is essentially the serialized state of the process at the time the snapshot was taken. It's a bit like emacs's unexec or sbcl's save-lisp-and-die command.
cachedDatadoes something different, it's just a precompile step. It takes source code and compiles it into baseline machine code but it doesn't optimize or run it. Unless you are on a slow system (like raspberry pi 1 slow), the overhead of the baseline compiler is negligible for most applications.The problem with snapshots is that there is no way to revive external state, like file descriptors, child processes, etc. That makes it useless for quickstarting most applications.
- ghost changed the title
[-]Discussion: Faster startup with dynamically generated custom v8 snapshots[/-][+]Resarch Discussion: Faster startup with dynamically generated custom v8 snapshots[/+]on Nov 6, 2016 - ghost changed the title
[-]Resarch Discussion: Faster startup with dynamically generated custom v8 snapshots[/-][+]Research Discussion: Faster startup with dynamically generated custom v8 snapshots[/+]on Nov 6, 2016 The embedder - i.e., node.js - can register FunctionTemplates and ObjectTemplates when the snapshot is created. There is probably no way to make that work for native add-ons, though.
Hard to say whether it's going to be significantly faster on average. Taking a snapshot right after start-up won't help much if your application doesn't do significant processing at start-up. Most of the main application will still be baseline code (or won't have been compiled at all if lazy compilation is enabled) because it hasn't run long enough to reach the optimizing tier.
- addeddiscussIssues opened for discussion and feedback.Issues opened for discussion and feedback.
on Nov 7, 2016 Regarding Templates, I'm thinking registering them wouldn't be a problem, rather having an instance of them in the heap, that was still referenced, would be the problem; when the snap would be deserialized in a new isolate, those instances would be pointing to who knows what.
If I understand your concern correctly: there is a mechanism for saving and restoring FunctionTemplate function pointers and a similar (albeit not identical) mechanism for internal fields.
(Untested but I suspect there are actually several ways to restore function pointers. One is Isolate::CreateParams::external_references, another is FunctionTemplate::FromSnapshot() followed by FunctionTemplate::SetCallHandler().)
what is the difference in performance between just baseline compiled code vs. having been fully optimized as much as possible?
I'd say 1.5-2x on average. If you want to try it out,
--nocrankshaftdisables the optimizing tier.I can't help but kinda 'know' there's just no way that going from utf8 text across thousands of files, to a single chunk of optimized code, is done so fast that it shouldn't matter.
I wouldn't say it's so fast it never matters but the baseline compiler is really just a template JIT: it's not smart at all, it's just fast (but not fast enough on mobile systems, hence the Ignition interpreter that is being added.)
Lazy compilation is another factor (and is enabled by default): generating machine code for a function doesn't happen until the first time it's called.
If you know about v8 snapshots, and node's 'default' snapshot, you might be able to provide insight into this discussion.
I seem to be using more and more 'commands' that are node based. When I run them, like npm, it's my understanding node has to reload and recompile the entry.js and all its require()d modules every time.
I'm wondering if just before node exited, if it could take a v8 snap and save it to a file named to correlate to the full path of entry.js. (obviously optimized to only snap when something changed however, so not every time node exited)
Then, when node was launched again, it could look for a saved snap based on entry.js and just create a new context from that snap, effectively getting to an executing state much faster.
At a high level I'm wondering if my understanding is correct, that a v8 snap is a heap dump that can be reloaded into an isolate, and that when a new context is created in the isolate it starts with modules already jitted, having come from the snap. But wouldn't there be some state that was 'left over' from the original snap that could potentially 'infect' the new context in some non deterministic way? Like say a module set a flag within itself, then the snap was taken, then when reloaded the flag would still be set?
Is there even a possibility, in some way, to save something from run to run, such that entry.js and all require()'d modules don't have to be parsed/jitted every time?