4
votes

I'm trying to benchmark a simple 'hello world' HTTP server in go. I've made 2 tests:

  1. Using amazon ec2 - m3.medium instance
  2. Using amazon elastic beanstalk - also with m3.medium single instance

On the first setup, I could get up to 18k req/sec. On the second, 1.6k req/sec.

Source code:(from: https://golang.org/doc/articles/wiki/)

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Is there any explanation for such a huge performance difference?

PS: benchmark tool: https://github.com/wg/wrk
Also, one important thing is: Elastic beanstalk always adds nginx as a reverse proxy for it's applications(and for Go apps I was not able to remove it) On the first setup, there was no nginx at all.

1
Another difference is that your EB setup most likely involved an Elastic Load Balancer. The "elastic" part means that it's supposed to scale with traffic, but I've seen instances where a sudden burst of traffic (such as with a performance test) can cause issues until the ELB catches up. - Brian
Agree with Brian. To test hypotheses, you could compare 1) m3.medium behind an ELB, 2) m3.medium + ELB after, say, 15 minutes of sustained load, 3) m3.medium + ELB + nginx. - twotwotwo
My EB setup is single instance but good point - rcmgleite
Were the EBS disk volumes of the same type and size? - Mark B
If your test generated any disk I/O at all, such as writing to log files, then the speed of the EBS disk volumes would affect the requests/second that the server can handle. It sounds like you used identical volumes though. My guess is the Nginx settings in the EB environment were causing a bottleneck. Maybe just the additional logging enabled by default on EB is causing the bottleneck. - Mark B

1 Answers

2
votes

The short answer: You were not measuring the same thing. On your own instance, you measured the native Go Webserver whereas on Beanstalk you measured Nginx with a native Go Web server behind.

The long answer:

If you are using AWS Elastic Beanstalk in a Single Instance Configuration, you receive the exact same instance as if you are using EC2. You do not receive an Elastic Load Balancer in front of a single instance Beanstalk environment.

If you are using the Beanstalk, you will get a predeployed nginx (as you already stated). Nginx has a significant impact on the performance, especially in a single CPU configuration as with the m3.medium instance.

The performance impact you measured were by no means caused directly by Beanstalk, but by your deployment configuration. To avoid this decrease in performance, you may choose to use the native Go Web server.


To support my reasoning I run some tests to demonstrate the performance. The following numbers were generated by running wrk on an EC2 m3.medium instance in the same datacenter as the workload was located.

I installed the same Go application on Beanstalk as on the native EC2 instance, and I installed a NGINX server with the same configuration as Beanstalk is using.

./wrk http://<server>/ --duration 20s --connections 300

Beanstalk m3.medium instance DIRECT:  9230.52 Requests / sec
Beanstalk m3.medium instance NGINX:   1502.14 Requests / sec
EC2 m3.medium instance DIRECT:       13649.46 Requests / sec
EC2 m3.medium instance NGINX:         2489.78 Requests / sec