Skip to content

Commit fc41bd5

Browse files
committed
Run Java applications on the Microsoft Cobalt 100 processors
Signed-off-by: odidev <[email protected]>
1 parent 604dba5 commit fc41bd5

File tree

7 files changed

+358
-0
lines changed

7 files changed

+358
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
title: Create an Arm based cloud VM using Microsoft Cobalt 100 CPU
3+
weight: 3
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Introduction
10+
11+
There are several ways to create an Arm-based Cobalt 100 VM : the Microsoft Azure console, the Azure CLI tool, or using your choice of IaC (Infrastructure as Code). This guide will use the Azure console to create a VM with Arm-based Cobalt 100 Processor.
12+
13+
This learning path focuses on the general-purpose VMs of the D series. Please read the guide on [Dpsv6 size series](https://learn.microsoft.com/en-us/azure/virtual-machines/sizes/general-purpose/dpsv6-series) offered by Microsoft Azure.
14+
15+
If you have never used the Microsoft Cloud Platform before, please review the microsoft [guide to Create a Linux virtual machine in the Azure portal](https://learn.microsoft.com/en-us/azure/virtual-machines/linux/quick-create-portal?tabs=ubuntu).
16+
17+
#### Create an Arm-based Azure Virtual Machine
18+
19+
Creating a virtual machine based on Azure Cobalt 100 is no different from creating any other VM in Azure. To create an Azure virtual machine, launch the Azure portal and navigate to Virtual Machines.
20+
21+
Select “Create”, and fill in the details such as Name, and Region. Choose the image for your VM (for example – Ubuntu 24.04) and select “Arm64” as the VM architecture.
22+
23+
In the “Size” field, click on “See all sizes” and select the D-Series v6 family of VMs. Select “D4ps_v6” from the list and create the VM.
24+
25+
![Instance Screenshot](./instance.png)
26+
27+
The VM should be ready and running; you can SSH into the VM using the PEM key, along with the Public IP details.
28+
29+
{{% notice Note %}}
30+
31+
To learn more about Arm-based VMs in Azure, refer to “Getting Started with Microsoft Azure” in [Get started with Arm-based cloud instances](https://learn.arm.com/learning-paths/servers-and-cloud-computing/csp/azure) .
32+
33+
{{% /notice %}}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
title: Install the JDK and build an application
3+
weight: 4
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
10+
### Working inside Azure Linux 3.0 Docker container
11+
The Azure Linux Container Host is an operating system image that's optimized for running container workloads on Azure Kubernetes Service (AKS). Microsoft maintains the Azure Linux Container Host and based it on CBL-Mariner, an open-source Linux
12+
distribution created by Microsoft.
13+
To know more about Azure Linux 3.0, kindly refer [What is Azure Linux Container Host for AKS](https://learn.microsoft.com/en-us/azure/azure-linux/intro-azure-linux). Azure Linux 3.0 offers support for Aarch64. However, the standalone VM image for Azure Linux 3.0 or CBL Mariner 3.0 is not available for Arm.
14+
15+
Hence, to use the default software stack provided by the Microsoft team, this guide will focus on creating a docker container with Azure Linux 3.0 as a base image and will build
16+
and run the Java application inside the container, with the default JDK provided by the Microsoft team via Azure Linux 3.0 environment.
17+
18+
### Create Azure Linux 3.0 Docker Container
19+
The [Microsoft Artifact Registry](https://mcr.microsoft.com/en-us/artifact/mar/azurelinux/base/core/about) offers updated docker image for the Azure Linux 3.0.
20+
21+
To create a docker container, install docker, and then follow the below instructions:
22+
23+
```console
24+
$ sudo docker run -it --rm mcr.microsoft.com/azurelinux/base/core:3.0
25+
```
26+
27+
The default container startup command is bash. tdnf and dnf are the default package managers.
28+
29+
### Install Java
30+
31+
This Azure Linux 3.0 image does not include Java, so you need to install it.
32+
33+
First update tdnf:
34+
35+
```console
36+
$ tdnf update -y
37+
```
38+
Then install java-devel:
39+
40+
```console
41+
$ tdnf install -y java-devel
42+
```
43+
44+
Java-devel installs both the default JRE and JDK provided by Azure Linux 3.0.
45+
46+
Check to ensure that the JRE is properly installed:
47+
48+
```console
49+
$ java -version
50+
```
51+
52+
**Your output will look like this:**
53+
54+
```output
55+
openjdk version "11.0.27" 2025-04-15 LTS
56+
OpenJDK Runtime Environment Microsoft-11371464 (build 11.0.27+6-LTS)
57+
OpenJDK 64-Bit Server VM Microsoft-11371464 (build 11.0.27+6-LTS, mixed mode,
58+
sharing)
59+
```
60+
61+
**Check to ensure that the JDK is properly installed:**
62+
63+
```console
64+
$ javac -version
65+
```
66+
Your output will look like this:
67+
68+
```output
69+
javac 11.0.27
70+
```
71+
72+
Set Java Environment Variable for Arm:
73+
74+
```console
75+
$ export JAVA_HOME=/usr/lib/jvm/msopenjdk-11
76+
$ export PATH=$JAVA_HOME/bin:$PATH
77+
```
78+
79+
{{% notice Note %}}
80+
Azure Linux 3.0 offers the default JDK version 11.0.27. It’s important to ensure that your version of OpenJDK for Arm is at least 11.0.9, or above. There is a large performance gap between OpenJDK-11.0.8 and OpenJDK 11.0.9. A patch added in 11.0.9 reduces false-sharing cache contention.
81+
For more information, you can view this [Arm community blog](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/java-performance-on-neoverse-n1).
82+
83+
The [Arm Ecosystem Dashboard](https://developer.arm.com/ecosystem-dashboard/) also recommends Java/OpenJDK version 11.0.9 as minimum recommended on the Arm platforms.
84+
{{% /notice %}}
85+
86+
### Deploy a Java application with Tomcat-like operation
87+
Apache Tomcat is a Java-based web application server (technically, a Servlet container) that executes Java web applications. It's widely used to host Java servlets, JSP (JavaServer Pages),
88+
and RESTful APIs written in Java.
89+
The below Java class simulates the generation of a basic HTTP response and measures the time taken to construct it, mimicking a lightweight Tomcat-like operation. It measures how long it
90+
takes to build the response string, helping evaluate raw Java execution efficiency before deploying heavier frameworks like Tomcat.
91+
Create a file named `HttpSingleRequestTest.java`, and add the below content to it:
92+
93+
```java
94+
public class HttpSingleRequestTest {
95+
public static void main(String[] args) {
96+
long startTime = System.nanoTime();
97+
String response = generateHttpResponse("Tomcat baseline test on Arm64");
98+
long endTime = System.nanoTime();
99+
double durationInMicros = (endTime - startTime) / 1_000.0;
100+
System.out.println("Response Generated:\n" + response);
101+
System.out.printf("Response generation took %.2f microseconds.%n", durationInMicros);
102+
}
103+
private static String generateHttpResponse(String body) {
104+
return "HTTP/1.1 200 OK\r\n" +
105+
"Content-Type: text/plain\r\n" +
106+
"Content-Length: " + body.length() + "\r\n\r\n" +
107+
body;
108+
}
109+
}
110+
```
111+
Compile and Run Java program :
112+
113+
```console
114+
$ javac HttpSingleRequestTest.java
115+
$ java -Xms128m -Xmx256m -XX:+UseG1GC HttpSingleRequestTest
116+
```
117+
118+
- -Xms128m sets the initial heap size for the Java Virtual Machine to 128 MB.
119+
- -Xmx256m sets the maximum heap size for the JVM to 256 MB.
120+
- -XX:+UseG1GC enables the G1 Garbage Collector (Garbage First GC), designed for low pause times and better performance in large heaps.
121+
122+
Output of java program on the Arm VM:
123+
```output
124+
125+
$ javac HttpSingleRequestTest.java
126+
$ java -Xms128m -Xmx256m -XX:+UseG1GC HttpSingleRequestTest
127+
Response Generated:
128+
HTTP/1.1 200 OK
129+
Content-Type: text/plain
130+
Content-Length: 29
131+
132+
Tomcat baseline test on Arm64
133+
Response generation took 22125.79 microseconds.
134+
```
135+
Output summary:
136+
137+
- The program generated a fake HTTP 200 OK response with a custom message.
138+
- It then measured and printed the time taken to generate that response (22125.79 microseconds).
139+
- This serves as a basic baseline performance test of string formatting and memory handling on the JVM running on an Azure Arm64 instance.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
title: Run Java applications on the Microsoft Azure Cobalt 100 processors
3+
4+
minutes_to_complete: 60
5+
6+
who_is_this_for: This is an introductory topic for the software developers who are willing to migrate their Java-based applications from x86_64 platforms to Arm-based platforms, or on Microsoft Azure - Cobalt 100 CPU-based VMs specifically. Most Java applications will run on Cobalt 100 with no changes needed.
7+
8+
learning_objectives:
9+
- Provision an Azure Arm64 VM using Azure console, with Ubuntu as the base image.
10+
- Deploy a Java application inside an Azure Linux Arm64-based Docker container.
11+
- Perform Java benchmarking inside the container running on the Azure Arm64 VM.
12+
13+
prerequisites:
14+
- A [Microsoft Azure](https://azure.microsoft.com/) account with access to Cobalt 100 based instances (Dpsv6).
15+
- A machine with [Docker](/install-guides/docker/) installed.
16+
17+
author: Zach Lasiuk
18+
19+
### Tags
20+
skilllevels: Advanced
21+
subjects: Performance and Architecture
22+
cloud_service_providers: Azure
23+
24+
armips:
25+
- Neoverse-N2
26+
27+
tools_software_languages:
28+
- Java
29+
- Docker
30+
31+
operatingsystems:
32+
- Linux
33+
34+
further_reading:
35+
- resource:
36+
title: Azure Virtual Machines documentation
37+
link: https://learn.microsoft.com/en-us/azure/virtual-machines/
38+
type: documentation
39+
- resource:
40+
title: Azure Container Instances documentation
41+
link: https://learn.microsoft.com/en-us/azure/container-instances/
42+
type: documentation
43+
- resource:
44+
title: Docker overview
45+
link: https://docs.docker.com/get-started/overview/
46+
type: documentation
47+
- resource:
48+
title: Java on Azure
49+
link: https://learn.microsoft.com/en-us/java/azure/
50+
type: documentation
51+
- resource:
52+
title: JMH (Java Microbenchmark Harness) documentation
53+
link: https://openjdk.org/projects/code-tools/jmh/
54+
type: documentation
55+
56+
57+
### FIXED, DO NOT MODIFY
58+
# ================================================================================
59+
weight: 1 # _index.md always has weight of 1 to order correctly
60+
layout: "learningpathall" # All files under learning paths have this same wrapper
61+
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content.
62+
---
63+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
# ================================================================================
3+
# FIXED, DO NOT MODIFY THIS FILE
4+
# ================================================================================
5+
weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation.
6+
title: "Next Steps" # Always the same, html page title.
7+
layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing.
8+
---
9+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
title: "Background"
3+
4+
weight: 2
5+
6+
layout: "learningpathall"
7+
---
8+
9+
## What is Cobalt 100 Arm-based processor?
10+
11+
Azure’s Cobalt 100 is built on Microsoft's first-generation, in-house Arm-based processor: the Cobalt 100. Designed entirely by Microsoft and based on Arm’s Neoverse N2 architecture, this 64-bit CPU delivers improved performance and energy efficiency across a broad spectrum of cloud-native, scale-out Linux workloads. These include web and application servers, data analytics, open-source databases, caching systems, and more. Running at 3.4 GHz, the Cobalt 100 processor allocates a dedicated physical core for each vCPU, ensuring consistent and predictable performance.
12+
13+
To learn more about Cobalt 100, refer to the blog [Announcing the preview of new Azure VMs based on the Azure Cobalt 100 processor](https://techcommunity.microsoft.com/blog/azurecompute/announcing-the-preview-of-new-azure-vms-based-on-the-azure-cobalt-100-processor/4146353).
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
title: Benchmarking via JMH
3+
weight: 5
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Test the Java application for Performance
10+
Now that you’ve built and run the Tomcat-like response, you can use it to test the JVM performance using JMH. You can also use it to test the performance difference between Cobalt 100 instances and other similar D series x86_64 based instances.
11+
12+
## Run the performance tests using JMH
13+
14+
JMH (Java Microbenchmark Harness) is a Java benchmarking framework developed by the JVM team at Oracle to measure the performance of small code snippets with high precision. It accounts for JVM optimizations like JIT and warm-up to ensure accurate and reproducible results. It measures the throughput, average latency, or execution time. Below steps help benchmark the Tomcat-like operation:
15+
16+
Install Maven:
17+
18+
```console
19+
$ tdnf install maven -y
20+
```
21+
Create Benchmark Project:
22+
23+
```console
24+
$ mvn archetype:generate \
25+
-DinteractiveMode=false \
26+
-DarchetypeGroupId=org.openjdk.jmh \
27+
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
28+
-DarchetypeVersion=1.37 \
29+
-DgroupId=com.example \
30+
-DartifactId=jmh-benchmark \
31+
-Dversion=1.0
32+
$ cd jmh-benchmark
33+
```
34+
35+
Edit the `src/main/java/com/example/MyBenchmark.java` file and add the below code on it:
36+
37+
```java
38+
package com.example;
39+
import org.openjdk.jmh.annotations.Benchmark;
40+
public class MyBenchmark {
41+
42+
@Benchmarkpublic void benchmarkHttpResponse() {
43+
String body = "Benchmarking a Tomcat-like operation";
44+
StringBuilder sb = new StringBuilder();
45+
sb.append("HTTP/1.1 200 OK\r\n");
46+
sb.append("Content-Type: text/plain\r\n");
47+
sb.append("Content-Length: ").append(body.length()).append("\r\n\r\n");
48+
sb.append(body);
49+
if (sb.length() == 0) throw new RuntimeException(); // avoid DCE }
50+
}
51+
```
52+
This simulates HTTP response generation similar to Tomcat.
53+
54+
Build the Benchmark:
55+
56+
```console
57+
$ mvn clean install
58+
```
59+
60+
After the build is complete, the JMH benchmark jar will be in the target/ directory.
61+
62+
Run the Benchmark:
63+
64+
```console
65+
$ java -jar target/benchmarks.jar
66+
```
67+
68+
Output:
69+
70+
```output
71+
Result "com.example.MyBenchmark.benchmarkHttpResponse":
72+
35600560.283 ?(99.9%) 121215.695 ops/s [Average]
73+
(min, avg, max) = (35293153.787, 35600560.283, 35831841.216), stdev = 161819.485
74+
CI (99.9%): [35479344.588, 35721775.978] (assumes normal distribution)
75+
# Run complete. Total time: 00:08:21
76+
```
77+
78+
## Benchmark summary on x86_64 based D4s_v6 general purpose Azure VM (JDK 11.0.27)
79+
80+
The benchmark was executed inside an Azure Linux 3.0 Docker container on an x86_64 VM using the default Microsoft OpenJDK 11.0.27.
81+
- Average Throughput: 21.88 million operations per second
82+
- Standard Deviation: ±76941.944 ops/sec
83+
- Confidence Interval (99.9%): [21.82M, 21.94M] ops/sec
84+
- Run Count: 25 iterations
85+
86+
## Benchmark summary on Arm64 based D4ps_v6 general purpose Azure VM (JDK 11.0.27):
87+
88+
The benchmark was run using JMH inside an Azure Linux 3.0 Docker container on an Arm64 VM
89+
with the default Microsoft OpenJDK 11.0.27.
90+
- Average Throughput: 35.60 million operations per second
91+
- Standard Deviation: ±161819.485 ops/sec
92+
- Confidence Interval (99.9%): [35.48M, 35.72M] ops/sec
93+
- Run Count: 25 iterations
94+
95+
## Highlights from Azure Linux Arm64 Benchmarking (JDK 11.0.27)
96+
97+
- **Superior Throughput:** Achieved an average of 35.60 million ops/sec.
98+
- **Stable Performance:** Low standard deviation161819.485 ops/sec) and a tight confidence interval suggest consistent benchmarking results.
99+
- **Efficient Execution:** Demonstrates the efficiency of the Arm64 architecture for handling high-throughput Java workloads, even within a containerized Azure Linux environment.
100+
- **Container Feasibility:** Confirms that Azure Linux 3.0 containers on Arm64 are a viable option for performance-sensitive Java applications, even in the absence of native Arm64 VM images.
101+
68.7 KB
Loading

0 commit comments

Comments
 (0)