src: let embedders supply a builtin code cache without a snapshot - #65352
Open
codebytere wants to merge 1 commit into
Open
src: let embedders supply a builtin code cache without a snapshot#65352codebytere wants to merge 1 commit into
codebytere wants to merge 1 commit into
Conversation
Collaborator
|
Review requested:
|
jasnell
reviewed
Aug 17, 2026
jasnell
reviewed
Aug 17, 2026
codebytere
force-pushed
the
embedder/builtin-code-cache-seed
branch
from
August 17, 2026 13:25
1b99e86 to
136d2ad
Compare
jasnell
approved these changes
Aug 17, 2026
Collaborator
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #65352 +/- ##
==========================================
- Coverage 90.06% 90.05% -0.01%
==========================================
Files 754 754
Lines 255742 255803 +61
Branches 48314 48332 +18
==========================================
+ Hits 230341 230373 +32
- Misses 16534 16556 +22
- Partials 8867 8874 +7
🚀 New features to boost your workflow:
|
Collaborator
legendecas
reviewed
Aug 20, 2026
codebytere
force-pushed
the
embedder/builtin-code-cache-seed
branch
from
August 20, 2026 20:34
136d2ad to
d33c3df
Compare
legendecas
approved these changes
Aug 20, 2026
Collaborator
legendecas
reviewed
Aug 20, 2026
codebytere
force-pushed
the
embedder/builtin-code-cache-seed
branch
from
August 21, 2026 06:06
d33c3df to
e512f86
Compare
legendecas
approved these changes
Aug 21, 2026
Collaborator
joyeecheung
reviewed
Aug 25, 2026
codebytere
force-pushed
the
embedder/builtin-code-cache-seed
branch
from
August 26, 2026 14:16
e512f86 to
189fbb1
Compare
Collaborator
Environments created from the built-in snapshot get the builtins' code cache from that snapshot. An embedder that bootstraps an Environment from scratch (its own isolate and context, no EmbedderSnapshotData) has no way to provide one: every builtin the bootstrap touches is compiled from source in every such process, and each of them then serializes a fresh cache (SaveCodeCache) that only a later worker thread would ever consume. Add node::EmbedderBuiltinCodeCache for that case. Its entries pair a builtin id with a v8::ScriptCompiler::CachedData; Generate(context) compiles every builtin in a context of the right kind of isolate and returns them for a build step to embed, and SetBuiltinCodeCache(isolate_data, cache) attaches them to an IsolateData, next to where a snapshot's code cache lives, so that every Environment created from it afterwards starts with them. The setter runs CachedData::CompatibilityCheck() against the isolate first and returns the result, leaving the IsolateData untouched for a cache made with another V8 version, flag set or read-only snapshot. Entries from a snapshot still merge with it (RefreshCodeCache() now merges instead of assuming a single call). CreateEnvironment() plus LoadEnvironment() of an empty script goes from about 38 ms to 13 ms with a cache attached. ProcessInitializationFlags::kNoHarvestBuiltinCodeCache stops serializing caches for builtins compiled without one, for embedders that supply their own or never create workers. The default is unchanged because worker threads copy the harvested cache. A cctest generates a cache, attaches it, checks that a new Environment's bootstrap compiles from it and that a corrupted cache is refused; embedtest gains --no-harvest-builtin-code-cache for a test that a worker does or does not find a harvested cache depending on the flag. Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
codebytere
force-pushed
the
embedder/builtin-code-cache-seed
branch
from
August 30, 2026 15:58
189fbb1 to
d1c9826
Compare
Collaborator
Member
Author
|
@legendecas @joyeecheung PTAL |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An embedder that creates its Environments without Node's snapshot (its own isolate, no
EmbedderSnapshotData) compiles every builtin the bootstrap touches from source in each such process, and then serializes a fresh code cache for each of them that only a later worker thread ever reads. This adds a way to attach a cache built ahead of time to anIsolateData, plus a flag to skip the runtime serialization;nodeitself is unchanged.CreateEnvironment()+LoadEnvironment(env, "0"), fresh context, linux x64, n=6EmbedderBuiltinCodeCacheattached to theIsolateDatanode::EmbedderBuiltinCodeCacheholds entries pairing a builtin id with av8::ScriptCompiler::CachedData.EmbedderBuiltinCodeCache::Generate(context)compiles every builtin in a context made withnode::NewContext()and returns them for a build step to embed;node::SetBuiltinCodeCache(isolate_data, cache)attaches them next to where a snapshot's code cache lives, so every Environment created from thatIsolateDataafterwards starts with them (they share the buffers; the cache object can be freed after the call). The setter runsCachedData::CompatibilityCheck()against the isolate and returns the result, leaving theIsolateDatauntouched for a cache made with another V8 version, flag set or read-only snapshot. A snapshot's entries still merge with it, soRefreshCodeCache()merges withinsert_or_assigninstead of asserting a single call.ProcessInitializationFlags::kNoHarvestBuiltinCodeCachestopsLookupAndCompile()from serializing a cache for builtins compiled without one. The default stays as it is because worker threads start from that harvested cache.The per-context scripts
NewContext()runs (internal/per_context/*) are outside an Environment and keep compiling from source.Tests: a cctest generates a cache, attaches it, checks that a new Environment compiles
internal/bootstrap/nodeand everything outsideinternal/per_context/*from it, and that a corrupted cache is refused and anullptrclears it; a cctest for theRefreshCodeCachemerge;embedtestgains--no-harvest-builtin-code-cachefor an embedding test that a worker started with and without the flag does and doesn't find a harvested cache. embedding, cctest and the default suite pass.Disclosure: the code, tests, measurements and this description were written by Claude Code, directed and reviewed by @codebytere.