~ 3 min

Perf Comparison Between Rust & Go for REST APIs

A small comparison between using Rust and Golang for simple REST APIs.

Photo by Nicolas Hoizey on Unsplash

This test is just with a small microservice with REST API using both Go (gin framework) and Rust (rocket framework).

Initial memory usage

GOLANGRUST
11.8M3.3M

First call time taken

GOLANGRUST
2ms6ms

Subsequent call times

GOLANGRUST
2ms3ms

GO small load test

Doing a small load test with POSTing data to the service resulted in these performance numbers:

hey -n 200 -c 10 -m POST -D β€œ./examples/post1.json” http://localhost:8080/posts

Summary: Total: 0.0189 secs Slowest: 0.0032 secs Fastest: 0.0001 secs Average: 0.0008 secs Requests/sec: 10590.3759

Total data: 26600 bytes Size/request: 133 bytes

Response time histogram: 0.000 [1] |β–  0.000 [68] |β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  0.001 [68] |β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  0.001 [21] |β– β– β– β– β– β– β– β– β– β– β– β–  0.001 [12] |β– β– β– β– β– β– β–  0.002 [2] |β–  0.002 [2] |β–  0.002 [6] |β– β– β– β–  0.003 [3] |β– β–  0.003 [6] |β– β– β– β–  0.003 [11] |β– β– β– β– β– β– 

Latency distribution: 10% in 0.0002 secs 25% in 0.0004 secs 50% in 0.0005 secs 75% in 0.0010 secs 90% in 0.0025 secs 95% in 0.0029 secs 99% in 0.0032 secs

Details (average, fastest, slowest): DNS+dialup: 0.0000 secs, 0.0001 secs, 0.0032 secs DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0006 secs req write: 0.0000 secs, 0.0000 secs, 0.0018 secs resp wait: 0.0007 secs, 0.0001 secs, 0.0032 secs resp read: 0.0000 secs, 0.0000 secs, 0.0007 secs

Status code distribution: [201] 200 responses

RUST small load test

hey -n 200 -c 10 -m POST -D β€œ./examples/post1.json” -T β€œapplication/json” http://localhost:8000/posts

Summary: Total: 0.1444 secs Slowest: 0.0453 secs Fastest: 0.0010 secs Average: 0.0067 secs Requests/sec: 1385.1906

Total data: 22000 bytes Size/request: 110 bytes

Response time histogram: 0.001 [1] | 0.005 [116] |β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  0.010 [51] |β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  0.014 [12] |β– β– β– β–  0.019 [5] |β– β–  0.023 [9] |β– β– β–  0.028 [3] |β–  0.032 [1] | 0.036 [0] | 0.041 [1] | 0.045 [1] |

Latency distribution: 10% in 0.0015 secs 25% in 0.0026 secs 50% in 0.0048 secs 75% in 0.0074 secs 90% in 0.0146 secs 95% in 0.0226 secs 99% in 0.0379 secs

Details (average, fastest, slowest): DNS+dialup: 0.0000 secs, 0.0010 secs, 0.0453 secs DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0010 secs req write: 0.0000 secs, 0.0000 secs, 0.0003 secs resp wait: 0.0065 secs, 0.0009 secs, 0.0451 secs resp read: 0.0001 secs, 0.0000 secs, 0.0012 secs

Status code distribution: [200] 200 responses

Conclusion

The performance is very comparable, with Go having a slight edge with faster response times. The memory usage is the only area where there is a major difference - with Go requiring more memory to host the garbage collector and other framework bits, and Rust not having that overhead.

Does the small memory overhead really matter? Probably not, since it will be stable and not play a role in the performance of the APIs.