[gev] A lightweight, fast non-blocking Golang network library based on Reactor mode
Tags: go, epoll, kqueue
Published: 2019-09-26 03:27:37

---
title: [gev] A lightweight, fast non-blocking Golang network library based on Reactor mode
published: true
description: https://github.com/Allenxuxu/gev
tags: go,epoll,kqueue
---

➡️➡️ https://github.com/Allenxuxu/gev

`gev` is a lightweight, fast non-blocking TCP network library based on Reactor mode.

## Features

- High-performance event loop based on epoll and kqueue
- Support multi-core and multi-threading
- Dynamic expansion of read and write buffers implemented by Ring Buffer
- Asynchronous read and write
- SO_REUSEPORT port reuse support

## Network model

`gev` uses only a few goroutines, one of them listens for connections and the others (work coroutines) handle read and write events of connected clients. The count of work coroutines is configurable, which is the core number of host CPUs by default.

![image](https://github.com/Allenxuxu/gev/raw/master/benchmarks/out/reactor.png)

## Performance Test

> Test environment: Ubuntu18.04 | 4 Virtual CPUs | 4.0 GiB

### Throughput Test

limit GOMAXPROCS=1（Single thread），1 work goroutine

![image](https://github.com/Allenxuxu/gev/raw/master/benchmarks/out/gev11.png)

limit GOMAXPROCS=4，4 work goroutine

![image](https://github.com/Allenxuxu/gev/raw/master/benchmarks/out/gev44.png)

### Other Test


Compared with the simple performance of similar libraries, the pressure measurement method is the same as the evio project.

- gnet
- eviop
- evio
- net (StdLib)

limit GOMAXPROCS=1，1 work goroutine

![image](https://github.com/Allenxuxu/gev/raw/master/benchmarks/out/echo-1c-1loops.png)

limit GOMAXPROCS=1，4 work goroutine

![image](https://github.com/Allenxuxu/gev/raw/master/benchmarks/out/echo-1c-4loops.png)

limit GOMAXPROCS=4，4 work goroutine

![image](https://github.com/Allenxuxu/gev/raw/master/benchmarks/out/echo-4c-4loops.png)

## Install

```bash
go get -u github.com/Allenxuxu/gev
```

## Getting start

```go
package main

import (
	"log"

	"github.com/Allenxuxu/gev"
	"github.com/Allenxuxu/gev/connection"
	"github.com/Allenxuxu/ringbuffer"
)

type example struct{}

func (s *example) OnConnect(c *connection.Connection) {
	log.Println(" OnConnect ： ", c.PeerAddr())
}

func (s *example) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte) {
	log.Println("OnMessage")
	first, end := buffer.PeekAll()
	out = first
	if len(end) > 0 {
		out = append(out, end...)
	}
	buffer.RetrieveAll()
	return
}

func (s *example) OnClose(c *connection.Connection) {
	log.Println("OnClose")
}

func main() {
	handler := new(example)

	s, err := gev.NewServer(handler,
		gev.Address(":1833"),
		gev.NumLoops(2),
		gev.ReusePort(true))
	if err != nil {
		panic(err)
	}

	s.Start()
}
```

*Handler* is an interface that programs must implement.

```go
type Handler interface {
	OnConnect(c *connection.Connection)
	OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) []byte
	OnClose(c *connection.Connection)
}

func NewServer(handler Handler, opts ...Option) (server *Server, err error) {
```

When the message arrivals, `gev` will send data within a slice back to the client by calling OnMessage.

```go
func (s *example) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte)
```

There is also a *Send* method that can be used for sending data. But *Send* puts the data to Event-Loop and invokes it to send the data rather than sending data by itself immediately.

Check out the example [Server timing push](https://github.com/Allenxuxu/gev/tree/master/example/pushmessage/main.go) for a detailed.

```go
func (c *Connection) Send(buffer []byte) error
```

*ShutdownWrite* works for reverting connected status to false and closing connection.

Check out the example [Maximum connections](https://github.com/Allenxuxu/gev/tree/master/example/maxconnection/main.go) for a detailed.

```go
func (c *Connection) ShutdownWrite() error
```

[RingBuffer](https://github.com/Allenxuxu/ringbuffer) is a dynamical expansion implementation of circular buffer.

➡️➡️ https://github.com/Allenxuxu/gev