DEV Community

Vadym Kazulkin for AWS Heroes

Posted on

Quarkus 3 application on AWS Lambda- Part 6 Optimization strategies for the cold and warm starts

Introduction

In the previous articles of the series about how to develop, run and optimize Quarkus 3 application on AWS Lambda with :

  • Managed Java 21 runtime
  • GraalVM Native Image deployed as Lambda Custom Runtime

We also did Lambda performance (cold and warm starts) measurements with the following settings:

  • Lambda functions used 1024 MB memory
  • Java compilation option "-XX:+TieredCompilation -XX:TieredStopAtLevel=1"
  • Lambda x86_64 architecture used
  • Default Apache HTTP Client used to connect to the DynamoDB

In this part of the series we'll introduce some Lambda additional performance (cold and warm starts) optimization techniques that you can apply for your Quarkus 3 application on AWS Lambda. You'll need to measure the performance by yourself to figure out whether they will provide desired Lambda performance improvements.

Please keep in mind that you can also deploy your Quarkus application on AWS Lambda als using (Docker) Container Image. I didn't cover this approach, but you can look into my article series Lambda function using Docker Container Image for a step by step introduction on how to do it. The cold start will be quite big and can't be optimized (reduced) as Lambda SnapStart isn't available for the Lambda deployment as Container Image.

Optimization strategies for the cold and warm starts

To find a good balance between cold and warm start time you can try out the optimization techniques introduced below. I have not done any additional measurements with the Qurakus 3 application on AWS Lambda, but have done them using pure Java on AWS Lambda without the usage of any frameworks on top. I'll provide references to my relevant articles.

The following approaches can be applied to all approaches: managed Java runtime on Lambda including enabling SnapStart (and priming techniques on top) and GraalVM Native Image deployed as Lambda Custom Runtime:

The following approaches can be applied primary only to the managed Java runtime on Lambda including enabling SnapStart (and priming techniques on top) :

  • Try out different Java compilation options for the Lambda function. All measurements until now have been performed with the compilation option "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" and default tiered compilation for the Lambda function. There are other compilation options that can be provided to the Lambda function using environment variable called JAVA_TOOL_OPTIONS which can have different cold and warm starts trade offs. See my article Measuring cold and warm starts with Java 21 using different compilation options for further examples, performance measurements and conclusions. In case of GraalVM Native Image Java compilation method (and optimizations during runtime) doesn't have much impact on the Lambda performance (well, because it's already compiled as a native image).
  • Further exclude unused dependencies. With that especially cold start times can be reduced (also for SnapStart), see my article Measuring cold starts with Java 21 using different deployment artifact sizes. In case of GraalVM Native Image only reachable Java classes, function and methods will become a part of the Native Image, so including unused dependencies may not hear that much.

The following approach can be applied can be applied primary to the managed Java runtime on Lambda with enabled SnapStart:

The following approach can only be applied primary to the GraalVM Native Image :

  • Try out Profile-Guided Optimizations to see whether you can further improve Lambda performance. The difficulty of trying out this technique is that you'll need to do some additional semi-automated steps to run your application either with the Lambda emulator locally or on the extra environment to obtain the profile of your application which you'll then need to generate the optimized Native Image. You can use Lambda extension for it, but it still requires a lot of additional work. The same work is done by AWS for us in case Lambda SnapStart is activated and I really appreciate that I don't need to care about generating, encrypting, storing and restoring the snapshots/profiles.

Conclusion

In this part of the series, we introduced some additional Lambda performance (cold and warm start times) optimization strategies to be used for the Quarkus 3 application on AWS Lambda. Try them out on your own to figure out whether they will provide desired Lambda performance improvements.

Top comments (0)