国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home Java javaTutorial Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

Jan 07, 2025 am 06:16 AM

Introduction

A fairly common approach when it comes to working with serverless code is to write it as a Python, Node or Go application given their reputation for very fast cold starts.

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

But what if we are faced with pre-existing Java apps targeting serverless environments such as AWS Lambda? Perhaps a good majority of our code base hosts Java and we have developed a rich ecosystem of tools and libraries that we would like to reuse. Re-writing the entire fleet of such applications into a different language is expensive, not to mention, we are giving up features such as static type safety and compile time optimizations.

A while back, I was faced with this exact scenario: 9 AWS Lambda apps written in Java that would be very slow on cold starts to the point where some of them would occasionally time out.

The Lambdas in question were placed behind API Gateway and used for admin tasks by calling the corresponding REST APIs. This functionality was not very heavily used and so running into cold starts was inevitable; however, because this was not a critical service it was a perfect opportunity for experimentation: to figure out if these Lambdas could be salvaged.

It wasn’t long before I ran into several other blog posts about developers successfully using GraalVM and frameworks such as Quarkus to address this very problem. And so I’ve decided to try it out for myself.

But what are these tools anyways?

GraalVM

In short, GraalVM is a Java Virtual Machine that comes with a toolset capable of compiling Java to a Native Image and executing it using the Graal JVM.

Normally Java utilizes the “Just In Time” (JIT) compiler, which as the name suggests, performs optimizations and compilation during the execution of our code. The long-running applications benefit from this given the JVM optimizers constantly monitor program’s execution and perform fine-tuning that over-time translates into better performance.

This is great if an application is instantiated once, and is expected to run for several hours or more, but not so great if we are dealing with Kubernetes, AWS Lambdas and batch jobs that hope to boot up Java apps quickly, perform time-sensitive operations and scale depending on the demand - speaking of turbo lag for the car enthusiasts out there.

And this is where GraalVM’s Native Image capability steps-in to help. Instead of using JIT compiler, it opts in for a very different approach of compiling our code ahead of time (AOT). It pre-bakes our pie using static code analysis and even pre-initializes certain classes during build time so that they are ready to fire any time our application code is executed.

The result? Very fast cold starts, which make Native Images very capable in serverless domains where apps are short-lived and have to boot up quickly.

One thing to note is that even though GraalVM is capable of AOT, it can also serve as a drop-in replacement for the existing JVM offering better performance given GraalVM’s new JIT compiler written in Java.

But wait, there is more! Because Native Image includes only the code that is on the known execution path we trim the fat and all of the Java classes that have not been explicitly declared to keep will not be available. Because we only keep the bits that are expected to execute, we increase our application’s security.

Take for example the infamous Log4J vulnerability that was using Remote Code Execution as the means of compromising the host. With Native Images, gadget chaining is very unlikely to be successful because the pieces of library code required to convey the attack aren’t even reachable.

Quarkus

Quarkus on the other hand, is a Java framework optimized for serverless applications which comes with a toolbox that makes building Native Images easier by offering an extension for specifically configuring and building AWS Lambdas as native executables.

C1 Compiler

During my Lambda optimization journey, I have also run into alternative optimization techniques. One of such optimizations was the proposed exclusive usage of a C1 compiler during Lambda’s execution which has promised to deliver faster cold starts. Normally, Java applications that run inside a JVM use a tiered compilation which consists of a faster, but less optimal C1, followed by C2 which is slower, but offers more optimal performance for Java apps that execute for a long time. Given that Lambdas are short-lived, the benefits of C2 compilation are negligible.

A guide walking through the process of configuring C1 compilation for AWS Lambdas is available here.

Of course I wanted to know how much of an improvement this technique can offer in comparison to my GraalVM master plan in place, and so I have also included it in my findings below.

Further details about JVM’s tiered compilation as well as GraalVM’s brand new JIT compiler can be found in this Baeldung article.

“But wait, what about AWS SnapStart?”

Ironically enough, a few months after I shipped my changes to production, AWS came up with their latest SnapStart capability, which takes a snapshot of a running Lambda and instead of re-initializing it all over again, it uses snapshot images as a restore point promising faster cold starts. I had to give it a try to find out if the use of GraalVM was a wasted effort and also included it in my findings.

