-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
[aws-lambda-nodejs] Bundling performance issues #10286
Comments
@jaapvanblaaderen currently investigating this... looks indeed like there's an issue with the cache. |
@jogold Ok cool, just let me know if I can help testing something if needed. |
So... it's complicated and has to do with the content of |
Bundling in a random temporary directory each time invalidates Parcel's cache. Use the `cacheKey` instead of random characters. Addresses aws#10286 (not sure if closes it yet)
@jaapvanblaaderen we'll see how #10763 improves the cache performance. Let me know your experience when it's merged and released. |
Thanks @jogold, I'll let you know. |
Bundling in a random temporary directory each time invalidates Parcel's cache. Use the `cacheKey` instead of random characters for the temp directory. Addresses #10286 (not sure if it closes it yet) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@jogold I've done some testing with the latest 1.68 release, which should include the changes in #10763 if I'm correct. I've tested with the exact same test app as mentioned in the issue description and took the average of four test runs (running Results with parcel 2.0.0-beta.1
Not very promising results as it apparently got 10 seconds slower. I tested a few other versions as well, 1.62-1.66 are similar in performance and from 1.67 and upwards it's around 10 seconds slower. Now the interesting part... I noticed that there are quite some security vulnerabilities with the currently supported version of Parcel, not really a big issue, but decided to upgrade it using Results with parcel 2.0.0-nightly.425
That 5.4 seconds looks promising 🙂 . I hope this info helps to improve the situation? I guess you can compare CDK 1.66 and 1.67 to see why the performance (from CDK perspective) got worse? Then there is Parcel, I find it a bit weird that the latest 2.x release is quite old especially as they are still in beta and apparently making quite good (performance) improvements. Also note that there is already a (dependabot PR) for updating parcel in CDK: #10953 |
You can solve the slow tests problem by mocking out Parcel bundling with this module - https://www.npmjs.com/package/cdk-lambda-nodejs-mock |
@alan-cooney This indeed works great for running tests, thanks! 👍 Is there also an open GitHub repo linked to this module? |
Hey @jaapvanblaaderen . I have implemented a new cdk construct aws-lambda-nodejs-esbuild See comparison results on my machine:
vs
I forked your sample, so you can see how to migrate Just saying. |
Very interesting!! |
@floydspace This is great work! I will definitely have a look at this. |
The benchmarks look really promising regarding the https://github.com/floydspace/aws-lambda-nodejs-esbuild package. As a regular user of AWS CDK + NodejsFunction constructs, I vote strongly on switching to the A side note: we've had good results with using Webpack back in the days before the NodejsFunction construct existed. Are there any plans for evaluating that one as a possible technology to back the construct? |
@eladb what's your opinion here? I've made some tests with If we go in this direction would you agree to include @floydspace would you be ready to contribute for this? |
Hey @jogold , sure would love to.
Thank you. |
Let's wait for @eladb's feedback
For modules using native dependencies you could want to install in a Lambda compatible environment. This could be an option of course.
We started to use |
Sounds promising but I would still be reluctant to bundle it with the CDK. Going towards 2.0 the CDK will be a single module, which means our bar for bundling deps is going to be very high. Can we still employ the same docker fallback approach here? What are the downsides? |
Seems like a reasonable approach. To let the developers opt for Docker based or
Based on these facts, I consider the "meaningful default" to be an option that is FASTER in 99% of the use cases and requires fewer system dependencies (Docker). This option currently is either Parcel or Long story short, it's about finding the right balance of keeping package dependencies low, and at the same time - keeping the development experience of consumers of the NodejsFunction construct satisfactory. Just curious: If the NodejsFunction construct declares Parcel or |
Yes but one of the problems we have with Docker here is that we need to mount the project root (in order to have access to the top level Implementing a local only solution would result in much cleaner code also. We could maybe go back to having an "undeclared peer dependency". Note: local bundling could still use Docker (as an option) when installing unbundled dependencies that should be built in a Lambda compatible environment. |
Why exactly do we need access to the top-level node_modules? I normally have my own package.json in the lambda subfolder and I think bundling should work in this folder without the CDK project, shouldn't it? |
That's a "classical" setup yes, but not a necessary one. In our organization, instead, we create Lambdas alongside/next-to the CDK constructs. So there's a single package.json and it's at the root of the CDK app. This makes it easy to centralize third party version upgrades of dozens of Lambdas. |
How do you easily |
I see that with bundling this might indeed not be necessary. Sometimes I zip the folder as Lambda asset and then I need it contained in a subfolder. Installing is done using the normal How do I specify Lambda-specific deps in one subproject and not in another? I am open to any best-practices and happy to improve my setup. |
Currently it's on my company's monorepo, but I can split it out if useful? It essentially just replaces all NodejsFunction classes with the standard Function from @aws-cdk/aws-lambda, and sets the code as |
Got it, in this case you have no other solution (but you're creating a zip that contains much more than what's needed by your function). That's exactly the problem we're trying to solve with the
This means that you're sometimes downloading and installing the same package multiple times. It's also complicated when you want to update packages. |
I see your arguments. Performance is one issue, packaging additional files is sometimes an issue, and different dependency versions are sometimes a wanted thing. But I would love to get rid of all this. |
@floydspace we are going to replace Let me first draft a PR for this then we can work on it together. |
Replace Parcel with esbuild for bundling. esbuild offers [impressive performances](https://esbuild.github.io/) compared to Parcel. Moreover everything can be configured via the CLI. This means that we don't need to play with the user `package.json` file anymore. Add full Windows support for local bundling. Refactor and clean-up. Closes #10286 Closes #9130 Closes #9312 Resolves #11222 BREAKING CHANGE: local bundling now requires `esbuild` to be installed. * **lambda-nodejs**: `projectRoot` has been replaced by `depsLockFilePath`. It should point to your dependency lock file (`package-lock.json` or `yarn.lock`) * **lambda-nodejs**: `parcelEnvironment` has been renamed to `bundlingEnvironment` * **lambda-nodejs**: `sourceMaps` has been renamed to `sourceMap`
|
❓ General Issue
The Question
In my stack I've created several lamdas using the new NodejsFunction from
@aws-cdk/aws-lambda-nodejs
. Functionally everything works fine, code in bundled with Parcel and the stack deploys without issues. There are however two (Parcel related?) performance issues:I'm wondering if this is the expected performance or if I'm missing something? I did some tests with webpack to manually bundle the Lambdas, this is about 3 times faster than webpack. I'm also wondering about the caching feature in Parcel, shouldn't the second performance issue be tackled it?
How to reproduce
I've created a simple sample app to show the issue: https://github.com/jaapvanblaaderen/cdk-lambda-bundling-performance
The app contains a single stack with one lambda that's referenced in two tests. In the test output you can observe that bundling an empty lambda function takes about 8 seconds (initially slow) and for the second test it's still around 6-7 seconds (no/bad caching?).
Environment
The text was updated successfully, but these errors were encountered: