Menu
Rust vs Zig vs Go Performance

Rust vs Zig vs Go Performance

Anton Putra

138,526 views 1 year ago 7 min read

Video Summary

This video benchmarks three programming languages: Rust, Zig, and Go, focusing on HTTP application performance. The tests measure latency, throughput, saturation (CPU and memory usage), and errors using a production-ready Kubernetes cluster. Initially, Go shows higher CPU usage and slightly higher latency. As request volume increases, Go begins to degrade around 20,000 requests per second, with its latency rising significantly.

Rust and Zig perform comparably for most metrics, with Zig using less memory at idle. However, Rust's memory usage eventually catches up to and surpasses Zig's. At approximately 98,000 requests per second, Rust starts to degrade, exhibiting increased latency and returning errors, leading to a drop in availability.

Ultimately, Zig demonstrates the highest throughput, capable of processing around 118,000 requests per second, followed closely by Rust at 113,000 requests per second. Go lags significantly, reaching only 70,000 requests per second and experiencing out-of-memory errors that lead to it being killed by Kubernetes. The comparison highlights the superior performance and scalability of Rust and Zig over Go for high-throughput HTTP applications.

Short Highlights

  • Benchmarking Methodology: The test utilizes four key metrics: latency (P99 percentile), throughput (requests per second), saturation (CPU/memory usage relative to Kubernetes limits), and errors (successful requests ratio).
  • Initial Performance: Go exhibits higher CPU usage and slightly higher latency from the start, while Rust and Zig remain competitive, though Zig uses considerably less idle memory (under 1 MB for Rust vs. almost 25 MB for Zig).
  • Go's Degradation: Go begins to degrade around 20,000 requests per second, with its latency increasing. By 33,000 requests per second, it cannot compete in latency. At 40,000 requests per second, it starts dropping requests, and by 51,000 requests per second, it's significantly outmatched. It eventually consumes over 256 MB of memory and is terminated.
  • Rust vs. Zig Performance: Rust's memory usage eventually overtakes Zig's. Rust starts degrading around 98,000 requests per second, showing increased latency and availability drops due to timeouts.
  • Final Throughput Results: Zig achieves the highest throughput at approximately 118,000 requests per second. Rust follows at 113,000 requests per second. Go is significantly lower, peaking at around 70,000 requests per second.

Key Details

Benchmarking Metrics [00:20]

  • The test focuses on four "golden signals" for application monitoring: latency, throughput, saturation, and errors.
  • Latency is measured using the 99th percentile (P99).
  • Throughput measures how many requests per second each application can handle for HTTP-based applications.
  • Saturation monitors how full the service is, tracking CPU usage relative to Kubernetes limits and actual memory usage.
  • CPU throttling is also monitored.
  • Errors or availability is defined as the ratio of successful requests to the total number of requests for an HTTP service.

The testing methodology is designed to provide a comprehensive view of application performance under load by examining key metrics like latency, throughput, and resource utilization. These metrics are crucial for understanding an application's stability and efficiency.

"we'll focus on four golden signals"

Test Environment and Setup [01:14]

  • A production-ready Kubernetes cluster is used for benchmarking.
  • Large EC2 instances are used to deploy the applications.
  • Four extra-large Graviton-based instances (ARM-based and cheaper than AMD) are used to run the clients.
  • A simple API endpoint /api/v1/devices is created, returning a single hardcoded device to the client, to establish baseline performance.

The infrastructure is set up to closely mirror real-world production environments, using scalable cloud resources and a representative API endpoint for testing.

"I use production ready kubernetes cluster in ads to run most of my benchmarks"

Initial Idle State Performance [02:01]

  • All three applications are run for approximately 5 minutes without any load to observe idle state performance.
  • Actual memory usage in bytes is displayed.
  • At idle, Rust uses under 1 MB of memory, while Zig uses almost 25 MB.

This initial observation reveals a significant difference in memory footprint when the applications are not actively processing requests.

"in idle State Rost uses under 1 mgab while Zig uses almost 25 mbes of memory"

Early Performance Comparison [02:30]

  • Go exhibits higher CPU usage from the start and slightly higher latency compared to Rust and Zig.
  • Rust and Zig perform very closely across most metrics, with the primary difference being memory usage.
  • Go begins to degrade at around 20,000 requests per second, with its latency starting to rise.

Go's initial performance indicates a higher resource overhead and a susceptibility to performance degradation at lower loads compared to Rust and Zig.

"as expected goling has higher CPU usage from the start and its latency is slightly higher than rust and zik"

Go's Performance Decline [03:01]

  • By 33,000 requests per second, Go is clearly unable to compete with Rust and Zig in terms of latency.
  • At 40,000 requests per second, Go starts to drop some requests and cannot keep up in terms of throughput.
  • Go begins caching more requests and eventually exceeds its 256 MB memory limit in Kubernetes, leading to termination via out-of-memory errors.

Go's performance deteriorates significantly under increasing load, primarily due to rising latency and memory consumption, ultimately leading to its failure.

"by 33,000 requests per second it became clear that goling could not compete in terms of latency with other applications"

Rust and Zig's Performance Throughput [04:10]

  • Rust's memory usage eventually reaches and overtakes Zig's.
  • At around 98,000 requests per second, Rust begins to degrade, unable to handle the same number of requests as Zig.
  • Rust's latency increases, and it starts returning errors, causing its availability to decrease due to timeouts.
  • For throughput calculations, only requests completing with successful status codes are counted, explaining a slight drop in the request count for Rust.

Both Rust and Zig maintain strong performance for a considerable load, but Rust eventually shows signs of degradation at higher request volumes due to increased latency and errors.

"at around 98,000 requests per second rust starts to degrade"

Final Throughput and Degradation Points [04:55]

  • Zig demonstrates the highest maximum throughput, processing approximately 118,000 requests per second.
  • Rust can handle 113,000 requests per second.
  • Go, on the other hand, only reaches about 70,000 requests per second.
  • Kubernetes begins to throttle the Go application, but it's already significantly behind.

Zig emerges as the top performer in terms of throughput, with Rust also showing excellent scalability, while Go lags considerably behind.

"the maximum number of requests that Zig can process is around 100 118 requests per second"

Full Test Duration Graphs [05:27]

  • Requests per second: Go is significantly below, handling around 70,000 requests per second, while Rust and Zig reach over 100,000 requests per second.
  • Latency: Rust and Zig are much closer to each other and show lower latency compared to Go.
  • CPU usage: [No specific comparative details given, but implied difference].
  • Memory usage: Many Go instances appear due to being killed multiple times. When a pod restarts, it's immediately hit with requests and killed again.
  • Availability: [No specific comparative details given, but implied difference].
  • CPU throttling: [No specific comparative details given, but implied difference].

Visualizing the entire test duration confirms the initial findings, highlighting Rust and Zig's superior handling of high request volumes and Go's instability and limitations.

"goink is way below handling around 70,000 requests per second while rust and zek reach 100,000 requests per second"

Other People Also See