Skip to content

Instantly share code, notes, and snippets.

@methane
Last active December 12, 2015 04:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save methane/4715414 to your computer and use it in GitHub Desktop.
Save methane/4715414 to your computer and use it in GitHub Desktop.

Other servers on same machine.

node.js 0.8.18

code

var http = require('http'); 
http.createServer(function (req, res) { 
    res.writeHead(200, {'Content-Type': 'text/plain'}); 
    res.end('hello, world!\n'); 
}).listen(8080, "127.0.0.1"); 
console.log('Server running at http://127.0.0.1:8080/');

result

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8080/
weighttp - a lightweight and simple webserver benchmarking tool

finished in 9 sec, 82 millisec and 931 microsec, 11009 req/s, 1698 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 15800000 bytes total, 13400000 bytes http, 2400000 bytes data

meinheld

meinheld is world fastest Python web server.

code

import meinheld
from multiprocessing import Process
import signal

workers = []

def hello_world(environ, start_response):
    status = '200 OK'
    res = "Hello world!"
    response_headers = [('Content-type','text/plain'),('Content-Length', '12')]
    start_response(status, response_headers)
    return [res]

def run(app, i):
    meinheld.run(app)

def kill_all(sig, st):
    for w in workers:
        w.terminate()

def start(num=2):
    for i in range(num):
        p = Process(name="worker-%d" % i, target=run, args=(hello_world,i))
        workers.append(p)
        p.start()

signal.signal(signal.SIGTERM, kill_all)
meinheld.set_keepalive(10)
meinheld.set_access_logger(None)
meinheld.set_error_logger(None)
meinheld.listen(("0.0.0.0", 8000))
start()

result

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8000/
weighttp - a lightweight and simple webserver benchmarking tool

finished in 3 sec, 174 millisec and 522 microsec, 31500 req/s, 4983 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 16200000 bytes total, 15000000 bytes http, 1200000 bytes data

unset GOMAXPROCS

normal

$ curl -v http://127.0.0.1:8000/
* About to connect() to 127.0.0.1 port 8000 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.26.0
> Host: 127.0.0.1:8000
> Accept: */*
> 
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Content-Length: 13
< Content-Type: text/plain; charset=utf-8
< Date: Tue, 05 Feb 2013 16:01:11 GMT
< 
Hello World!
* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8000/
weighttp - a lightweight and simple webserver benchmarking tool

finished in 7 sec, 442 millisec and 178 microsec, 13436 req/s, 1705 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 13000000 bytes total, 11700000 bytes http, 1300000 bytes data

with date cache

$ curl -v http://127.0.0.1:8000/
* About to connect() to 127.0.0.1 port 8000 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.26.0
> Host: 127.0.0.1:8000
> Accept: */*
> 
* additional stuff not fine transfer.c:1037: 0 0
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Content-Length: 13
< Content-Type: text/plain; charset=utf-8
< Date: Tue, 05 Feb 2013 16:01:48 GMT
< 
Hello World!
* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8000/
weighttp - a lightweight and simple webserver benchmarking tool

finished in 6 sec, 851 millisec and 292 microsec, 14595 req/s, 1852 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 13000000 bytes total, 11700000 bytes http, 1300000 bytes data

with date cache and read/writeNB patch

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8000/
weighttp - a lightweight and simple webserver benchmarking tool

finished in 6 sec, 280 millisec and 128 microsec, 15923 req/s, 2021 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 13000000 bytes total, 11700000 bytes http, 1300000 bytes data

GOMAXPROC=4

normal hello

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8000/                                                                                                 
weighttp - a lightweight and simple webserver benchmarking tool

finished in 5 sec, 155 millisec and 19 microsec, 19398 req/s, 2462 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 13000000 bytes total, 11700000 bytes http, 1300000 bytes data

with date cache

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8000/
weighttp - a lightweight and simple webserver benchmarking tool

finished in 4 sec, 917 millisec and 32 microsec, 20337 req/s, 2581 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 13000000 bytes total, 11700000 bytes http, 1300000 bytes data

with date cache and read/writeNB patch

$ ~/local/bin/weighttp -n100000 -t4 -c16 -k http://127.0.0.1:8000/
weighttp - a lightweight and simple webserver benchmarking tool

finished in 4 sec, 12 millisec and 384 microsec, 24922 req/s, 3164 kbyte/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 13000000 bytes total, 11700000 bytes http, 1300000 bytes data
package main
import (
"io"
"net/http"
"strconv"
"time"
)
const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
var formattedDate string = ""
func getDate() (date string) {
date = formattedDate
if date == "" {
date = time.Now().UTC().Format(TimeFormat)
formattedDate = date
go func() {
<-time.After(time.Second)
formattedDate = ""
}()
}
return
}
func HelloServer(w http.ResponseWriter, req *http.Request) {
msg := "Hello World!\n";
header := w.Header()
header.Add("Content-Length", strconv.Itoa(len(msg)))
header.Add("Content-Type", "text/plain; charset=utf-8")
header.Add("Date", getDate())
io.WriteString(w, msg)
}
func main() {
http.HandleFunc("/", HelloServer)
http.ListenAndServe(":8000", nil)
}
package main
import (
"io"
"net/http"
"strconv"
)
func HelloServer(w http.ResponseWriter, req *http.Request) {
msg := "Hello World!\n";
w.Header().Add("Content-Length", strconv.Itoa(len(msg)))
io.WriteString(w, msg)
}
func main() {
http.HandleFunc("/", HelloServer)
http.ListenAndServe(":8000", nil)
}
$ uname -a
Linux sag14 3.2.0-4-amd64 #1 SMP Debian 3.2.35-2 x86_64 GNU/Linux
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz
stepping : 2
microcode : 0x56
cpu MHz : 1861.677
cache size : 2048 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts nopl aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm dtherm tpr_shadow
bogomips : 3723.35
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
(more 1 cpu)
diff -r 36d247dd8ee5 src/pkg/net/fd_unix.go
--- a/src/pkg/net/fd_unix.go Tue Feb 05 07:06:00 2013 -0500
+++ b/src/pkg/net/fd_unix.go Tue Feb 05 23:05:59 2013 +0900
@@ -424,7 +424,7 @@
err = errTimeout
break
}
- n, err = syscall.Read(int(fd.sysfd), p)
+ n, err = syscall.ReadNB(int(fd.sysfd), p)
if err != nil {
n = 0
if err == syscall.EAGAIN {
@@ -522,7 +522,7 @@
break
}
var n int
- n, err = syscall.Write(int(fd.sysfd), p[nn:])
+ n, err = syscall.WriteNB(int(fd.sysfd), p[nn:])
if n > 0 {
nn += n
}
diff -r 36d247dd8ee5 src/pkg/syscall/syscall_linux.go
--- a/src/pkg/syscall/syscall_linux.go Tue Feb 05 07:06:00 2013 -0500
+++ b/src/pkg/syscall/syscall_linux.go Tue Feb 05 23:05:59 2013 +0900
@@ -17,6 +17,20 @@
* Wrapped
*/
+func ReadNB(fd int, p []byte) (n int, err error) {
+ n, err = readNB(fd, p)
+ if raceenabled && err == nil {
+ raceAcquire(unsafe.Pointer(&ioSync))
+ }
+ return
+}
+func WriteNB(fd int, p []byte) (n int, err error) {
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ return writeNB(fd, p)
+}
+
//sys open(path string, mode int, perm uint32) (fd int, err error)
func Open(path string, mode int, perm uint32) (fd int, err error) {
return open(path, mode|O_LARGEFILE, perm)
@@ -915,6 +929,7 @@
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
//sys read(fd int, p []byte) (n int, err error)
+//sysnb readNB(fd int, p []byte) (n int, err error) = SYS_READ
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Removexattr(path string, attr string) (err error)
//sys Rename(oldpath string, newpath string) (err error)
@@ -942,6 +957,7 @@
//sys Ustat(dev int, ubuf *Ustat_t) (err error)
//sys Utime(path string, buf *Utimbuf) (err error)
//sys write(fd int, p []byte) (n int, err error)
+//sysnb writeNB(fd int, p []byte) (n int, err error) = SYS_WRITE
//sys exitThread(code int) (err error) = SYS_EXIT
//sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ
//sys writelen(fd int, p *byte, np int) (n int, err error) = SYS_WRITE
diff -r 36d247dd8ee5 src/pkg/syscall/zsyscall_linux_amd64.go
--- a/src/pkg/syscall/zsyscall_linux_amd64.go Tue Feb 05 07:06:00 2013 -0500
+++ b/src/pkg/syscall/zsyscall_linux_amd64.go Tue Feb 05 23:05:59 2013 +0900
@@ -824,6 +824,23 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func readNB(fd int, p []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := RawSyscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ n = int(r0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func Readlink(path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1204,6 +1221,23 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func writeNB(fd int, p []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := RawSyscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ n = int(r0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func exitThread(code int) (err error) {
_, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
if e1 != 0 {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment