Thank you for visiting!
My little window on internet allowing me to share several of my passions
Categories:
- FreeBSD
- OpenBSD
- VM
- High Availability
- vdcron
- My Sysupgrade
- FreeBSD
- Nas
- DragonflyBSD
- fapws
- Alpine Linux
- Openbox
- Desktop
- Security
- nvim
- yabitrot
- nmctl
- Tint2
- Firewall
- VPN
- Project Management
- Hifi
- Alarm
Most Popular Articles:
Last Articles:

Fapws versus GO
Posted on 2019-02-10 21:17:00 from Vincent in OpenBSD fapws
The context of the comparison
As already post on this blog, I'm comparing Fapws to other web server who could be simple to use and have a small memory foot print.
This time, I'm comparing Fapws with a Web server written in Go.
Since the context of Go, I would expect much quicker results than Fapws. But, for the memory foot print, I'm interested to see which tool is the smallest.
The test methodology
I'm doing all test on the same machine. A Dell 5450 running OpenBSD 6.4.
The test will consist of ApacheBenchmark execution with different concurrent requests.
The Go program will be executed with the command: go run hello.go
For Fapws, we will do: python2.7 hello.py
The Fapws code
I'm using the hello.py script present in the sample folder of Fapws3.
Since the amazing results, I've also compared both solutions when presenting static files.
#!/usr/bin/env python
import fapws._evwsgi as evwsgi
import fapws
import fapws.base
import fapws.contrib
import fapws.contrib.views
import sys
sys.setcheckinterval(100000) # since we don't use threads, internal checks are no more required
import views
def start():
evwsgi.start("0.0.0.0", "8085")
evwsgi.set_base_module(fapws.base)
def index(environ, start_response):
print "GET:", environ['fapws.uri']
return views.index(environ, start_response)
def mystatic(environ, start_response):
s=fapws.contrib.views.Staticfile("static/")
return s(environ, start_response)
evwsgi.wsgi_cb(("/static/",mystatic))
evwsgi.wsgi_cb(("/", index))
#evhttp.gen_http_cb(generic)
evwsgi.set_debug(0)
print "libev ABI version:%i.%i" % evwsgi.libev_version()
evwsgi.run()
if __name__=="__main__":
start()
Go web server
For Go I'm using the following script which is a collection of samples I've found on internet
package main
import (
"fmt"
"log"
"net/http"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!") // send data to client side
}
func staticFile(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "page") // send data to client side
}
func main() {
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
http.HandleFunc("/", sayhelloName) // set router
err := http.ListenAndServe(":9090", nil) // set listen port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Results
Hello world
The first test is to return the simple "Hello World".
In both cases, I've asked ApacheBenchmark to perform 100.000 requests.
For 100.000 requests, the results are:
concurrency | Go | Fapws |
---|---|---|
10 | 2834 | 3582 |
500 | 3606 | 3341 |
1000 | 2393 | 2643 |
The memory values are:
Go | Fapws | |
VSZ | 113704 | 5880 |
RSS | 11500 | 12588 |
Those results are un-expected. It means that Python with bunch of C code has the same performance of Go.
Let's see what will be the results with a small static file ans with a much bigger static file. This is a much representative test.
Small static file
The small file will be a file of 9,7kB. This is typically a css or an icon we can often see on web sites.
Still for 100.000 request, the results are:
concurrency | Go | Fapws |
---|---|---|
10 | 2266 | 3587 |
500 | 2023 | 3374 |
1000 | 2292 | 3012 |
The memory values are:
Go | Fapws | |
VSZ | 112660 | 7480 |
RSS | 16704 | 14184 |
Those results are still amazing. Fapws is in fact better for such use case.
Big static file
The file will be a file of 2.1MB. This is typically a picture file we can see on web sites.
Still for 100.000 request, the results are:
concurrency | Go | Fapws |
---|---|---|
10 | 75 | 132 |
500 | 99 | 108 |
1000 | na | 104 |
For a concurrency of 1000, Go stopped working by saying: "too many open files, retrying in 5 ms"
The memory values are:
Go | Fapws | |
VSZ | 113704 | 7120 |
RSS | 13724 | 13368 |
Those results are still amazing. Fapws is in fact better for such use case.
Conclusion
Surprisingly, Go is not better than Fapws. Moreover the memory foot print is quite bad.
But this last element could be improved. Indeed, after having spent some time this year at the Fosdem, I saw the following presentation. A novice like me in Go, will understand that memory could be drastically reduced, but need a certain expertise.
I think that the remaining test is to compare Fapws with Rust.