diff --git a/README.md b/README.md index 8ab4842..222c2ad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
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