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

feat: faster, lazy-friendly runtime loading #4181

Merged
merged 9 commits into from
Jul 25, 2023
Merged

Conversation

RomainMuller
Copy link
Contributor

@RomainMuller RomainMuller commented Jul 17, 2023

Instead of eagerly loading each type from the assemblies in order to annotate the constructors with jsii fully qualified type names (FQNs), leverage the jsii.rtti data that is injected by the jsii compiler since release 1.19.0.

This should make the jsii runtimes friendlier to large libraries that include lazy-loading provisions, such as the aws-cdk-lib.


In addition to this, JSII_RUNTIME_PACKAGE_CACHE was flipped from opt-in to opt-out (set it to any value other than enabled to disable), and the @jsii/runtime entry point now sets --preserve-symlinks so that we can symbolically link packages from the cache instead of copying them around, which is significantly faster.


Finally, the jsii kernel had not opted out of the assembly validation feature, which is redundant in the majority of scenarios, and is quite time-consuming (~500ms for aws-cdk-lib)... So also opting out, but allowing users to opt-back-in via an environment variable.


Example on a "simple" repro via aws-cdk-lib:

Before:

[@jsii/kernel:timing] tar.extract(<redacted>/.venv-vanilla/lib/python3.11/site-packages/aws_cdk/_jsii/[email protected]) => <redacted>/jsii-kernel-Xxp43L/node_modules/aws-cdk-lib: 1.909s
[@jsii/kernel:timing] loadAssemblyFromPath(<redacted>/jsii-kernel-Xxp43L/node_modules/aws-cdk-lib): 383.8ms
[@jsii/kernel:timing] require(<redacted>/jsii-kernel-Xxp43L/node_modules/aws-cdk-lib): 630.081ms
[@jsii/kernel:timing] registerAssembly({ name: aws-cdk-lib, types: 10957 }): 8.452ms
[@jsii/kernel:timing] load({
  "name": "aws-cdk-lib",
  "version": "2.87.0",
  "tarball": "<redacted>/.venv-vanilla/lib/python3.11/site-packages/aws_cdk/_jsii/[email protected]",
  "api": "load"
}): 2.933s

After:

[@jsii/kernel:timing] tar.extract(<redacted>/.venv-lazy/lib/python3.11/site-packages/aws_cdk/_jsii/[email protected]) => <redacted>/jsii-kernel-eAOMah/node_modules/aws-cdk-lib: 12.247ms
[@jsii/kernel:timing] loadAssemblyFromPath(<redacted>/jsii-kernel-eAOMah/node_modules/aws-cdk-lib): 388.388ms
[@jsii/kernel:timing] require(<redacted>/jsii-kernel-eAOMah/node_modules/aws-cdk-lib/lazy-index.js): 132.801ms
[@jsii/kernel:timing] registerAssembly({ name: aws-cdk-lib, types: 10957 }): 0.009ms
[@jsii/kernel:timing] load({
  "name": "aws-cdk-lib",
  "version": "2.87.0",
  "tarball": "<redacted>/.venv-lazy/lib/python3.11/site-packages/aws_cdk/_jsii/[email protected]",
  "api": "load"
}): 537.449ms

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Instead of eagerly loading each type from the assemblies in order to
annotate the constructos with jsii fully qualified type names (FQNs),
leverage the `jsii.rtti` data that is injected by the `jsii` compiler
since release `1.19.0`.
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Jul 17, 2023
@RomainMuller RomainMuller marked this pull request as ready for review July 17, 2023 12:41
@RomainMuller RomainMuller changed the title feat: leverage runtime type information in jsii runtime feat: faster, lazy-friendly runtime loading Jul 17, 2023
@RomainMuller RomainMuller force-pushed the rmuller/lazy-friend branch from 8ed8f68 to 8ab3813 Compare July 24, 2023 09:51
@mergify
Copy link
Contributor

mergify bot commented Jul 25, 2023

Thank you for contributing! ❤️ I will now look into making sure the PR is up-to-date, then proceed to try and merge it!

@mergify mergify bot added the pr/ready-to-merge This PR is ready to be merged. label Jul 25, 2023
@mergify
Copy link
Contributor

mergify bot commented Jul 25, 2023

Merging (with squash)...

@mergify mergify bot merged commit ef6e5b1 into main Jul 25, 2023
@mergify mergify bot deleted the rmuller/lazy-friend branch July 25, 2023 10:36
@mergify mergify bot removed the pr/ready-to-merge This PR is ready to be merged. label Jul 25, 2023
rix0rrr added a commit that referenced this pull request Aug 8, 2023
In #4181, a faster method to load
modules was introduced: symlinking instead of recursing through the
directory tree, mostly affecting the load times of large modules.

Since Windows Vista, non-Administrator users on Windows aren't allowed
to create symlinks anymore, so this new loading method fails for users
working in corporate Windows environments.

Catch the error and fall back to the slower copying method if that
happens.

Fixes #4208.
mergify bot pushed a commit that referenced this pull request Aug 8, 2023
In #4181, a faster method to load modules was introduced: symlinking instead of recursing through the directory tree, mostly affecting the load times of large modules.

Since Windows Vista, non-Administrator users on Windows aren't allowed to create symlinks anymore, so this new loading method fails for users working in corporate Windows environments.

Catch the error and fall back to the slower copying method if that happens.

Fixes #4208.



---

By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license].

[Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
rix0rrr added a commit that referenced this pull request Aug 9, 2023
The package cache mechanism that was turned on by default in #4181
works in theory under parallelism, but not in practice.

Typically the CDK CLI will prevent CDK apps from running in parallel,
but Python testing frameworks like `tox` use subprocess parallelism
to speed up test runs, leading to the jsii imports being executed
at the same time.

Since jsii is sync, the locking needs to be sync. The sync locking
feature of the `lockfile` library doesn't have wait support (for good
reason), and so when a lock is already acquired by another process
it quickly burns through its 12 retries in a hot loop, and then exits
with an error.

Two changes to address this:

- (Ab)use `Atomics.wait()` to get a synchronous sleeping primitive;
  since `lockSync` doesn't support synchronous sleep, we build our
  own retry loop with synchronous sleep around `lockSync`.
- Since the extracted directory is immutable: if the marker file in the
  extracted directory exists, we can treat it as evidence that the
  directory has been completely written and we can skip trying to vy
  for exclusive access to write it. This avoids all lock contention
  after the very first CDK app execution.

Fixes #4207.
mergify bot pushed a commit that referenced this pull request Aug 10, 2023
The package cache mechanism that was turned on by default in #4181 works in theory under parallelism, but not in practice.

Typically the CDK CLI will prevent CDK apps from running in parallel, but Python testing frameworks like `tox` use subprocess parallelism to speed up test runs, leading to the jsii imports being executed at the same time.

Since jsii is sync, the locking needs to be sync. The sync locking feature of the `lockfile` library doesn't have wait support (for good reason), and so when a lock is already acquired by another process it quickly burns through its 12 retries in a hot loop, and then exits with an error.

Two changes to address this:

- (Ab)use `Atomics.wait()` to get a synchronous sleeping primitive; since `lockSync` doesn't support synchronous sleep, we build our own retry loop with synchronous sleep around `lockSync`.
- Since the extracted directory is immutable: if the marker file in the extracted directory exists, we can treat it as evidence that the directory has been completely written and we can skip trying to vy for exclusive access to write it. This avoids all lock contention after the very first CDK app execution.

Fixes #4207.

---

By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license].

[Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants