Post

Is Graviton5 Really Faster for Your Workloads? Debunking Performance Myths

Skeptical about Graviton5 25% uplift claims? This post cuts through hype to debunk myths and reveal true performance gains.

Is Graviton5 Really Faster for Your Workloads? Debunking Performance Myths

Myth: Just switching to Graviton5 instances will automatically make my application 25% faster. This promise feels like a free lunch, but reality is more nuanced. The impressive benchmarks you see are for specific, highly-optimized workloads, and your mileage will absolutely vary.

TL;DR: AWS Graviton5 performance gains are real but not automatic. The 25% uplift hinges on your workload being multi-threaded and memory-bound, not I/O-bound. This post provides a simple benchmark framework and a decision checklist to see if your application is a good fit before you migrate.

You’ll walk away with:

  • A clear mental model for which workloads benefit most from Graviton5.
  • A simple, copy-pasteable hey command to benchmark your own HTTP services.
  • A pre-migration checklist to make a data-driven decision.
  • The one compiler flag that makes the biggest difference for compiled languages.

The AWS marketing material for M9g instances claims they “deliver up to 25% better compute performance… than comparable Graviton4-based M7g instances.” The key here is “up to”. Those gains don’t come from magic; they come from tangible architectural improvements: faster DDR5 memory and higher core density.

This means your application must actually be in a position to use that extra memory bandwidth and those extra cores. A single-threaded Python script waiting on a slow database query won’t get any faster. But a Go web service handling thousands of concurrent requests can see a massive improvement.

At its core, vCPU on Graviton represents a physical core, not a hyper-thread as it is on x86. This distinction is critical: when you scale up cores on Graviton, you are adding real, physical execution units, which dramatically benefits truly parallel workloads.

graph TD
    subgraph "Graviton5 Sweet Spot"
        A["Web Server (Go, Rust, Java)"] -- "many concurrent requests" --> B["Parallel Task Processing"];
        C["ML Inference (Batch Processing)"] -- "utilizes all cores" --> D["In-Memory Database (Redis)"];
    end
    subgraph "Gains Will Be Marginal"
        X["Single-threaded Python Script"] -- "waits on API call" --> Y["Network I/O"];
        Z["Legacy App (single process)"] -- "cannot parallelize" --> W["Disk I/O Bound"];
    end

The myth is that the instance type is the variable that matters most. The truth is that the bottleneck in your application architecture is what dictates performance. Graviton5 only fixes CPU and memory bottlenecks.

How Do You Benchmark Your Application for Graviton?

To benchmark your application, you must test the entire stack under a realistic load, not just a synthetic CPU test. Deploy identical versions of your application to both an M7g (Graviton4) and an M9g (Graviton5) instance. Then, use a load generation tool like hey to hammer the endpoints and compare requests per second and latency distributions.

Here’s a simple, effective test for an HTTP API. Run this from a separate EC2 instance in the same VPC to get a clean network measurement.

1
2
3
4
5
# First, benchmark the existing M7g instance to get a baseline
hey -z 2m -c 100 http://<m7g-instance-ip>:8080/api/v1/workload

# Then, run the exact same test against the new M9g instance
hey -z 2m -c 100 http://<m9g-instance-ip>:8080/api/v1/workload

Look for a significant increase in “Requests/sec” and a decrease in the average and 99th percentile latency in the output.

Click to see example 'hey' output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Summary:
  Total:	120.0059 secs
  Slowest:	0.1588 secs
  Fastest:	0.0088 secs
  Average:	0.0249 secs
  Requests/sec:	4007.8206

  Total data:	2048.00 MB
  Size/req:	4259 bytes

Response time histogram:
  0.009 [1]	|
  0.024 [179782] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.039 [199701] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.054 [78001]	|■■■■■■■■■■■■■
  0.069 [15600]	|■■■
  0.084 [5200]	|■
  0.099 [1820]	|
  0.114 [520]	|
  0.129 [1]	|
  0.144 [1]	|
  0.159 [1]	|

Latency distribution:
  10% in 0.0150 secs
  25% in 0.0190 secs
  50% in 0.0250 secs
  75% in 0.0310 secs
  90% in 0.0380 secs
  95% in 0.0430 secs
  99% in 0.0560 secs

My strong recommendation: do not use generic CPU benchmarks like sysbench cpu run. They are misleading because they test a workload that lives entirely in L1 cache and ignores memory bandwidth and I/O, which is where real-world gains (or losses) happen.

Test your actual application under a production-like load; synthetic benchmarks lie.

What Compiler Flags Actually Matter for Graviton?

For compiled languages like Go, Rust, or C++, the single most important optimization is telling the compiler which specific CPU it’s building for. Use the -march=native flag to allow the compiler to generate instructions that leverage newer features of the Arm architecture, like the Scalable Vector Extension (SVE). This often yields a bigger performance boost than tweaking optimization levels.

Without this flag, the compiler targets a generic arm64 baseline, leaving performance on the table.

Here’s the change in a typical Makefile:

1
2
3
4
5
6
7
8
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,3 @@
 CC=gcc
-CFLAGS=-O2 -Wall
+CFLAGS=-O3 -march=native -Wall
 
 myapp: myapp.c

For interpreted languages like Python, Ruby, or Node.js, you don’t need to worry about compiler flags for your own code. The performance gains come from ensuring your runtime (e.g., the Python interpreter, the Node.js binary) is a modern version compiled specifically for Arm64. Use official arm64 builds and you’ll inherit the benefits automatically.

For C++/Rust/Go, always compile with -march=native on the build server to let the compiler use the best instructions for the target CPU.

Is Your Workload Ready for Graviton5?

Before you commit to a migration, run through this checklist. If you can’t check at least three of these, you may not see the performance gains you’re hoping for.

  • My workload is multi-threaded, multi-process, or handles many concurrent requests.
  • My application is CPU-bound or memory-bound, not primarily I/O-bound.
  • I have an established performance baseline (requests/sec, latency) on my current instance type.
  • My entire software stack, including OS, runtimes, and libraries, has official arm64 support.
  • For compiled code, my build pipeline can use target-specific flags like -march=native.

This isn’t about just lifting and shifting. It’s about shifting to an architecture that rewards parallelism and efficient memory access.

In our next post, we’ll dive deep into specific perf and eBPF tooling you can use to find the exact functions in your code that are CPU-bound and ripe for optimization on Graviton5.

Bottom Line

Graviton5 delivers on its performance promises, but only for the right workloads. Stop treating it like a magic button and start treating it like an architectural choice. If your application is bottlenecked by CPU or memory bandwidth, you’ll see substantial price-performance improvements. If it’s waiting on a disk or a network call, you’re just paying for cores you can’t use.

FAQ

Is Graviton5 cheaper than Graviton4?

No, M9g instances typically have a higher on-demand price than comparable M7g instances. The value proposition is in price-performance: you can potentially run your workload on a smaller instance or fewer instances, leading to an overall cost reduction.

Do I need to recompile my application for Graviton5?

If you are already running on a Graviton instance, a recompile is not strictly required but is highly recommended. Using a modern compiler with flags like -march=native enables the binary to use instruction sets available on newer processors for a significant performance boost.

What is the main difference between Graviton4 and Graviton5?

The key architectural upgrades in the Graviton5 processors powering M9g instances are support for DDR5 memory, which offers 50% more bandwidth than the DDR4 used with Graviton4, and a higher physical core count per socket.

Can I run Docker containers on Graviton5?

Absolutely. As long as your Docker image is built for the linux/arm64 architecture, it will run without modification. Most official upstream images (like node, python, golang) provide multi-architecture manifests, so docker pull automatically fetches the correct version.

What’s the easiest way to build a multi-arch Docker image?

Use docker buildx. The command docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest . --push will build your image for both architectures and push them to the registry under a single tag.

Further Reading


🚀 Ready to get hands-on? Spin up an interactive AI or Kubernetes Sandbox at Aicademy Labs for free.

This post is licensed under CC BY 4.0 by the author.