Cost savings can often be as simple as upgrading the version of Java you’re using. However, anyone who has managed Java in large organizations knows that this process is rarely easy. This is where platforms like Cloud Foundry truly excel. In episode 21 of Cloud Foundry Weekly, Mark Fynes demonstrated how Tanzu Platform’s Java Native Image Compilation can significantly reduce memory consumption, enabling new opportunities for cloud-native applications, even at the edge.
Shrink Your Java App’s Memory by 90%
With GraalVM and the new Java native image buildpack on Tanzu Platform, you can reduce your Java app’s memory usage by 90%. This allows your applications to use fewer resources, which directly contributes to cost savings and more compute capacity. Mark Fynes, Field Principal Solutions Engineer at Broadcom, walks us through this optimization with a simple helloWorld app that cuts memory from 1GB to just 32MB. For real-world apps, even halving memory needs would deliver huge benefits, saving costs, capacity expansion, and enhancing scalability. So how can you implement this with existing applications currently running on a tPCF foundation?
The Java Optimizer Solution
Let’s say we have an existing Java app, testApp. The first thing we need to do is re-build the app as a Java native image. Mark’s CF Java Optimizers simplifies this process. . We start by targeting the space in which the application is currently deployed and execute the command:
cf-java-optimizer.sh <appName> <appMemorySize>
Here, the optional “AppMemory” parameter specifies the amount of memory desired for the application post build, with a default value of 32Mbs. The recommendation is to start with your original application’s memory footprint, build the application, then adjust based on running memory once deployed. You should see significant memory requirement reduction upon migration to native images. While Mark’s demo gives a better visual, this method will, in essence, extract the currently running application droplet, reissue the build command (while leaving the current app running) to migrate the droplet into a native image, then redeploy in a typical blue green fashion.
You’ll see in Mark’s demo his CF Java Optimizer script automates migrating existing apps to Java native images—bringing sub-second startup times, improved resource use, and no downtime—without developer interaction or application downtime. This appeals to developers and platform engineers alike, and it will appeal even more to management that’s looking to lower costs. Mark also provides the demo code for those of you who like to experiment, this is a great way to show the art of the possible.
Should you decide to replicate this demo, it is important to include the -Pnative flag in your Maven package and ensure the graalvm-build-tools is included in your POM file to accommodate the change necesssary to complete the native image compliation.
Watch Mark’s demo here:
A Small Price for Big Gains
One downside to native images is that they take longer to compile, sometimes more than 20 minutes, but as Mark explains, it’s a one-time cost that can be implemented in staging and production builds. To deal with this, developers can use non-native images that are less time consuming during experimentation and testing, then switch to native images for staging to realize the memory optimizations. Once built, the droplet can be easily reused across multiple Cloud Foundry implementations, on-prem or public cloud . That is, you only need to build the droplet once and then you can deploy it multiple times and places, just like container images.
Utilizing some less known commands on the Tanzu Platform cf-cli, you can deploy droplets across orgs, spaces, and Cloud Foundry environments, to enhance deployment flexibility. In our example HelloWorld app, the below shows the commands necessary, how to list, download, and deploy the original testApp droplet as testApp2:
- cf droplets <AppName>: Lists all stored droplets for the specified app
repo/sandbox ❯ cf droplets testApp
Getting droplets of app testApp in org DemoOrg / space DemoSpace as admin...
guid state created
23efa083-d63c-448e-b405-d1f641d5a66d (current) staged Thu 19 Sep 10:12:22 MDT 2024
589a31f6-dce5-44a5-82f9-94c89565ca57 staged Thu 19 Sep 09:58:01 MDT 2024
fbbb3869-1e42-485d-9030-2d6e6e621215 staged Thu 19 Sep 09:50:40 MDT 2024
- cf download-droplet <AppName> <optional_switches>: This command downloads a previously compiled droplet from Tanzu Platform as a .tgz file.
–droplet <GUID>: Specify the app’s droplet GUID to download. Defaults to the current droplet of the named applications.
–path, -p <directory>: Set the destination path. Defaults to the current directory if not specified.
repo/sandbox ❯ cf download-droplet testApp --path ~/tmp
Downloading current droplet for app GuidEnricher in org DemoOrg / space DemoSpace as admin...
Droplet downloaded successfully at /Users/<user>/tmp/droplet_23efa083-d63c-448e-b405-d1f641d5a66d.tgz
OK
- cf push <appName> –droplet <path_to_downloaded_droplet>: Deploy a previously downloaded droplet to another foundation, org, or space. This allows you to build the droplet once and deploy it multiple times without rebuilding.
repo/sandbox ❯ cf push testApp2 --droplet ~/tmp/droplet_23efa083-d63c-448e-b405-d1f641d5a66d.tgz
Pushing app testApp2 to org DemoOrg / space DemoSpace as admin...
Uploading droplet bits...
79.80 MiB / 79.80 MiB [===========================================] 100.00% 32s
Waiting for API to complete processing files...
Waiting for app testApp2 to start...
Instances starting...
Instances starting...
name: testApp2
requested state: started
routes: testApp2.<redacted_domain>
last uploaded: Tue 24 Sep 15:09:28 MDT 2024
stack:
buildpacks:
type: web
sidecars:
instances: 1/1
memory usage: 1024M
state since cpu memory disk details
#0 running 2024-09-24T21:10:21Z 104.8% 119.3M of 1G 206M of 1G
That’s it! With a change like this, you can expect anywhere from 30% to 90% reduced memory usage. That’s a lot for even just one app, when spread across hundreds of apps you can imagine how it really adds up.
More than just cost savings
Using fewer resources and saving money is probably the best result in most cases. But, there’s other functionality you can get when you switch to Java native image buildpacks:
- Build-Only Foundations: Build droplets once and deploy them across multiple environments using CI/CD pipelines, ensuring identical deployments.
- Edge Deployments: Ideal for lightweight Cloud Foundry implementations in resource-constrained environments.
- Multi-Cloud Portability: Use small footprint foundations in public clouds, reducing runtime costs and management complexity while enabling business units to pay for only what they use.
Java native image compilation and Cloud Foundry droplet portability have the potential to transform how apps are deployed in the cloud and at the edge. These capabilities provide the ability to optimize resource usage, cut costs, and scale applications efficiently. Whether you’re a developer, platform engineer, or business leader, these advancements can provide you with significant value.
There’s a lot more detail and demoing from Mark in the episode 21 of Cloud Foundry Weekly. And, for more insights like this, tune in to Cloud Foundry Weekly, and don’t forget to like and subscribe for the latest updates!