-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[codegen/node] Implement support for lazy-loaded Node modules #10538
Conversation
Please view the results of the Downstream Codegen Tests Here |
@@ -5,10 +5,12 @@ import * as pulumi from "@pulumi/pulumi"; | |||
import * as utilities from "../utilities"; | |||
|
|||
// Export members: | |||
export * from "./sqlResourceSqlContainer"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is a typical change example. Instead of reexporting *
which generates require()
at runtime we reexport equivalent definitions below.
|
||
// Import resources to register: | ||
import { SqlResourceSqlContainer } from "./sqlResourceSqlContainer"; | ||
export { SqlResourceSqlContainerArgs } from "./sqlResourceSqlContainer"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- re-export all interfaces, type-only, no require()
// Import resources to register: | ||
import { SqlResourceSqlContainer } from "./sqlResourceSqlContainer"; | ||
export { SqlResourceSqlContainerArgs } from "./sqlResourceSqlContainer"; | ||
export type SqlResourceSqlContainer = import("./sqlResourceSqlContainer").SqlResourceSqlContainer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- re-export the type of the resource class; this is needed if it's used for declaring types and type-checking
import { SqlResourceSqlContainer } from "./sqlResourceSqlContainer"; | ||
export { SqlResourceSqlContainerArgs } from "./sqlResourceSqlContainer"; | ||
export type SqlResourceSqlContainer = import("./sqlResourceSqlContainer").SqlResourceSqlContainer; | ||
export const SqlResourceSqlContainer: typeof import("./sqlResourceSqlContainer").SqlResourceSqlContainer = null as any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- mock-reexport the value of the resource class, this is needed to type-check expressions such as new SqlResourceSqlContainer(); still this generates no require()
export { SqlResourceSqlContainerArgs } from "./sqlResourceSqlContainer"; | ||
export type SqlResourceSqlContainer = import("./sqlResourceSqlContainer").SqlResourceSqlContainer; | ||
export const SqlResourceSqlContainer: typeof import("./sqlResourceSqlContainer").SqlResourceSqlContainer = null as any | ||
utilities.lazy_load_property(exports, "./sqlResourceSqlContainer", "SqlResourceSqlContainer"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- patch up the export at runtime (no impact on types) to call require lazily
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
I've found and fixed some issues by trying it on pulumi-azure-native (not caught by codegen tests? need to look into this). This helps a bit! Test: After
Before
|
Tracing which modules get loaded, it's the function modules mostly. This is very promising. IF we lazy-load them also we get a real win here.
|
I'm starting to think this approach has an advantage over lazy top-level submodules only - this optimizes imports of |
pkg/codegen/testing/test/testdata/azure-native-nested-types/nodejs/utilities.ts
Outdated
Show resolved
Hide resolved
pkg/codegen/testing/test/testdata/dash-named-schema/nodejs/utilities.ts
Outdated
Show resolved
Hide resolved
pkg/codegen/testing/test/testdata/dashed-import-schema/nodejs/index.ts
Outdated
Show resolved
Hide resolved
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
Reminder to self: this PR still needs to address the fate of resource registrations. AFAIK these must be eagerly registered when importing any of the modules as before. The lazy loading may defer the registrations too late. |
The lazy-load of functions had impact! Now on azure-native:
|
Remaining modules automatically loaded by require("@pulumi/azure-native"):
|
Now measure the example rewritten for recommended imports "azure-native/storage" and "azure-native/resources".
It's a wash because it manages to load all enums from all modules, which dominates. This needs addressing somehow to be a real benefit to users. Tinkering further. |
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
Ok good, with the latest tweak to avoid importing types/index.js that gets us all enum modules imported, we reclaim the last milliseconds. Code:
After:
Before:
Code:
After:
Before:
This is clearly better and we only import 50 modules from azure-native now when using recommended imports (mostly the index.js ones), out of 650 total modules imported. And when not using recommended imports it's not ideal but still a lot better. I think this is good enough. |
Ah nevermind! We are lucky here. The calls to registerResourceModule are all sitting in index.ts modules files which are not affected by this change. So they will happen exactly as before. As to enum files, they never call registerResourceModule. So this concern is irrelevant for the PR. |
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
836cda5
to
d57a597
Compare
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
Please view the results of the Downstream Codegen Tests Here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Well done! :D
let m = cache.module || (cache.module = loadModule()); | ||
return m[property]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this change is any better than the original syntax (though it doesn't hurt either). NodeJS caches calls to require()
, so "reloading" the module is free.
Please view the results of the Downstream Codegen Tests Here |
Downstream checks actually passed here: #10576 after a fixup to the GHA definition. |
Description
This PR implements opt-in support for generating lazy load code for Node modules. The changes should be entirely non-breaking for consumers of the providers.
#7653 for more history and motivation
In addition to PR checks, this has been tested manually on azure-native. It compiles and delivers speedups in node startup time: from 7.6s to 1.6s when importing "@pulumi/azure-native" and from 800ms to 450ms when importing "@pulumi/azure-native/resources" and "@pulumi/azure-native/storage".
How this works:
import type ..
form when importing enums ("useTypeOnlyReferences" opt-in flag in schema)pulumi.runtime.registerResourceModule
side-effects are not affected and happen as before.Our prior approach on 7653 went for lazily importing module-re-exports; this would still be preferable but we run into some corner cases where we can't seem to properly make TypeScript re-export the module as a "namespace", leading to a class of programs that can break. This is explored in some detail in pulumi/pulumi-azure-native#1944
Further work: we should be able to do a lot better here with subsequent work by making sure we emit more precise imports, this will optimize not only node time but also TS compilation time - this is tracked in #10442 - but recommend adopting this for now.
Fixes #7653
Checklist