add io_uring support

This commit is contained in:
smallnest
2023-07-09 15:24:09 +08:00
parent 942816525d
commit 2dbf046a3a
7 changed files with 139 additions and 5 deletions
+6 -5
View File
@@ -18,11 +18,12 @@ import (
type ConnFactoryFn func(c *Client, network, address string) (net.Conn, error)
var ConnFactories = map[string]ConnFactoryFn{
"http": newDirectHTTPConn,
"kcp": newDirectKCPConn,
"quic": newDirectQuicConn,
"unix": newDirectConn,
"memu": newMemuConn,
"http": newDirectHTTPConn,
"kcp": newDirectKCPConn,
"quic": newDirectQuicConn,
"unix": newDirectConn,
"memu": newMemuConn,
"iouring": newIOUringConn,
}
// Connect connects the server via specified network.
+10
View File
@@ -0,0 +1,10 @@
package client
import (
"net"
)
// experimental
func newIOUringConn(c *Client, network, address string) (net.Conn, error) {
return newDirectConn(c, "tcp", address)
}
+46
View File
@@ -0,0 +1,46 @@
//go:build linux
// +build linux
package client
import (
"context"
"testing"
"time"
"github.com/smallnest/rpcx/server"
)
func TestXClient_IOUring(t *testing.T) {
s := server.NewServer()
s.RegisterName("Arith", new(Arith), "")
go s.Serve("iouring", "127.0.0.1:8972")
defer s.Close()
time.Sleep(500 * time.Millisecond)
addr := s.Address().String()
d, err := NewPeer2PeerDiscovery("iouring@"+addr, "desc=a test service")
if err != nil {
t.Fatalf("failed to NewPeer2PeerDiscovery: %v", err)
}
xclient := NewXClient("Arith", Failtry, RandomSelect, d, DefaultOption)
defer xclient.Close()
args := &Args{
A: 10,
B: 20,
}
reply := &Reply{}
err = xclient.Call(context.Background(), "Mul", args, reply)
if err != nil {
t.Fatalf("failed to call: %v", err)
}
if reply.C != 200 {
t.Fatalf("expect 200 but got %d", reply.C)
}
}
+2
View File
@@ -50,6 +50,7 @@ require (
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/godzie44/go-uring v0.0.0-20220926161041-69611e8b13d5 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect
github.com/google/uuid v1.3.0 // indirect
@@ -57,6 +58,7 @@ require (
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/klauspost/reedsolomon v1.11.7 // indirect
github.com/kr/text v0.1.0 // indirect
github.com/libp2p/go-sockaddr v0.1.1 // indirect
github.com/lucas-clemente/quic-go v0.31.1 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.4 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.2 // indirect
+5
View File
@@ -93,6 +93,8 @@ github.com/go-redis/redis_rate/v9 v9.1.2/go.mod h1:oam2de2apSgRG8aJzwJddXbNu91Iy
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/godzie44/go-uring v0.0.0-20220926161041-69611e8b13d5 h1:5zELAgnSz0gqmr4Q5DWCoOzNHoeBAxVUXB7LS1eG+sw=
github.com/godzie44/go-uring v0.0.0-20220926161041-69611e8b13d5/go.mod h1:ermjEDUoT/fS+3Ona5Vd6t6mZkw1eHp99ILO5jGRBkM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -201,6 +203,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/libp2p/go-sockaddr v0.1.1 h1:yD80l2ZOdGksnOyHrhxDdTDFrf7Oy+v3FMVArIRgZxQ=
github.com/libp2p/go-sockaddr v0.1.1/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k=
github.com/lucas-clemente/quic-go v0.28.0/go.mod h1:oGz5DKK41cJt5+773+BSO9BXDsREY4HLf7+0odGAPO0=
github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4=
github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
@@ -486,6 +490,7 @@ golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+4
View File
@@ -35,6 +35,10 @@ func SetLogger(logger Logger) {
l = logger
}
func GetLogger() Logger {
return l
}
func SetDummyLogger() {
l = &dummyLogger{}
}
+66
View File
@@ -0,0 +1,66 @@
//go:build linux
// +build linux
package server
import (
"net"
"runtime"
"time"
uringnet "github.com/godzie44/go-uring/net"
"github.com/godzie44/go-uring/reactor"
"github.com/godzie44/go-uring/uring"
"github.com/smallnest/rpcx/log"
)
func init() {
makeListeners["iouring"] = iouringMakeListener
}
// iouringMakeListener creates a new listener using io_uring.
// You can use RegisterMakeListener to register a customized iouring Listener creator.
// experimental
func iouringMakeListener(s *Server, address string) (ln net.Listener, err error) {
n := runtime.GOMAXPROCS(-1)
var opts []uring.SetupOption
opts = append(opts, uring.WithSQPoll(time.Millisecond*100))
rings, closeRings, err := uring.CreateMany(n, uring.MaxEntries>>3, n, opts...)
if err != nil {
return nil, err
}
netReactor, err := reactor.NewNet(rings, reactor.WithLogger(&uringLogger{log.GetLogger()}))
if err != nil {
return nil, err
}
ln, err = uringnet.NewListener(net.ListenConfig{}, address, netReactor)
if err != nil {
return nil, err
}
return &uringnetListener{Listener: ln, closeRings: closeRings}, nil
}
type uringnetListener struct {
net.Listener
closeRings uring.Defer
}
func (cl *uringnetListener) Close() error {
cl.Listener.Close()
cl.closeRings()
return nil
}
type uringLogger struct {
log.Logger
}
func (l *uringLogger) Log(keyvals ...interface{}) {
l.Logger.Info(keyvals...)
}