Skip to content

Instantly share code, notes, and snippets.

@yosssi
Last active Aug 12, 2021
Embed
What would you like to do?
Go networking performance vs Nginx

1. Nginx

$ wrk -t12 -c400 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     7.71ms    3.16ms  23.05ms   69.17%
    Req/Sec     3.44k     1.98k    7.80k    58.22%
  63697 requests in 2.00s, 17.86MB read
  Socket errors: connect 155, read 47, write 0, timeout 66
Requests/sec:  31780.82
Transfer/sec:      8.91MB

2. Go with an empty response

main.go

package main

import (
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

	})
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
$ GOMAXPROCS=2 go run main.go
$ wrk -t12 -c400 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.79ms  492.55us   7.85ms   76.02%
    Req/Sec     6.63k     2.47k   13.10k    60.47%
  124846 requests in 2.00s, 13.81MB read
  Socket errors: connect 155, read 50, write 0, timeout 66
Requests/sec:  62314.54
Transfer/sec:      6.89MB

3. Go with a simple response

main.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Hello")
	})
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
$ GOMAXPROCS=2 go run main.go
$ wrk -t12 -c400 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.79ms  492.55us   7.85ms   76.02%
    Req/Sec     6.63k     2.47k   13.10k    60.47%
  124846 requests in 2.00s, 13.81MB read
  Socket errors: connect 155, read 50, write 0, timeout 66
Requests/sec:  62314.54
Transfer/sec:      6.89MB
mac:~ yoshidakeiji$ wrk -t12 -c400 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.87ms  725.83us  13.10ms   84.56%
    Req/Sec     6.50k     3.06k   23.70k    60.89%
  121878 requests in 2.00s, 14.06MB read
  Socket errors: connect 155, read 54, write 0, timeout 66
Requests/sec:  60837.67
Transfer/sec:      7.02MB

4. Go with a file server

main.go

package main

import (
	"log"
	"net/http"
)

func main() {
	http.Handle("/", http.FileServer(http.Dir("/Users/yoshidakeiji/www")))
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
$ GOMAXPROCS=2 go run main.go
$ wrk -t12 -c400 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    14.86ms    1.52ms  19.52ms   74.31%
    Req/Sec     1.65k   795.40     2.53k    69.16%
  32254 requests in 2.00s, 7.47MB read
  Socket errors: connect 155, read 0, write 0, timeout 66
Requests/sec:  16088.43
Transfer/sec:      3.73MB

5. Go with a cached file server

main.go

package main

import (
	"log"
	"net/http"

	"github.com/yosssi/go-fileserver"
)

func main() {
	fs := fileserver.New(fileserver.Options{})
	http.Handle("/", fs.Serve(http.Dir("/Users/yoshidakeiji/www")))
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
$ GOMAXPROCS=2 go run main.go
$ wrk -t12 -c400 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    13.55ms    2.76ms  27.83ms   75.61%
    Req/Sec     2.19k   393.78     3.04k    57.03%
  51146 requests in 2.00s, 8.93MB read
  Socket errors: connect 0, read 190, write 0, timeout 0
Requests/sec:  25581.43
Transfer/sec:      4.46MB

6. Go with a cached file server which calls io.Copy instead of http.ServeContent

main.go

package main

import (
	"log"
	"net/http"

	"github.com/yosssi/go-fileserver"
)

func main() {
	fs := fileserver.New(fileserver.Options{})
	http.Handle("/", fs.Serve(http.Dir("/Users/yoshidakeiji/www")))
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
$ GOMAXPROCS=2 go run main.go
$ wrk -t12 -c400 -d2s http://127.0.0.1:8080
Running 2s test @ http://127.0.0.1:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.01ms  641.48us   9.39ms   79.67%
    Req/Sec     5.27k     1.48k    9.30k    60.07%
  118962 requests in 2.00s, 13.17MB read
  Socket errors: connect 0, read 125, write 0, timeout 0
Requests/sec:  59517.07
Transfer/sec:      6.59MB
@Azareal

This comment has been minimized.

Copy link

@Azareal Azareal commented Dec 3, 2016

The last two code examples look identical o.o

@kazzkiq

This comment has been minimized.

Copy link

@kazzkiq kazzkiq commented Feb 11, 2017

Would be interesting to see how well Go behaves when using fasthttp instead of net/http.

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Feb 15, 2018

Those results are pretty impressive. Tempts me to run both my frontend and backend using the same Go server just to simplify deployment and reduce running processes. I know its not really a huge margin, but for what I am doing this may just make sense.

@ChandraNarreddy

This comment has been minimized.

Copy link

@ChandraNarreddy ChandraNarreddy commented Feb 20, 2018

This is quite impressive. What is NGINX version and configuration, is it serving static content?

@larytet

This comment has been minimized.

Copy link

@larytet larytet commented Jun 7, 2018

In my tests switch to fasthttp gives x1.5 to x2 boost

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Nov 23, 2018

@dalovar

This comment has been minimized.

Copy link

@dalovar dalovar commented Nov 24, 2018

see https://github.com/tidwall/evio

Interesting. Is evio faster than nginx and production ready? Does it have any built-in protection against DDoS attacks like nginx

Great contribution

@correiaa

This comment has been minimized.

Copy link

@correiaa correiaa commented Jun 25, 2021

I'll update everyone here. I am about to give this a GO :). I am at my limit with Nginx and will be building my apps Rest api with this. Interested to see how hard it can get hit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment