diff --git a/README.md b/README.md index 8ab4842..222c2ad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

evio
Build Status diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore new file mode 100644 index 0000000..c484fb4 --- /dev/null +++ b/benchmarks/.gitignore @@ -0,0 +1,2 @@ +bin/ +socket diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 0000000..d08f54c --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,8 @@ +## evio benchmark tools + +Required: + +- [wrk](https://github.com/wg/wrk) for HTTP +- [tcpkali](https://github.com/machinezone/tcpkali) for Echo +- [Redis](http://redis.io) for Redis + diff --git a/benchmarks/bench-echo.sh b/benchmarks/bench-echo.sh new file mode 100755 index 0000000..ec40238 --- /dev/null +++ b/benchmarks/bench-echo.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +#set -e + +echo "" +echo "--- ECHO START ---" +echo "" + +cd $(dirname "${BASH_SOURCE[0]}") +function cleanup { + echo "--- ECHO DONE ---" + kill $(jobs -rp) + wait $(jobs -rp) 2>/dev/null +} +trap cleanup EXIT + +mkdir -p bin + +$(pkill net-echo-server || printf "") +$(pkill evio-echo-server || printf "") + +function gobench { + printf "\e[96m[%s]\e[0m\n" $1 + if [ "$3" != "" ]; then + go build -o $2 $3 + fi + $2 -port $4 & + sleep 1 + echo "Sending 6 byte packets, 50 connections" + nl=$'\r\n' + tcpkali -c 50 -m "PING{$nl}" 127.0.0.1:$4 + echo "--- DONE ---" + echo "" +} + +gobench "net/echo" bin/net-echo-server net-echo-server/main.go 5001 +gobench "evio/echo" bin/evio-echo-server ../examples/echo-server/main.go 5002 diff --git a/benchmarks/bench-http.sh b/benchmarks/bench-http.sh new file mode 100755 index 0000000..00899d3 --- /dev/null +++ b/benchmarks/bench-http.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +#set -e + +echo "" +echo "--- HTTP START ---" +echo "" + +cd $(dirname "${BASH_SOURCE[0]}") +function cleanup { + echo "--- HTTP DONE ---" + kill $(jobs -rp) + wait $(jobs -rp) 2>/dev/null +} +trap cleanup EXIT + +mkdir -p bin +$(pkill net-http-server || printf "") +$(pkill fasthttp-server || printf "") +$(pkill iris-server || printf "") +$(pkill evio-http-server || printf "") + +function gobench { + printf "\e[96m[%s]\e[0m\n" $1 + if [ "$3" != "" ]; then + go build -o $2 $3 + fi + $2 -port $4 & + sleep 1 + echo "Using 4 threads, 50 connections, 10 seconds" + wrk -t4 -c50 -d10 http://127.0.0.1:$4 + echo "--- DONE ---" + echo "" +} + +gobench "net/http" bin/net-http-server net-http-server/main.go 8081 +gobench "iris" bin/iris-server iris-server/main.go 8082 +gobench "fasthttp" bin/fasthttp-server fasthttp-server/main.go 8083 +gobench "evio/http" bin/evio-http-server ../examples/http-server/main.go 8084 diff --git a/benchmarks/bench-redis.sh b/benchmarks/bench-redis.sh new file mode 100755 index 0000000..7f4ab72 --- /dev/null +++ b/benchmarks/bench-redis.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +#set -e + +echo "" +echo "--- REDIS START ---" +echo "" + + +cd $(dirname "${BASH_SOURCE[0]}") +function cleanup { + echo "--- REDIS DONE ---" + kill $(jobs -rp) + wait $(jobs -rp) 2>/dev/null +} +trap cleanup EXIT + +mkdir -p bin + +$(pkill redis-server || printf "") +$(pkill evio-redis-server || printf "") + +function gobench { + printf "\e[96m[%s]\e[0m\n" $1 + if [ "$3" != "" ]; then + go build -o $2 $3 + fi + $2 --port $4 & + sleep 1 + echo "Sending pings, 50 connections, 1 packet pipeline" + redis-benchmark -p $4 -t ping -q -P 1 + echo "Sending pings, 50 connections, 10 packet pipeline" + redis-benchmark -p $4 -t ping -q -P 10 + echo "Sending pings, 50 connections, 20 packet pipeline" + redis-benchmark -p $4 -t ping -q -P 20 + echo "--- DONE ---" + echo "" +} +gobench "real/redis" redis-server "" 6392 +gobench "evio/redis" bin/evio-redis-server ../examples/redis-server/main.go 6393 diff --git a/benchmarks/bench.sh b/benchmarks/bench.sh new file mode 100755 index 0000000..1eb81d3 --- /dev/null +++ b/benchmarks/bench.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +#set -e + +cd $(dirname "${BASH_SOURCE[0]}") + +./bench-http.sh +./bench-echo.sh +./bench-redis.sh diff --git a/benchmarks/fasthttp-server/main.go b/benchmarks/fasthttp-server/main.go new file mode 100644 index 0000000..247b8c4 --- /dev/null +++ b/benchmarks/fasthttp-server/main.go @@ -0,0 +1,32 @@ +// Copyright 2017 Joshua J Baker. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "log" + + "github.com/valyala/fasthttp" +) + +var res string + +func main() { + var port int + flag.IntVar(&port, "port", 8080, "server port") + flag.Parse() + go log.Printf("http server started on port %d", port) + err := fasthttp.ListenAndServe(fmt.Sprintf(":%d", port), + func(c *fasthttp.RequestCtx) { + _, werr := c.WriteString("Hello World!\r\n") + if werr != nil { + log.Fatal(werr) + } + }) + if err != nil { + log.Fatal(err) + } +} diff --git a/benchmarks/iris-server/main.go b/benchmarks/iris-server/main.go new file mode 100644 index 0000000..b83a87d --- /dev/null +++ b/benchmarks/iris-server/main.go @@ -0,0 +1,31 @@ +// Copyright 2017 Joshua J Baker. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "log" + + "github.com/kataras/iris" +) + +var res string + +func main() { + var port int + flag.IntVar(&port, "port", 8080, "server port") + flag.Parse() + go log.Printf("http server started on port %d", port) + app := iris.New() + app.Get("/", func(ctx iris.Context) { + ctx.WriteString("Hello World!\r\n") + }) + err := app.Run(iris.Addr(fmt.Sprintf(":%d", port))) + if err != nil { + log.Fatal(err) + } + +} diff --git a/benchmarks/net-echo-server/main.go b/benchmarks/net-echo-server/main.go new file mode 100644 index 0000000..7240deb --- /dev/null +++ b/benchmarks/net-echo-server/main.go @@ -0,0 +1,47 @@ +// Copyright 2017 Joshua J Baker. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "log" + "net" +) + +func main() { + var port int + flag.IntVar(&port, "port", 5000, "server port") + flag.Parse() + ln, err := net.Listen("tcp4", fmt.Sprintf(":%d", port)) + if err != nil { + log.Fatal(err) + } + defer ln.Close() + log.Printf("echo server started on port %d", port) + var id int + for { + conn, err := ln.Accept() + if err != nil { + log.Fatal(err) + } + id++ + go func(id int, conn net.Conn) { + defer func() { + //log.Printf("closed: %d", id) + conn.Close() + }() + //log.Printf("opened: %d: %s", id, conn.RemoteAddr().String()) + var packet [0xFFF]byte + for { + n, err := conn.Read(packet[:]) + if err != nil { + return + } + conn.Write(packet[:n]) + } + }(id, conn) + } +} diff --git a/benchmarks/net-http-server/main.go b/benchmarks/net-http-server/main.go new file mode 100644 index 0000000..6a544c4 --- /dev/null +++ b/benchmarks/net-http-server/main.go @@ -0,0 +1,36 @@ +// Copyright 2017 Joshua J Baker. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "log" + "net/http" + "strings" +) + +var res string + +func main() { + var port int + var aaaa bool + flag.IntVar(&port, "port", 8080, "server port") + flag.BoolVar(&aaaa, "aaaa", false, "aaaaa....") + flag.Parse() + if aaaa { + res = strings.Repeat("a", 1024) + } else { + res = "Hello World!\r\n" + } + log.Printf("http server started on port %d", port) + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(res)) + }) + err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) + if err != nil { + log.Fatal(err) + } +} diff --git a/evio_unix.go b/evio_unix.go index 83327cd..1ffdd91 100644 --- a/evio_unix.go +++ b/evio_unix.go @@ -323,7 +323,7 @@ func serve(events Events, lns []*listener) error { c.outpos += n if len(c.outbuf)-c.outpos == 0 { c.outpos = 0 - c.outbuf = nil + c.outbuf = c.outbuf[:0] } } if c.action == Shutdown { diff --git a/examples/echo-server/main.go b/examples/echo-server/main.go index 1329f84..6c1d7a2 100644 --- a/examples/echo-server/main.go +++ b/examples/echo-server/main.go @@ -5,6 +5,8 @@ package main import ( + "flag" + "fmt" "log" "net" @@ -12,17 +14,26 @@ import ( ) func main() { - var events evio.Events + var port int + flag.IntVar(&port, "port", 5000, "server port") + flag.Parse() + var events evio.Events events.Serving = func(wake func(id int) bool, addrs []net.Addr) (action evio.Action) { - log.Print("echo server started on port 5000") + log.Printf("echo server started on port %d", port) + return + } + events.Opened = func(id int, addr evio.Addr) (out []byte, opts evio.Options, action evio.Action) { + //log.Printf("opened: %d: %s", id, addr.Remote.String()) + return + } + events.Closed = func(id int, err error) (action evio.Action) { + //log.Printf("closed: %d", id) return } - events.Data = func(id int, in []byte) (out []byte, action evio.Action) { out = in return } - - log.Fatal(evio.Serve(events, "tcp://0.0.0.0:5000")) + log.Fatal(evio.Serve(events, fmt.Sprintf("tcp://:%d", port))) } diff --git a/examples/http-server/main.go b/examples/http-server/main.go index 5a13465..6e23155 100644 --- a/examples/http-server/main.go +++ b/examples/http-server/main.go @@ -63,28 +63,18 @@ func main() { events.Opened = func(id int, addr evio.Addr) (out []byte, opts evio.Options, action evio.Action) { conns[id] = &conn{addr: addr} - log.Printf("%s: opened", addr.Remote.String()) + //log.Printf("opened: %d: %s: %s", id, addr.Local.String(), addr.Remote.String()) return } events.Closed = func(id int, err error) (action evio.Action) { - c := conns[id] - log.Printf("%s: closed: %v", c.addr.Remote.String(), err) + // c := conns[id] + // log.Printf("closed: %d: %s: %s", id, c.addr.Local.String(), c.addr.Remote.String()) delete(conns, id) return } events.Data = func(id int, in []byte) (out []byte, action evio.Action) { - // out = []byte(`HTTP/1.1 200 OK - // Server: evio - // Date: Thu, 02 Nov 2017 15:48:57 GMT - // Content-Type: text/plain; charset=utf-8 - // Content-Length: 1024 - - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`) - - // return - if in == nil { return } @@ -112,7 +102,7 @@ func main() { return } // We at least want the single http address. - addrs := []string{fmt.Sprintf("tcp://localhost:%d", port)} + addrs := []string{fmt.Sprintf("tcp://:%d", port)} if tlspem != "" { // load the cert and key pair from the concat'd pem file. cer, err := tls.LoadX509KeyPair(tlspem, tlspem) @@ -121,7 +111,7 @@ func main() { } config := &tls.Config{Certificates: []tls.Certificate{cer}} // Update the address list to include https. - addrs = append(addrs, fmt.Sprintf("tcp://localhost:%d", tlsport)) + addrs = append(addrs, fmt.Sprintf("tcp://:%d", tlsport)) // TLS translate the events events = evio.Translate(events, diff --git a/examples/redis-server/main.go b/examples/redis-server/main.go index 728db5f..ac4b8db 100644 --- a/examples/redis-server/main.go +++ b/examples/redis-server/main.go @@ -130,7 +130,7 @@ func main() { c.is.End(data) return } - addrs := []string{fmt.Sprintf("tcp://0.0.0.0:%d", port)} + addrs := []string{fmt.Sprintf("tcp://:%d", port)} if unixsocket != "" { addrs = append(addrs, fmt.Sprintf("unix://%s", unixsocket)) } diff --git a/resources/logo.png b/logo.png similarity index 100% rename from resources/logo.png rename to logo.png