AWS SnapStart - Part 11 Measuring cold starts with Java 21 using different deployment artifact sizes
Tags: aws, java, serverless, coldstart
Published: 2023-12-18 16:33:58

## Introduction
In the [part 9](https://dev.to/aws-builders/measuring-lambda-cold-starts-with-aws-snapstart-part-9-measuring-with-java-21-5e52) of our series we measured the cold starts of the Lambda function with Corretto Java 21 runtime without SnapStart enabled, with SnapStart enabled and also applied DynamoDB invocation priming optimization. Lambda functions had 1024MB memory and the deployment artifact size (jar file) is approx. 15MB. In this article we will make the same measurements but play around with different deployment artifact sizes to figure out whether it will make any difference.

## Measuring cold starts with Java 21 with and without SnapStart enabled using deployment artifact sizes

Lets's consider 3 scenarios: 

1. [Small HelloWorld-style application](https://github.com/Vadym79/AWSLambdaJavaSnapStart/tree/main/pure-lambda-21-small) which consists of Lambda receiving the API Gateway request with product id and basically prints this id out. There is no persistence layer involved. The application is that simple, that there is no priming technique to be applied. There are only several dependencies declared in [pom.xml](https://github.com/Vadym79/AWSLambdaJavaSnapStart/blob/main/pure-lambda-21-small/pom.xml) like aws-lambda-java-core and slf4j-simple. The deployment artifact size of such an application is 137 KB only. 
2. [Medium Size application with DynamoDB persistence](https://github.com/Vadym79/AWSLambdaJavaSnapStart/tree/main/pure-lambda-21). We'll re-use the application introduced in [part 9](https://dev.to/aws-builders/measuring-lambda-cold-starts-with-aws-snapstart-part-9-measuring-with-java-21-5e52) for this. There are basically 2 Lambda functions which both respond to the API Gateway requests and retrieve product by id received from the API Gateway from DynamoDB. One Lambda function can be used with and without SnapStart and the second one uses SnapStart and DynamoDB request invocation priming. There are bunch of dependencies declared in [pom.xml](https://github.com/Vadym79/AWSLambdaJavaSnapStart/blob/main/pure-lambda-21/pom.xml) like aws-lambda-java-core, aws-lambda-java-events, slf4j-simple, crac, dynamodb and url-connection-client. The deployment artifact size of such application is 15 MB.
3. [Big Size application with DynamoDB persistence and dependencies to many other AWS services] (https://github.com/Vadym79/AWSLambdaJavaSnapStart/tree/main/pure-lambda-21-big). It's similira to medium size application. There are basically 2 Lambda functions which both respond to the APIGateway requests and retrieve product by id received from the ApiGateway from DynamoDB. One Lambda function can be used with and without SnapStart and the second one uses SnapStart and DynamoDB request invocation priming. There are bunch of dependencies declared in [pom.xml](https://github.com/Vadym79/AWSLambdaJavaSnapStart/blob/main/pure-lambda-21-big/pom.xml) like aws-lambda-java-core, aws-lambda-java-events, slf4j-simple, crac, dynamodb and url-connection-client. But we also declare man other dependencies to various differnt AWS service like sns, kinesis, eventbridge, bedrock, but we won't even use them in our application. Deployment artifact size (jar file) is 50 MB for this use case.

The results of the experiment below were based on reproducing approximately 100 cold starts, which were generated during the experiment which ran for approximately 1 hour. All Lambda functions had 1024 MB memory setting.

Legend: **SMALL** - corresponds to 137 KB deployment artifact size, **MEDIUM** to 15 MB and **BIG** to 50 MB.

| Experiment description                     | p50      | p90       |p99       |
|---------------------------  |----------|-----------|----------|
|SMALL: cold start time w/o SnapStart                | 547.77  | 595.15   | 618.88  |
|SMALL: cold start time with SnapStart w/o Priming  | 483.92  | 663.65   | 774.08  |
|SMALL: cold start time with SnapStart with Priming | 483,92   | 663.65   | 774.08  |
|MEDIUM: cold start time w/o SnapStart                | 3155.88  | 3292.80   | 3605.95  |
|MEDIUM: cold start time with SnapStart w/o Priming  | 1591.31  | 1823.14   | 2021.67  |
|MEDIUM: cold start time with SnapStart with Priming | 760.79   | 955.76    | 1200.12  |
|BIG: cold start time w/o SnapStart                | 3165.20  | 3317.44   | 3666.15  |
|BIG: cold start time with SnapStart w/o Priming  | 1608.89  | 2095.23   | 2509.05  |
|BIG: cold start time with SnapStart with Priming | 763.18   | 1373.74    | 1623.76  |

For the small deployment artifact size cold start time with SnapStart enabled and with and without Priming are the same because there is nothing to prime is this simple case.

Let's put the figures on the graphs for each percentile to be able to compare the effect of the deployment artifact sizes better.

For p50:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/660y5ilx8280kvl9mxy7.png)

For p90:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38jizhvgjmlmufkaiy5g.png)


For p99: 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbp9tmyl0vyi5wts1oje.png)

## Conclusions

There are some interesting insights coming from those measurements aso concerning the usage of SnapStart itself: for the small deployment size there is no real benefit of using SnapStart as cold start times with and without it are quite comparable. But applications and Lambda functions without any real dependencies incuding those to other AWS services are quite exceptional. 

There is also quite noticable cold start difference for p90 and p99 comparing medium and big deployment artifact sizes whereas p50 remained similar. And of course cold starts for medium and big deployment sizes are much bigger than with the small one. So also for Java 21 the deployment size still plays a crucial role for the cold start without usage of the SnapStart but also with! Try to make your Lambda functions small and single-purposed!

In one of the next articles we'll do the same measurements but for Java 17 runtime, as Java 21 is quite new and I expect the majority to use Java 17. Stay tuned!