Can Java Microservices Match Go’s Speed? Benchmark Results Revealed

Through a series of benchmark tests comparing simple, logging‑enabled microservices written in Java (Helidon) and Go (Go‑Kit), the authors evaluate whether Java can achieve Go‑like performance, exploring JVM tuning, GraalVM native images, and Kubernetes deployments to uncover speed, memory, and scalability trade‑offs.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Can Java Microservices Match Go’s Speed? Benchmark Results Revealed

1. Background

We wanted to determine whether Java microservices can achieve the same runtime speed as Go microservices. The industry often views Java as old, slow, and boring, while Go is seen as fast, modern, and cool. We set out to test this perception with data.

To ensure a fair test we built a very simple microservice without external dependencies (e.g., databases) and with a short code path that only processes strings. The service includes metrics and logging, uses lightweight frameworks (Helidon for Java and Go‑Kit for Go), and also a pure JAX‑RS implementation for Java. Different Java versions, JVMs, heap sizes, and garbage‑collector settings were tried, and the services were warmed up before testing.

2. History of Java

Java was created by Sun Microsystems and later acquired by Oracle. Version 1.0 was released in 1996; the latest at the time of writing is Java 15 (2020). Its main goals are JVM and bytecode portability and garbage‑collected memory management. Java remains one of the most popular open‑source languages worldwide.

Common beliefs about Java’s slowness are largely outdated. Modern Java features many performance‑sensitive areas, such as advanced garbage collectors (serial, parallel, concurrent‑mark‑sweep, G1, ZGC) and a JIT compiler.

Oracle Labs developed GraalVM, a Java VM written in Java that can compile bytecode to native images that run without a JVM.

3. History of Go

Go was created at Google by Robert Griesemer, Rob Pike, and Ken Thompson. Go 1.0 was released in 2012; the latest at the time is 1.15 (2020). It is an open‑source, statically typed compiled language influenced by C, Python, JavaScript, and C++.

Go offers memory safety, garbage collection, structured types, and CSP‑style concurrency with lightweight goroutines and channels. It is the language of choice for many CNCF projects such as Kubernetes, Istio, Prometheus, and Grafana.

Key perceived advantages of Go over Java include simpler function‑style programming, far less boilerplate, early‑stage language evolution with little backward‑compatibility pressure, native static binaries, smaller size, faster startup, and the absence of OOP, inheritance, generics, and pointer arithmetic.

However, Go also has drawbacks: an immature tooling ecosystem, slower dependency management, lack of dynamic linking, limited runtime tuning options, and missing language features such as try/catch exceptions.

4. Load‑Testing Methodology

We used JMeter to generate load, measuring response time, throughput (transactions per second), and memory usage. For Go we collected resident set size; for Java we tracked native memory. Tests were run on the same machine as JMeter, with a 1 000‑call warm‑up phase before each run.

The source code and JMeter test definitions are available at https://github.com/markxnelson/go-java-go .

5. First Round of Tests

Tests were executed on a 2.5 GHz dual‑core Intel i7 laptop with 16 GB RAM running macOS. We used 100 threads, each performing 10 000 loops, plus a 10‑second warm‑up. Java ran on JDK 11 with Helidon 2.0.1; Go used Go 1.13.3.

Go was the clear winner in this round.

Logging (especially java.util.logging) was a major performance factor; disabling it improved results.

Java’s memory footprint was noticeably larger even for this tiny service.

JVM warm‑up had a large impact; pre‑warming is crucial for Java performance.

We also compared native‑image builds with GraalVM to bring Java closer to Go’s execution model.

6. GraalVM Native Images

GraalVM can compile Java applications into native executables that include all classes, dependencies, and runtime libraries, eliminating the need for a separate JVM.

When using GraalVM native images in the first round, throughput and latency did not improve significantly, but memory usage decreased.

Response‑time charts showed that the first request in all Java variants was much slower, with occasional peaks likely caused by garbage collection or JIT optimizations.

7. Second Round of Tests

This round used a larger machine with 36 cores (hyper‑threaded) and 256 GB RAM running Oracle Linux 7.8. The same workload (100 threads, 10 000 loops, 10‑second warm‑up) and versions of Go, Java, Helidon, and GraalVM were used.

GraalVM native image won this round.

Key observations:

Java variants improved dramatically; without logging they outperformed Go.

Java leveraged multiple cores and threads more effectively than Go.

GraalVM native image achieved the best latency (≈0.25 ms, 82 426 tps) and the smallest memory footprint.

Go’s latency was more consistent, likely due to its incremental garbage collection.

8. Third Round: Kubernetes

We deployed the services to a three‑node Kubernetes 1.16.8 cluster (each node: 2 cores, 14 GB RAM, Oracle Linux 7.8). Tests ran with 100 threads, 10 000 loops, and a 10‑second warm‑up, with JMeter outside the cluster.

Go binary size: 11.6 MB

Java/Helidon JAR: 1.41 GB

Java/Helidon JLinked: 150 MB

GraalVM native image: 25.2 MB

Results showed Go sometimes faster, GraalVM often leading, but differences were generally under 5 %.

9. Conclusions

Kubernetes did not provide rapid horizontal scaling.

Java utilizes all available cores/threads better than Go on large machines.

On smaller or less powerful hardware, Go outperforms Java.

Go’s performance is more consistent, likely due to Java’s garbage‑collection pauses.

In production‑scale hardware, Java and Go performance are comparable.

Logging is a major bottleneck for both languages.

Modern Java versions and frameworks like Helidon mitigate many historic Java issues (verbosity, GC, startup time).

10. Future Work

Explore automatic scaling in Kubernetes with more complex services and higher load.

Investigate network effects and microservice‑mesh tuning.

Deep‑dive into logging overhead and mitigation strategies.

Analyze generated machine code to find further optimization opportunities.

Assess JMeter’s ability to generate load without becoming a bottleneck.

Measure container startup time and memory usage in greater detail.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaMicroservicesKubernetesGoperformance benchmarkgraalvm
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.