Skip to content
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

Reland "refactor(core): cleanup feature flags for js source inclusion" #19519

Merged

Conversation

nayeemrmn
Copy link
Collaborator

Relands #19463. This time the ExtensionFileSourceCode enum is preserved, so this effectively just splits feature include_js_for_snapshotting into exclude_js_sources and runtime_js_sources, adds a force_include_js_sources option on extension!(), and unifies ext::Init_ops_and_esm() and ext::init_ops() into ext::init().

Copy link
Contributor

@mmastrac mmastrac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few comments -- will let @bartlomieju look at this before we go further on it but thanks for putting it back together with the changes I made to the runtime.

core/01_core.js Outdated Show resolved Hide resolved
core/modules/loaders.rs Show resolved Hide resolved
Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking as "request changes" because we need a few more passes before landing.

cli/build.rs Outdated
Comment on lines 321 to 322
code: ExtensionFileSourceCode::LoadAtRuntime(
PathBuf::from("../runtime/js/99_main.js"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things here: a) my opinion is that ExtensionFileSourceCode is super helpful and we should keep it because this immediately caught my attention; b) why is this file loaded at runtime and not snapshotted?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this file loaded at runtime and not snapshotted?

It's loaded at the 'runtime' of this build script, as it was before. I renamed the variant to match precisely what it does since it's a public API and can be used with extension builders or customizers. A name like LoadFromFsDuringSnapshot is counterintuitive because it might trick users into thinking its filtered out or otherwise guarded against when not snapshotting, whereas this is more cautionary to avoid using it outside of build scripts.

(FTR the first PR removed ExtensionFileSourceCode because there was no load-at-runtime case. It worked by just bundling everything since it only applied to build.rs contexts. I still don't know where the size increase came from 🙁)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the size increase either but I guess the linker cannot prove the source wasn't used.

Comment on lines +37 to +43
// Provide bootstrap namespace
globalThis.__bootstrap ??= {};
const key = Symbol.for("00_primordials.js");
if (globalThis.__bootstrap[key]) {
return;
}
globalThis.__bootstrap[key] = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I get it right that this file can be actually executed multiple times when creating snapshots? Does it mean that all files that are snapshotted have this caveat or maybe it's only limited to "scripts" (ie. not ES modules).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's just a trade-off of unifying init_ops_and_esm() and init_ops(). ES modules already have identities attached to their specifiers, with just the minor change of making mod_evaluate() idempotent.

core/Cargo.toml Outdated Show resolved Hide resolved
core/extensions.rs Show resolved Hide resolved
core/extensions.rs Outdated Show resolved Hide resolved
core/inspector.rs Outdated Show resolved Hide resolved
core/runtime/jsruntime.rs Outdated Show resolved Hide resolved
runtime/js.rs Outdated Show resolved Hide resolved
Comment on lines -217 to -222
$(
ext.esm(vec![ExtensionFileSource {
specifier: "ext:setup",
code: ExtensionFileSourceCode::IncludedInBinary($esm_setup_script),
}]);
)?
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed this feature since it's unused and doesn't make sense because it uses the same specifier and can't be used for more than one extension.

@bartlomieju
Copy link
Member

@nayeemrmn we're OOO this week. I'll review your PR over the weekend.

Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I'm gonna be watching benchmarks page after landing this PR to make sure there's no regression in the binary/snapshot size.

Comment on lines +883 to +891
{
let module_map_rc = self.module_map.clone();
let module_map = module_map_rc.borrow();
let handle = module_map.handles.get(mod_id).unwrap().clone();
let mut scope = realm.handle_scope(self.v8_isolate());
let handle = v8::Local::new(&mut scope, handle);
if handle.get_status() == v8::ModuleStatus::Evaluated {
continue;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better :)

@bartlomieju bartlomieju merged commit 28a4f3d into denoland:main Jun 25, 2023
10 checks passed
@bartlomieju
Copy link
Member

@nayeemrmn there's still 750kB increase in the binary size :(

Screenshot 2023-06-25 at 10 49 42

Screenshot 2023-06-25 at 10 49 45

@bartlomieju
Copy link
Member

I'm still trying to figure out what's going on here - all the files are marked as LoadAtRuntime and I don't see any file being include_str!() during the build process.

@bartlomieju
Copy link
Member

bartlomieju commented Jun 25, 2023

I'm still debugging it, but I can definitely see all JavaScript sources loaded for snapshotting being included in the binary. Is there any other way they could have been included besides include_js_files!?

EDIT: I might have been wrong, opening deno (latest release) in binary editor I can see these files included as well - they are probably inside the snapshot. So probably a red herring.

However there's a difference - in latest release there appears to be 290 files included, while after this PR there are 308 files. So appears we have 18 duplicate files.

@nayeemrmn nayeemrmn deleted the snapshot-feature-flag-cleanup-reland branch June 25, 2023 15:23
@nayeemrmn
Copy link
Collaborator Author

nayeemrmn commented Jun 25, 2023

However there's a difference - in latest release there appears to be 290 files included, while after this PR there are 308 files. So appears we have 18 duplicate files.

I think you're using the debug binary to get 308. Comparing the canary releases for a181ceb and 28a4f3d, I get 291 both before and after (a file was added in #19223). I assume we're both searching with the copyright header.

Last thing I can think of is the duplicate calls to load_side_module() on cli snapshot creation which ends up calling .instantiate_module() for each module handle again. It shouldn't do anything for a kEvaluated module but who knows.
Edit: Nope not this.

@bartlomieju
Copy link
Member

I think you're using the debug binary to get 308. Comparing the canary releases for a181ceb and 28a4f3d, I get 291 both before and after (a file was added in #19223). I assume we're both searching with the copyright header.

Yikes, that might have been it. I compared it to the latest released version. And yes, I was looking at the copyright headers in the produced binary.

Last thing I can think of is the duplicate calls to load_side_module() on cli snapshot creation which ends up calling .instantiate_module() for each module handle again. It shouldn't do anything for a kEvaluated module but who knows.
Edit: Nope not this.

That's a good pointer, but I believe V8 is smart enough, not to create a duplicate module entries.

Let's wait a few hours before we dig into it more - I think we will abandon the idea of not snapshotting ext/node (because of some other work and decisions). While I think this PR cleans up a lot, the fact that we can't establish where this binary increase is coming from is really worrisome.

bartlomieju added a commit to bartlomieju/deno that referenced this pull request Jun 26, 2023
bartlomieju added a commit that referenced this pull request Jun 26, 2023
#19611)

…nclusion" (#19519)"

This reverts commit 28a4f3d.

This change causes failures when used outside Deno repo:
```
============================================================
Deno has panicked. This is a bug in Deno. Please report this
at https://github.com/denoland/deno/issues/new.
If you can reliably reproduce this panic, include the
reproduction steps and re-run with the RUST_BACKTRACE=1 env
var set and include the backtrace in your report.

Platform: linux x86_64
Version: 1.34.3+b37b286
Args: ["/opt/hostedtoolcache/deno/0.0.0-b37b286f7fa68d5656f7c180f6127bdc38cf2cf5/x64/deno", "test", "--doc", "--unstable", "--allow-all", "--coverage=./cov"]

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Failed to read "/home/runner/work/deno/deno/core/00_primordials.js"

Caused by:
    No such file or directory (os error 2)', core/runtime/jsruntime.rs:699:8
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants