-
-
Notifications
You must be signed in to change notification settings - Fork 459
S3 import in default-handler likely causing higher cold start time #580
Comments
Sounds good - also this is the first I've heard of the |
I like the idea of lazy requiring stuff that is only needed in certain code paths, sort of what Next.js does here with jsonwebtoken. |
@thchia yep, the project link is here, it's written by AWS: https://github.com/aws/aws-sdk-js-v3. A little bit confusing since in npm, they don't publish it as v3 (s3-client-node itself is 0.1.0-preview), but I believe all the clients under @aws-sdk/client-* are for this new version. |
Basically, it's more modularized so you can write code like this: const { DynamoDBClient, ListTablesCommand } = require("@aws-sdk/client-dynamodb");
(async () => {
const client = new DynamoDBClient({ region: "us-west-2" });
const command = new ListTablesCommand({});
try {
const results = await client.send(command);
console.log(results.TableNames.join("\n"));
} catch (err) {
console.error(err);
}
})(); and that will only require the code needed for PS: just noticed in my trial, I was using the new import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3-node"; |
Finished doing some more tests. Added // Lazily import only S3Client to reduce init times until actually needed
console.log("Before S3Client import: " + performance.now());
const { S3Client } = await import("@aws-sdk/client-s3/S3Client");
console.log("Before S3Client construction: " + performance.now());
const s3 = new S3Client({ region: "us-west-1" });
console.log("Before GetObjectCommand import: " + performance.now());
const { GetObjectCommand } = await import(
"@aws-sdk/client-s3/commands/GetObjectCommand"
);
console.log("Before PutObjectCommand import: " + performance.now());
const { PutObjectCommand } = await import(
"@aws-sdk/client-s3/commands/PutObjectCommand"
);
console.log("After s3: " + performance.now());
It's even faster than I imagined! It takes less than 3 ms to import all 3 classes on a cold start. So in most cases, we should be able to save the entire ~100 ms of importing S3, and when needed for With this, size of default-handler is about 500 kB. We could minify further using rollup-terser plugin, but it shouldn't affect too much. @danielcondemarin any thoughts of using this aws-sdk-js-v3 (https://github.com/aws/aws-sdk-js-v3)? It is in gamma and although not final release, it is actively published and looks stable enough. If you are fine, I can work on the PR to update to to using this. Now if only we can reduce that page |
Go for it! I think we should pin the version of the aws-sdk-js-v3 whilst is on gamma though. |
Thanks! Will try to work on it tonight. |
I created the PR, handler size did increase from ~150 kB to 500 kB since I bundled the new @thchia if you have a test repo with |
@dphang I can push one up in a few hours. |
No worries, thanks a bunch! |
@thchia thanks! I'll test it out with these changes. |
Describe the bug
Not really a bug, more a slight optimization we can do. So I saw the S3 import was added for
getStaticPaths
support:serverless-next.js/packages/libs/lambda-at-edge/src/default-handler.ts
Line 21 in a854139
Based on some quick perf tests, this
require
seems to be adding up to 80-100 ms to init times on cold start (1024 MB function, Node 12.x). Total init time is ~250 ms for my app.I think s3 is not needed all the time, just if
getStaticPaths
is being used, so maybe this should berequired
just before where it's actually needed, i.e: https://github.com/serverless-nextjs/serverless-next.js/blame/a854139f4344530de1a42268828231a4d38c7c91/packages/libs/lambda-at-edge/src/default-handler.ts#L319 instead?To Reproduce
Steps to reproduce the behavior:
default-handler
before and after the require of S3. Then build and deploy with the new handler.Expected behavior
Maybe lazily
require
this module for better overall performance.Additional context
Also, maybe consider using the
aws-sdk-js-v3
(https://github.com/aws/aws-sdk-js-v3), as it is more modularized and lightweight? Although it is in gamma release now, so maybe we can wait for a more stable release.I also did do some initial tests by bundling this new version:
@aws-sdk/client-s3-node
(via Rollup.js) and it seems to berequired
somewhat faster (by around 20-30 ms) than the built-inaws-sdk
one, which I thought would have been fairly optimized already...Related article about
aws-sdk
require
times: https://theburningmonk.com/2019/03/just-how-expensive-is-the-full-aws-sdk/The text was updated successfully, but these errors were encountered: