What is the fastest host and server software to host nothing!

This is theoretical kind of question but may have real practical implications for a project I’m involved in.

The idea is to have a server that serves nothing, it just returns a blank page, in other words. No content at all. But it doesn’t return HTTP errors either, it serves a valid page of nothing.

The general idea is to have the fastest hosting, with least amount of overhead. So the question is kind of like, Apache versus nginx versus lighttpd etc etc.

What do you think the fastest server OS + software would be? Would you build a server like this on pretty standard Ubuntu, or CentOS or something else?

Again, I’ve done initial tests and already found that Apache is like 30ms slower than nginx, so the idea is to try and build a setup as fast as possible to serve nothing.

thanks

Fastest would probably be between LiteSpeed Enterprise Webserver (or it’s open source equivalent OpenLiteSpeed) and Nginx web server. Both options would be faster than Apache for static file serving which would include a blank page.

LiteSpeed and OpenLiteSpeed might be just slightly faster than Nginx as out of box default has a small file cache in memory (LS/OLS has memory buffer caching, memory mapped caching etc) while Nginx doesn’t out of the box.

1 Like

First off, forget about Apache. Apache is slow.

I was intrigued by the question so I decided to write the smallest possible webserver I could come up with in Go, which is read the request, ignore it, and respond with HTTP/1.1 200 OK. Note that this breaks the HTTP spec because it doesn’t return any Date headers or anything, but I assume that’s not really a problem? Less headers = less bytes over the wire = less time.

So here is the code

package main

import (
	"io"
	"log"
	"net"
	"os"
	"runtime"
)

func handleConnection(conn net.Conn) {
	defer conn.Close()
	b := make([]byte, 100)
	for {
		_, err := conn.Read(b)
		if err == io.EOF {
			return
		}
		if containsDoubleLnRf(b) {
			break
		}
	}
	conn.Write([]byte("HTTP/1.1 200 OK\n"))
}

func containsDoubleLnRf(b []byte) bool {
	for i := 0; i < len(b)-3; i++ {
		if b[i] == 13 && b[i+1] == 10 && b[i+2] == 13 && b[i+3] == 10 {
			return true
		}
	}
	return false
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	ln, err := net.Listen("tcp", ":8080")
	if err != nil {
		log.Printf("Error starting server: %s", err)
		os.Exit(1)
	}
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Printf("Could not accept connection: %s", err)
			continue
		}
		go handleConnection(conn)
	}
}

I have benchmarked this using ab -n 100000 -c 100 and got:

Concurrency Level:      100
Time taken for tests:   17.481 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      1600000 bytes
HTML transferred:       0 bytes
Requests per second:    5720.57 [#/sec] (mean)
Time per request:       17.481 [ms] (mean)
Time per request:       0.175 [ms] (mean, across all concurrent requests)
Transfer rate:          89.38 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    8   2.0      8      40
Processing:     1    9   2.5      9      44
Waiting:        0    7   2.4      6      41
Total:          6   17   2.3     17      50

The same thing for NGiNX serving a blank html file yielded:

Concurrency Level:      100
Time taken for tests:   21.586 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      15600000 bytes
HTML transferred:       0 bytes
Requests per second:    4632.73 [#/sec] (mean)
Time per request:       21.586 [ms] (mean)
Time per request:       0.216 [ms] (mean, across all concurrent requests)
Transfer rate:          705.77 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    9   7.9      8     229
Processing:     2   12  13.1     10     231
Waiting:        1    9  11.3      7     221
Total:         14   22  15.6     18     241

so basically my go program is about 23% faster than NGiNX :smile:

(to run the program, install go, save my code to a file, say server.go, when in the directory where server.go is stored, type go build server.go and then ./server)

3 Likes