Browse Source

[Go]goev is a high-performance, lightweight, i/o event-driven network framework in Go. (#8311)

* add goev

* del file

* fix bug

* x

* goev ok

* goev ok

* modify version to v0.0.1

* add go.sum

* 1. add http header parse, 2. modify reactor params

* modify evpoll num

* update to stripped

---------

Co-authored-by: nobodynobodyee <[email protected]>
shaovie 2 years ago
parent
commit
b968ea38ae

+ 9 - 0
frameworks/Go/goev/README.md

@@ -0,0 +1,9 @@
+# [goev](https://github.com/shaovie/goev) (GoLang) Benchmarking Test
+
+This is the go portion of a [benchmarking test suite](https://www.techempower.com/benchmarks/) comparing a variety of web development platforms.
+
+"goev is a high-performance, lightweight, i/o event-driven network framework in Go."
+
+## Test URLs
+
+    http://localhost:8080/plaintext

+ 23 - 0
frameworks/Go/goev/benchmark_config.json

@@ -0,0 +1,23 @@
+{
+  "framework": "goev",
+  "tests": [{
+    "default": {
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Stripped",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "goev",
+      "language": "Go",
+      "flavor": "None",
+      "orm": "Raw",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Goev",
+      "notes": "",
+      "versus": "go"
+    }
+  }]
+}

+ 14 - 0
frameworks/Go/goev/config.toml

@@ -0,0 +1,14 @@
+[framework]
+name = "goev"
+
+[main]
+urls.plaintext = "/plaintext"
+approach = "Stripped"
+classification = "Platform"
+database = "None"
+database_os = "Linux"
+os = "Linux"
+orm = "Raw"
+platform = "None"
+webserver = "None"
+versus = "go"

+ 13 - 0
frameworks/Go/goev/goev.dockerfile

@@ -0,0 +1,13 @@
+FROM docker.io/golang:1.20
+
+WORKDIR /goev
+
+COPY ./src /goev
+
+RUN go mod download
+
+RUN GOAMD64=v3 go build -o ./app main.go
+
+EXPOSE 8080
+
+CMD ./app

+ 7 - 0
frameworks/Go/goev/src/go.mod

@@ -0,0 +1,7 @@
+module goev
+
+go 1.19
+
+require github.com/shaovie/goev v0.0.1
+
+require golang.org/x/sys v0.10.0 // indirect

+ 4 - 0
frameworks/Go/goev/src/go.sum

@@ -0,0 +1,4 @@
+github.com/shaovie/goev v0.0.1 h1:mY176fZsNViEPpVXPdXlrJAAXRLRwV3zlr46iKo7sZw=
+github.com/shaovie/goev v0.0.1/go.mod h1:aa9aX72GpBSJAIkbhbFns3PTkhEdRVY5cCkpuZr27FE=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

+ 131 - 0
frameworks/Go/goev/src/main.go

@@ -0,0 +1,131 @@
+package main
+
+import (
+	"fmt"
+    "time"
+    "bytes"
+    "runtime"
+	"syscall"
+	"sync/atomic"
+
+	"github.com/shaovie/goev"
+	"github.com/shaovie/goev/netfd"
+)
+
+var (
+    httpRespHeader []byte
+    httpRespContentLength []byte
+	ticker *time.Ticker
+    liveDate atomic.Value
+)
+
+const httpHeaderS = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nServer: goev\r\nContent-Type: text/plain\r\nDate: "
+const contentLengthS = "\r\nContent-Length: 13\r\n\r\nHello, World!"
+
+type Http struct {
+	goev.Event
+}
+
+func (h *Http) OnOpen(fd int, now int64) bool {
+    netfd.SetNoDelay(fd, 1)
+    // AddEvHandler 尽量放在最后, (OnOpen 和ORead可能不在一个线程)
+	if err := h.GetReactor().AddEvHandler(h, fd, goev.EV_IN); err != nil {
+		return false
+	}
+	return true
+}
+func (h *Http) OnRead(fd int, evPollSharedBuff []byte, now int64) bool {
+    buf := evPollSharedBuff[:]
+	readN := 0
+	for {
+		if readN >= cap(buf) { // alloc new buff to read
+            readN = 1 // ^_^
+		}
+		n, err := netfd.Read(fd, buf[readN:])
+		if err != nil {
+			if err == syscall.EAGAIN { // epoll ET mode
+				break
+			}
+			return false
+		}
+		if n > 0 { // n > 0
+			readN += n
+            break // ^_^
+		} else { // n == 0 connection closed,  will not < 0
+			if readN == 0 {
+				// fmt.Println("peer closed. ", n)
+			}
+			return false
+		}
+	}
+	if idx := bytes.Index(buf, []byte{'\r', '\n', '\r', '\n'}); idx == -1 {
+        return false
+    }
+    buf = buf[:0]
+    buf = append(buf, httpRespHeader...)
+    buf = append(buf, []byte(liveDate.Load().(string))...)
+    buf = append(buf, httpRespContentLength...)
+	netfd.Write(fd, buf) // Connection: close
+	return true
+}
+func (h *Http) OnClose(fd int) {
+	netfd.Close(fd)
+}
+
+func updateLiveSecond() {
+	for {
+		select {
+        case now := <-ticker.C:
+			liveDate.Store(now.Format("Mon, 02 Jan 2006 15:04:05 GMT"))
+		}
+	}
+}
+
+func main() {
+	fmt.Println("hello boy")
+    runtime.GOMAXPROCS(runtime.NumCPU() * 2)
+
+    liveDate.Store(time.Now().Format("Mon, 02 Jan 2006 15:04:05 GMT"))
+    ticker = time.NewTicker(time.Millisecond * 1000)
+
+    httpRespHeader = []byte(httpHeaderS)
+    httpRespContentLength = []byte(contentLengthS)
+
+	forAcceptReactor, err := goev.NewReactor(
+		goev.EvDataArrSize(20480), // default val
+		goev.EvPollNum(1),
+		goev.EvReadyNum(8), // only accept fd
+		goev.NoTimer(true),
+	)
+	if err != nil {
+		panic(err.Error())
+	}
+	forNewFdReactor, err := goev.NewReactor(
+		goev.EvDataArrSize(20480), // default val
+		goev.EvPollNum(runtime.NumCPU()*2-1),
+		goev.EvReadyNum(512), // auto calc
+		goev.NoTimer(true),
+	)
+	if err != nil {
+		panic(err.Error())
+	}
+	//= http
+	_, err = goev.NewAcceptor(forAcceptReactor, forNewFdReactor, func() goev.EvHandler { return new(Http) },
+		":8080",
+		goev.ListenBacklog(512),
+		//goev.SockRcvBufSize(16*1024), // 短链接, 不需要很大的缓冲区
+	)
+	if err != nil {
+		panic(err.Error())
+	}
+
+    go updateLiveSecond()
+	go func() {
+		if err = forAcceptReactor.Run(); err != nil {
+			panic(err.Error())
+		}
+	}()
+	if err = forNewFdReactor.Run(); err != nil {
+		panic(err.Error())
+	}
+}