It’s worth noting that in order to get the most out of SnapStart, code refactor would have been required in order to utilize the beforeCheckpoint and afterRestore hooks (more details here). Given I wanted to avoid any major code changes if possible, I’ve used this feature “as is”, without implementing these methods and rearranging any code.

The Master Plan

Now back to GraalVM! To my surprise, after incorporating this solution, there were absolutely no Java code changes required aside from adding and adjusting build configuration files and some required metadata.

Sounds too good to be true?

Maybe a little. Given that we are using AOT compilation, in the world of Java, this poses a certain challenge if it comes to the use of language features such as Reflections, Proxies, Interfaces, and Service registries which a lot of libraries rely on. This is why the GraalVM compiler requires extra configuration metadata to be declared that explicitly registers certain classes and services so that they can be included in the final artifact. GraalVM provides a so-called agent which can be used to run alongside your executable to automatically identify the required configuration which can make this process easier.

Quarkus provides several extensions for well-known libraries to make them “native-image friendly”, but given I was working with an existing code base, and my goal was to avoid any major refactor (or any code changes for that matter), I settled for creating the required configuration files that the existing libraries required in order to produce Native Images successfully.

Be aware that compiling Native Images is resource intensive and it takes a significantly longer amount of time compared to the bytecode compilation targeting a standard JVM runtime. Chances are that you may find yourself having to allocate more RAM to a build node to avoid out of memory issues, which shouldn’t be a deal breaker, but is definitely something to keep in mind.

Now that I’ve had my Native Image Lambdas compiled and packaged it was time to deploy them into a test environment. Normally, Java Lambdas utilize AWS’s Java Runtimes to execute; however, given we are trying to use a Native Image which is a binary artifact that contains our app code wrapped inside the Graal JVM, we must select one of the “Custom” Amazon Linux environments that AWS offers.

Testing Methodology

I have used a Postman API Collection to send requests to all the 9 Lambdas and measure cold start response times for each technique mentioned above. To ensure I was always encountering a cold start, I have reloaded target Lambda’s configuration which assures that the next invocation will not use an instance that might be already warm. All Lambdas were configured with 1GB of RAM. I have also measured a single invocation for every configuration given the process was time consuming; however, the observed response times painted a pretty clear picture.

Results

So did it work? Absolutely! Here are the results:

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

And the clear winner is: GraalVM Native Images - on average, it has resulted in a 3x speedup in comparison with the unchanged Java Lambdas - no more time-outs, and much better response times, which is exactly what I wanted to achieve.

SnapStart did not perform as well as I thought it would without any code changes. When the C1 compiler was employed in addition to the SnapStart feature, it lowered the cold start times further, but still did not beat GraalVM’s Native Image. That’s not to say that it’s not a viable option as a fast and easy to implement improvement; however, if we want to optimize our Lambda as much as possible and we have some time and resources to adjust configuration and our build process, GraalVM is definitely superior when it comes to performance and security.

Memory Footprint

As claimed by GraalVM, Native Images require less resources to run effectively as compared to their regular JVM counterparts. I wanted to see how the cold start and warm start performance would hold up if I was to reduce the amount of RAM these Lambdas had to work with. This time I have selected only a single Lambda app to perform this test. Here are the results:

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

And on their promise they have delivered! Regular JVM Lambdas ran out of memory when attempting configuration of 256 MB and lower, whereas the Native Image seemed to be unphased and continued executing. If not for 128 MB being the lowest available memory option, I wonder how much lower we could have gone. Native Images are not only faster on cold starts, but offer consistent performance when working with limited resources, which translates into lower operating costs.

Conclusion

Java’s ecosystem is rich and vast with many new technologies and enhancements emerging every day that keep Java in the game when it comes to serverless applications. One such emerging technology is GraalVM. What started as a research project is now slowly being adopted and poses as a viable alternative to a standard JVM such as HotSpot. In this blog post, I have barely scratched the surface of what GraalVM has to offer and I would encourage readers to explore it further. There are several success stories from companies such as Adyen (article link) or Facebook (article link) who were able to utilize GraalVM to save time and money.

So the next time you are about to discount Java as an option, give GraalVM a try. And now that Spring Boot 3 supports GraalVM Native Images out of the box, it’s easier than ever to employ them for your serverless workloads to capitalize on performance, low resource consumption and added security that GraalVM has to offer.

The above is the detailed content of Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Difference between HashMap and Hashtable? Difference between HashMap and Hashtable? Jun 24, 2025 pm 09:41 PM

The difference between HashMap and Hashtable is mainly reflected in thread safety, null value support and performance. 1. In terms of thread safety, Hashtable is thread-safe, and its methods are mostly synchronous methods, while HashMap does not perform synchronization processing, which is not thread-safe; 2. In terms of null value support, HashMap allows one null key and multiple null values, while Hashtable does not allow null keys or values, otherwise a NullPointerException will be thrown; 3. In terms of performance, HashMap is more efficient because there is no synchronization mechanism, and Hashtable has a low locking performance for each operation. It is recommended to use ConcurrentHashMap instead.

Why do we need wrapper classes? Why do we need wrapper classes? Jun 28, 2025 am 01:01 AM

Java uses wrapper classes because basic data types cannot directly participate in object-oriented operations, and object forms are often required in actual needs; 1. Collection classes can only store objects, such as Lists use automatic boxing to store numerical values; 2. Generics do not support basic types, and packaging classes must be used as type parameters; 3. Packaging classes can represent null values ??to distinguish unset or missing data; 4. Packaging classes provide practical methods such as string conversion to facilitate data parsing and processing, so in scenarios where these characteristics are needed, packaging classes are indispensable.

How does JIT compiler optimize code? How does JIT compiler optimize code? Jun 24, 2025 pm 10:45 PM

The JIT compiler optimizes code through four methods: method inline, hot spot detection and compilation, type speculation and devirtualization, and redundant operation elimination. 1. Method inline reduces call overhead and inserts frequently called small methods directly into the call; 2. Hot spot detection and high-frequency code execution and centrally optimize it to save resources; 3. Type speculation collects runtime type information to achieve devirtualization calls, improving efficiency; 4. Redundant operations eliminate useless calculations and inspections based on operational data deletion, enhancing performance.

What are static methods in interfaces? What are static methods in interfaces? Jun 24, 2025 pm 10:57 PM

StaticmethodsininterfaceswereintroducedinJava8toallowutilityfunctionswithintheinterfaceitself.BeforeJava8,suchfunctionsrequiredseparatehelperclasses,leadingtodisorganizedcode.Now,staticmethodsprovidethreekeybenefits:1)theyenableutilitymethodsdirectly

What is an instance initializer block? What is an instance initializer block? Jun 25, 2025 pm 12:21 PM

Instance initialization blocks are used in Java to run initialization logic when creating objects, which are executed before the constructor. It is suitable for scenarios where multiple constructors share initialization code, complex field initialization, or anonymous class initialization scenarios. Unlike static initialization blocks, it is executed every time it is instantiated, while static initialization blocks only run once when the class is loaded.

What is the Factory pattern? What is the Factory pattern? Jun 24, 2025 pm 11:29 PM

Factory mode is used to encapsulate object creation logic, making the code more flexible, easy to maintain, and loosely coupled. The core answer is: by centrally managing object creation logic, hiding implementation details, and supporting the creation of multiple related objects. The specific description is as follows: the factory mode handes object creation to a special factory class or method for processing, avoiding the use of newClass() directly; it is suitable for scenarios where multiple types of related objects are created, creation logic may change, and implementation details need to be hidden; for example, in the payment processor, Stripe, PayPal and other instances are created through factories; its implementation includes the object returned by the factory class based on input parameters, and all objects realize a common interface; common variants include simple factories, factory methods and abstract factories, which are suitable for different complexities.

What is the `final` keyword for variables? What is the `final` keyword for variables? Jun 24, 2025 pm 07:29 PM

InJava,thefinalkeywordpreventsavariable’svaluefrombeingchangedafterassignment,butitsbehaviordiffersforprimitivesandobjectreferences.Forprimitivevariables,finalmakesthevalueconstant,asinfinalintMAX_SPEED=100;wherereassignmentcausesanerror.Forobjectref

What is type casting? What is type casting? Jun 24, 2025 pm 11:09 PM

There are two types of conversion: implicit and explicit. 1. Implicit conversion occurs automatically, such as converting int to double; 2. Explicit conversion requires manual operation, such as using (int)myDouble. A case where type conversion is required includes processing user input, mathematical operations, or passing different types of values ??between functions. Issues that need to be noted are: turning floating-point numbers into integers will truncate the fractional part, turning large types into small types may lead to data loss, and some languages ??do not allow direct conversion of specific types. A proper understanding of language conversion rules helps avoid errors.

See all articles