Introduction
In the article AWS SnapStart - Using insights from AWS Lambda Profiler Extension for Java to reduce Lambda cold starts , we introduced the extended priming technique to (fully) prime APIGatewayProxyRequestEvent SnapStart.
I wanted to figure out whether we'll improve Lambda performance (especially reduce Lambda cold start times) by applying this technique (I'll call it extended API Gateway request event priming) to the API Gateway request event priming introduced in the article Quarkus 3 application on AWS Lambda- Reducing Lambda cold starts with SnapStart and API Gateway request event priming.
Sample application with the AWS Lambda SnapStart using extended API Gateway request event priming
The main difference compared to the version of the Lambda SnapStart priming is from the article Quarkus 3 application on AWS Lambda- Reducing Lambda cold starts with SnapStart and API Gateway request event priming is in the beforeCheckpoint method of the AmazonAPIGatewayPrimingResource class.
@Override
public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception {
APIGatewayProxyRequestEvent requestEvent =
LambdaEventSerializers.serializerFor(APIGatewayProxyRequestEvent.class,
AmazonAPIGatewayPrimingResource.class.getClassLoader())
.fromJson(this.getAwsProxyRequestAsJson());
new QuarkusStreamHandler().handleRequest
(new ByteArrayInputStream(this.convertAwsProxyRequestToJsonBytes(requestEvent)),
new ByteArrayOutputStream(), new MockLambdaContext());
}
As explained in the article AWS SnapStart - Using insights from AWS Lambda Profiler Extension for Java to reduce Lambda cold starts , we additionally prime the following invocation:
APIGatewayProxyRequestEvent requestEvent = LambdaEventSerializers.
serializerFor(APIGatewayProxyRequestEvent.class, AmazonAPIGatewayPrimingResource.class.getClassLoader()).
fromJson(this.getAwsProxyRequestAsJson());
This requires adding additional dependency to the pom.xml
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-serialization</artifactId>
<version>1.1.5</version>
</dependency>
Measurements of cold and warm start times of our application with Lambda SnapStart and extended API Gateway request event priming
The measurements approach (including considering the tiered low-latency snapshot cache) is exactly the same as described in the article Quarkus 3 application on AWS Lambda- Reducing Lambda cold starts with SnapStart and API Gateway request event priming. I'll provide those results and the extended API Gateway request event priming directly below for the comparison.
During the measurements, I discovered that aws-lambda-java-serialization dependency is already provided by the AWS Lambda Java Runtime Interface Client, so we can set its scope to provided like this :
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-serialization</artifactId>
<version>1.1.5</version>
<scope>provided</scope>
</dependency>
With this, we'll reduce the deployment artifact size by 4.5 MBs (which should hopefully reduce the Lambda cold start times). In the measurements below for the "extended API Gateway request event priming applied" I provided the results without setting the scope to provided and with it (see explicit "with provided serialization dependency" in the scenario description).
Cold (c) and warm (w) start time with tiered compilation in ms:
Scenario Description | c p50 | c p75 | c p90 | c p99 | c p99.9 | c max | w p50 | w p75 | w p90 | w p99 | w p99.9 | w max |
---|---|---|---|---|---|---|---|---|---|---|---|---|
SnapStart enabled and API Gateway request event priming applied, all | 604 | 648 | 975 | 1181 | 1197 | 1198 | 5.25 | 6.25 | 7.33 | 15.62 | 41.64 | 338 |
SnapStart enabled and API Gateway request event priming applied, last 70 | 588 | 599 | 650 | 790 | 790 | 790 | 5.46 | 6.10 | 7.16 | 14.90 | 39.38 | 241 |
SnapStart enabled and extended API Gateway request event priming applied, all | 594 | 646 | 925 | 1137 | 1192 | 1193 | 5.46 | 6.10 | 7.10 | 15.38 | 39.70 | 396 |
SnapStart enabled and extended API Gateway request event priming applied, last 70 | 584 | 610 | 658 | 751 | 751 | 751 | 5.46 | 6.10 | 7.10 | 15.50 | 39.70 | 225 |
SnapStart enabled and extended API Gateway request event priming applied, with provided serialization dependency, all | 576 | 626 | 896 | 987 | 1025 | 1025 | 5.50 | 6.10 | 7.16 | 15.50 | 34.39 | 356 |
SnapStart enabled and extended API Gateway request event priming applied, with provided serialization dependency, last 70 | 558 | 598 | 646 | 750 | 750 | 750 | 5.46 | 6.05 | 7.10 | 15.75 | 32.79 | 260 |
Cold (c) and warm (w) start time with -XX:+TieredCompilation -XX:TieredStopAtLevel=1 compilation in ms:
Scenario Description | c p50 | c p75 | c p90 | c p99 | c p99.9 | c max | w p50 | w p75 | w p90 | w p99 | w p99.9 | w max |
---|---|---|---|---|---|---|---|---|---|---|---|---|
SnapStart enabled and API Gateway request event priming applied, all | 616 | 656 | 697 | 941 | 960 | 961 | 5.55 | 6.21 | 7.39 | 16.08 | 41.40 | 486 |
SnapStart enabled and API Gateway request event priming applied, last 70 | 595 | 619 | 653 | 765 | 765 | 765 | 5.47 | 6.21 | 7.27 | 16.08 | 39.94 | 486 |
SnapStart enabled and extended API Gateway request event priming applied, all | 565 | 592 | 656 | 1050 | 1222 | 1223 | 5.42 | 6.01 | 7.04 | 15.38 | 61.04 | 355 |
SnapStart enabled and extended API Gateway request event priming applied, last 70 | 562 | 586 | 615 | 734 | 734 | 734 | 5.37 | 5.96 | 6.99 | 15.02 | 48.84 | 229 |
SnapStart enabled and extended API Gateway request event priming applied, with provided serialization dependency, all | 565 | 615 | 646 | 1001 | 1042 | 1042 | 5.38 | 6.01 | 7.16 | 15.58 | 39.12 | 330 |
SnapStart enabled and extended API Gateway request event priming applied, with provided serialization dependency, last 70 | 544 | 572 | 642 | 729 | 729 | 729 | 5.38 | 6.01 | 7.16 | 15.58 | 39.12 | 190 |
Conclusion
In this article, we demonstrated that by applying Lambda SnapStart extended API Gateway request event priming (with the additional priming of the LambdaEventSerializers.serializerFor(...) invocation), we've got a slightly lower Lambda cold start times especially with provided aws-lambda-java-serialization dependency compared to the standard API Gateway request event priming.
The warm start times vary slightly depending on the percentile and the measurement method but are close to each other, as maximal values sometimes depend on luck, for example whether garbage collection was running or not.
Generally I would recommend using the SnapStart enabled and extended API Gateway request event priming with aws-lambda-java-serialization dependency to be set to the scope "provided". It requires a bit of additional code to be written but it's worth the Lambda performance gain.
Top comments (0)