diff --git a/client_test.go b/client_test.go index 3f270ba0e..8793293f6 100644 --- a/client_test.go +++ b/client_test.go @@ -100,50 +100,50 @@ func TestClient(t *testing.T) { t.Run("poll-LT", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", false, false, false, false, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{false, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", false, false, true, false, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{false, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", false, false, false, true, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{false, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", false, false, true, true, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{false, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", false, false, false, false, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{false, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", false, false, true, false, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{false, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", false, false, false, true, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{false, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", false, false, true, true, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{false, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", false, false, false, false, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{false, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", false, false, true, false, 10, SourceAddrHash) + runClient(t, "unix", "gnet2.sock", &testConf{false, 0, false, true, false, false, 10, SourceAddrHash}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", false, false, false, true, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{false, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", false, false, true, true, 10, SourceAddrHash) + runClient(t, "unix", "gnet2.sock", &testConf{false, 0, false, true, true, false, 10, SourceAddrHash}) }) }) }) @@ -151,50 +151,101 @@ func TestClient(t *testing.T) { t.Run("poll-ET", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", true, false, false, false, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{true, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", true, false, true, false, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{true, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", true, false, false, true, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{true, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", true, false, true, true, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{true, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", true, false, false, false, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{true, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", true, false, true, false, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{true, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", true, false, false, true, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{true, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", true, false, true, true, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{true, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", true, false, false, false, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{true, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", true, false, true, false, 10, SourceAddrHash) + runClient(t, "unix", "gnet2.sock", &testConf{true, 0, false, true, false, false, 10, SourceAddrHash}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", true, false, false, true, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{true, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", true, false, true, true, 10, SourceAddrHash) + runClient(t, "unix", "gnet2.sock", &testConf{true, 0, false, true, true, false, 10, SourceAddrHash}) + }) + }) + }) + + t.Run("poll-ET-chunk", func(t *testing.T) { + t.Run("tcp", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runClient(t, "tcp", ":9991", &testConf{true, 1 << 18, false, false, false, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runClient(t, "tcp", ":9992", &testConf{true, 1 << 19, false, true, false, false, 10, LeastConnections}) + }) + }) + t.Run("tcp-async", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runClient(t, "tcp", ":9991", &testConf{true, 1 << 18, false, false, true, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runClient(t, "tcp", ":9992", &testConf{true, 1 << 19, false, true, true, false, 10, LeastConnections}) + }) + }) + t.Run("udp", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runClient(t, "udp", ":9991", &testConf{true, 1 << 18, false, false, false, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runClient(t, "udp", ":9992", &testConf{true, 1 << 19, false, true, false, false, 10, LeastConnections}) + }) + }) + t.Run("udp-async", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runClient(t, "udp", ":9991", &testConf{true, 1 << 18, false, false, true, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runClient(t, "udp", ":9992", &testConf{true, 1 << 19, false, true, true, false, 10, LeastConnections}) + }) + }) + t.Run("unix", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runClient(t, "unix", "gnet1.sock", &testConf{true, 1 << 18, false, false, false, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runClient(t, "unix", "gnet2.sock", &testConf{true, 1 << 19, false, true, false, false, 10, SourceAddrHash}) + }) + }) + t.Run("unix-async", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runClient(t, "unix", "gnet1.sock", &testConf{true, 1 << 18, false, false, true, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runClient(t, "unix", "gnet2.sock", &testConf{true, 1 << 19, false, true, true, false, 10, SourceAddrHash}) }) }) }) @@ -202,50 +253,50 @@ func TestClient(t *testing.T) { t.Run("poll-reuseport-LT", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", false, true, false, false, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", false, true, true, false, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", false, true, false, true, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{false, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", false, true, true, false, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", false, true, false, false, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", false, true, true, false, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", false, true, false, false, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", false, true, true, true, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{false, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", false, true, false, false, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", false, true, true, false, 10, LeastConnections) + runClient(t, "unix", "gnet2.sock", &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", false, true, false, true, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{false, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", false, true, true, true, 10, LeastConnections) + runClient(t, "unix", "gnet2.sock", &testConf{false, 0, true, true, true, false, 10, LeastConnections}) }) }) }) @@ -253,50 +304,50 @@ func TestClient(t *testing.T) { t.Run("poll-reuseport-ET", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", true, true, false, false, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", true, true, true, false, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "tcp", ":9991", true, true, false, true, 10, RoundRobin) + runClient(t, "tcp", ":9991", &testConf{true, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "tcp", ":9992", true, true, true, false, 10, LeastConnections) + runClient(t, "tcp", ":9992", &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", true, true, false, false, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", true, true, true, false, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "udp", ":9991", true, true, false, false, 10, RoundRobin) + runClient(t, "udp", ":9991", &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "udp", ":9992", true, true, true, true, 10, LeastConnections) + runClient(t, "udp", ":9992", &testConf{true, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", true, true, false, false, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", true, true, true, false, 10, LeastConnections) + runClient(t, "unix", "gnet2.sock", &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runClient(t, "unix", "gnet1.sock", true, true, false, true, 10, RoundRobin) + runClient(t, "unix", "gnet1.sock", &testConf{true, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runClient(t, "unix", "gnet2.sock", true, true, true, true, 10, LeastConnections) + runClient(t, "unix", "gnet2.sock", &testConf{true, 0, true, true, true, false, 10, LeastConnections}) }) }) }) @@ -426,20 +477,22 @@ func (s *testClient) OnTick() (delay time.Duration, action Action) { return } -func runClient(t *testing.T, network, addr string, et, reuseport, multicore, async bool, nclients int, lb LoadBalancing) { +func runClient(t *testing.T, network, addr string, conf *testConf) { ts := &testClient{ tester: t, network: network, addr: addr, - multicore: multicore, - async: async, - nclients: nclients, + multicore: conf.multicore, + async: conf.async, + nclients: conf.clients, workerPool: goPool.Default(), } var err error clientEV := &clientEvents{tester: t, packetLen: streamLen, svr: ts} ts.client, err = NewClient( clientEV, + WithEdgeTriggeredIO(conf.et), + WithEdgeTriggeredIOChunk(conf.etChunk), WithTCPNoDelay(TCPNoDelay), WithLockOSThread(true), WithTicker(true), @@ -452,13 +505,14 @@ func runClient(t *testing.T, network, addr string, et, reuseport, multicore, asy err = Run(ts, network+"://"+addr, - WithEdgeTriggeredIO(et), - WithLockOSThread(async), - WithMulticore(multicore), - WithReusePort(reuseport), + WithEdgeTriggeredIO(conf.et), + WithEdgeTriggeredIOChunk(conf.etChunk), + WithLockOSThread(conf.async), + WithMulticore(conf.multicore), + WithReusePort(conf.reuseport), WithTicker(true), WithTCPKeepAlive(time.Minute*1), - WithLoadBalancing(lb)) + WithLoadBalancing(conf.lb)) assert.NoError(t, err) } diff --git a/client_unix.go b/client_unix.go index 2d82f8e98..709a09ef2 100644 --- a/client_unix.go +++ b/client_unix.go @@ -87,6 +87,13 @@ func NewClient(eh EventHandler, opts ...Option) (cli *Client, err error) { poller: p, } + if options.EdgeTriggeredIOChunk > 0 { + options.EdgeTriggeredIO = true + options.EdgeTriggeredIOChunk = math.CeilToPowerOfTwo(options.EdgeTriggeredIOChunk) + } else if options.EdgeTriggeredIO { + options.EdgeTriggeredIOChunk = 1 << 20 // 1MB + } + rbc := options.ReadBufferCap switch { case rbc <= 0: diff --git a/connection_windows.go b/connection_windows.go index efdfc22c9..b32675002 100644 --- a/connection_windows.go +++ b/connection_windows.go @@ -43,8 +43,8 @@ type udpConn struct { } type openConn struct { - c *conn - cb func() + c *conn + cb func() } type conn struct { diff --git a/eventloop_unix.go b/eventloop_unix.go index 0897485d6..6602e78eb 100644 --- a/eventloop_unix.go +++ b/eventloop_unix.go @@ -118,8 +118,6 @@ func (el *eventloop) read0(itf interface{}) error { return el.read(itf.(*conn)) } -const maxBytesTransferET = 1 << 20 - func (el *eventloop) read(c *conn) error { if !c.opened { return nil @@ -127,6 +125,7 @@ func (el *eventloop) read(c *conn) error { var recv int isET := el.engine.opts.EdgeTriggeredIO + chunk := el.engine.opts.EdgeTriggeredIOChunk loop: n, err := unix.Read(c.fd, el.buffer) if err != nil || n == 0 { @@ -152,7 +151,7 @@ loop: _, _ = c.inboundBuffer.Write(c.buffer) c.buffer = c.buffer[:0] - if c.isEOF || (isET && recv < maxBytesTransferET) { + if c.isEOF || (isET && recv < chunk) { goto loop } @@ -180,6 +179,7 @@ func (el *eventloop) write(c *conn) error { } isET := el.engine.opts.EdgeTriggeredIO + chunk := el.engine.opts.EdgeTriggeredIOChunk var ( n int sent int @@ -205,7 +205,7 @@ loop: } sent += n - if isET && !c.outboundBuffer.IsEmpty() && sent < maxBytesTransferET { + if isET && !c.outboundBuffer.IsEmpty() && sent < chunk { goto loop } diff --git a/gnet.go b/gnet.go index 99f6f4038..f05197e72 100644 --- a/gnet.go +++ b/gnet.go @@ -443,6 +443,13 @@ func createListeners(addrs []string, opts ...Option) ([]*listener, *Options, err return nil, nil, errors.ErrTooManyEventLoopThreads } + if options.EdgeTriggeredIOChunk > 0 { + options.EdgeTriggeredIO = true + options.EdgeTriggeredIOChunk = math.CeilToPowerOfTwo(options.EdgeTriggeredIOChunk) + } else if options.EdgeTriggeredIO { + options.EdgeTriggeredIOChunk = 1 << 20 // 1MB + } + rbc := options.ReadBufferCap switch { case rbc <= 0: diff --git a/gnet_test.go b/gnet_test.go index 3e20b0c00..201c6b9de 100644 --- a/gnet_test.go +++ b/gnet_test.go @@ -33,6 +33,17 @@ var ( streamLen = 1024 * 1024 ) +type testConf struct { + et bool + etChunk int + reuseport bool + multicore bool + async bool + writev bool + clients int + lb LoadBalancing +} + func TestServer(t *testing.T) { // start an engine // connect 10 clients @@ -43,66 +54,66 @@ func TestServer(t *testing.T) { t.Run("poll-LT", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, false, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{false, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, false, false, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{false, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, false, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{false, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, false, false, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{false, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("tcp-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, false, false, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{false, 0, false, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, false, false, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{false, 0, false, true, true, true, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, false, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{false, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, false, false, true, false, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{false, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, false, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{false, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, false, false, true, true, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{false, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, false, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{false, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, false, false, true, false, false, 10, SourceAddrHash) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{false, 0, false, true, false, false, 10, SourceAddrHash}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, false, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{false, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, false, false, true, true, false, 10, SourceAddrHash) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{false, 0, false, true, true, false, 10, SourceAddrHash}) }) }) t.Run("unix-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, false, false, false, true, true, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{false, 0, false, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, false, false, true, true, true, 10, SourceAddrHash) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{false, 0, false, true, true, true, 10, SourceAddrHash}) }) }) }) @@ -110,66 +121,133 @@ func TestServer(t *testing.T) { t.Run("poll-ET", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, true, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{true, 0, false, false, false, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"tcp://:9992"}, &testConf{true, 0, false, true, false, false, 10, LeastConnections}) + }) + }) + t.Run("tcp-async", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"tcp://:9991"}, &testConf{true, 0, false, false, true, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"tcp://:9992"}, &testConf{true, 0, false, true, true, false, 10, LeastConnections}) + }) + }) + t.Run("tcp-async-writev", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"tcp://:9991"}, &testConf{true, 0, false, false, true, true, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"tcp://:9992"}, &testConf{true, 0, false, true, true, true, 10, LeastConnections}) + }) + }) + t.Run("udp", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"udp://:9991"}, &testConf{true, 0, false, false, false, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"udp://:9992"}, &testConf{true, 0, false, true, false, false, 10, LeastConnections}) + }) + }) + t.Run("udp-async", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"udp://:9991"}, &testConf{true, 0, false, false, true, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"udp://:9992"}, &testConf{true, 0, false, true, true, false, 10, LeastConnections}) + }) + }) + t.Run("unix", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 0, false, false, false, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 0, false, true, false, false, 10, SourceAddrHash}) + }) + }) + t.Run("unix-async", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 0, false, false, true, false, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 0, false, true, true, false, 10, SourceAddrHash}) + }) + }) + t.Run("unix-async-writev", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 0, false, false, true, true, 10, RoundRobin}) + }) + t.Run("N-loop", func(t *testing.T) { + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 0, false, true, true, true, 10, SourceAddrHash}) + }) + }) + }) + + t.Run("poll-ET-chunk", func(t *testing.T) { + t.Run("tcp", func(t *testing.T) { + t.Run("1-loop", func(t *testing.T) { + runServer(t, []string{"tcp://:9991"}, &testConf{true, 1 << 18, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, true, false, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{true, 1 << 19, false, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, true, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{true, 1 << 18, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, true, false, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{true, 1 << 19, false, true, true, false, 10, LeastConnections}) }) }) t.Run("tcp-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, true, false, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{true, 1 << 18, false, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, true, false, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{true, 1 << 19, false, true, true, true, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, true, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{true, 1 << 18, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, true, false, true, false, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{true, 1 << 19, false, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, true, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{true, 1 << 18, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, true, false, true, true, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{true, 1 << 19, false, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, true, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 1 << 18, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, true, false, true, false, false, 10, SourceAddrHash) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 1 << 19, false, true, false, false, 10, SourceAddrHash}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, true, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 1 << 18, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, true, false, true, true, false, 10, SourceAddrHash) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 1 << 19, false, true, true, false, 10, SourceAddrHash}) }) }) t.Run("unix-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, true, false, false, true, true, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 1 << 18, false, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, true, false, true, true, true, 10, SourceAddrHash) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 1 << 19, false, true, true, true, 10, SourceAddrHash}) }) }) }) @@ -177,66 +255,66 @@ func TestServer(t *testing.T) { t.Run("poll-reuseport-LT", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, false, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, false, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, false, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{false, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, false, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{false, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("tcp-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, false, true, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{false, 0, true, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, false, true, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{false, 0, true, true, true, true, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, false, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, false, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, false, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{false, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, false, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{false, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, false, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, false, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, false, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{false, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, false, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{false, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("unix-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, false, true, false, true, true, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{false, 0, true, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, false, true, true, true, true, 10, LeastConnections) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{false, 0, true, true, true, true, 10, LeastConnections}) }) }) }) @@ -244,66 +322,66 @@ func TestServer(t *testing.T) { t.Run("poll-reuseport-ET", func(t *testing.T) { t.Run("tcp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, true, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, true, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("tcp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, true, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{true, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, true, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{true, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("tcp-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991"}, true, true, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991"}, &testConf{true, 0, true, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9992"}, true, true, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9992"}, &testConf{true, 0, true, true, true, true, 10, LeastConnections}) }) }) t.Run("udp", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, true, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, true, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("udp-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9991"}, true, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"udp://:9991"}, &testConf{true, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"udp://:9992"}, true, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"udp://:9992"}, &testConf{true, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("unix", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, true, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, true, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("unix-async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, true, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, true, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("unix-async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet1.sock"}, true, true, false, true, true, 10, RoundRobin) + runServer(t, []string{"unix://gnet1.sock"}, &testConf{true, 0, true, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"unix://gnet2.sock"}, true, true, true, true, true, 10, LeastConnections) + runServer(t, []string{"unix://gnet2.sock"}, &testConf{true, 0, true, true, true, true, 10, LeastConnections}) }) }) }) @@ -311,34 +389,34 @@ func TestServer(t *testing.T) { t.Run("poll-multi-addrs-LT", func(t *testing.T) { t.Run("sync", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("sync-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, false, false, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, false, false, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, true, false, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, true, false, true, 10, LeastConnections}) }) }) t.Run("async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, false, false, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, false, true, true, true, 10, LeastConnections}) }) }) }) @@ -346,34 +424,34 @@ func TestServer(t *testing.T) { t.Run("poll-multi-addrs-reuseport-LT", func(t *testing.T) { t.Run("sync", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("sync-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, false, false, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, false, false, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, true, false, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, true, false, true, 10, LeastConnections}) }) }) t.Run("async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, false, true, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{false, 0, true, true, true, true, 10, LeastConnections}) }) }) }) @@ -381,34 +459,34 @@ func TestServer(t *testing.T) { t.Run("poll-multi-addrs-ET", func(t *testing.T) { t.Run("sync", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, true, false, false, 10, LeastConnections}) }) }) t.Run("sync-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, false, false, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, false, false, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, true, false, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, true, false, true, 10, LeastConnections}) }) }) t.Run("async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, true, true, false, 10, LeastConnections}) }) }) t.Run("async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, true, false, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, false, true, true, true, 10, LeastConnections}) }) }) }) @@ -416,34 +494,34 @@ func TestServer(t *testing.T) { t.Run("poll-multi-addrs-reuseport-ET", func(t *testing.T) { t.Run("sync", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, false, false, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, false, false, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, true, false, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, true, false, false, 10, LeastConnections}) }) }) t.Run("sync-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, false, false, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, false, false, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, true, false, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, true, false, true, 10, LeastConnections}) }) }) t.Run("async", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, false, true, false, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "udp://:9993", "udp://:9994", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, false, true, false, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, true, true, false, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "udp://:9997", "udp://:9998", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, true, true, false, 10, LeastConnections}) }) }) t.Run("async-writev", func(t *testing.T) { t.Run("1-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, false, true, true, 10, RoundRobin) + runServer(t, []string{"tcp://:9991", "tcp://:9992", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, false, true, true, 10, RoundRobin}) }) t.Run("N-loop", func(t *testing.T) { - runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, true, true, true, true, true, 10, LeastConnections) + runServer(t, []string{"tcp://:9995", "tcp://:9996", "unix://gnet1.sock", "unix://gnet2.sock"}, &testConf{true, 0, true, true, true, true, 10, LeastConnections}) }) }) }) @@ -623,39 +701,41 @@ func (s *testServer) OnTick() (delay time.Duration, action Action) { return } -func runServer(t *testing.T, addrs []string, et, reuseport, multicore, async, writev bool, nclients int, lb LoadBalancing) { +func runServer(t *testing.T, addrs []string, conf *testConf) { ts := &testServer{ tester: t, addrs: addrs, - multicore: multicore, - async: async, - writev: writev, - nclients: nclients, + multicore: conf.multicore, + async: conf.async, + writev: conf.writev, + nclients: conf.clients, workerPool: goPool.Default(), } var err error if len(addrs) > 1 { err = Rotate(ts, addrs, - WithEdgeTriggeredIO(et), - WithLockOSThread(async), - WithMulticore(multicore), - WithReusePort(reuseport), + WithEdgeTriggeredIO(conf.et), + WithEdgeTriggeredIOChunk(conf.etChunk), + WithLockOSThread(conf.async), + WithMulticore(conf.multicore), + WithReusePort(conf.reuseport), WithTicker(true), WithTCPKeepAlive(time.Minute), WithTCPNoDelay(TCPNoDelay), - WithLoadBalancing(lb)) + WithLoadBalancing(conf.lb)) } else { err = Run(ts, addrs[0], - WithEdgeTriggeredIO(et), - WithLockOSThread(async), - WithMulticore(multicore), - WithReusePort(reuseport), + WithEdgeTriggeredIO(conf.et), + WithEdgeTriggeredIOChunk(conf.etChunk), + WithLockOSThread(conf.async), + WithMulticore(conf.multicore), + WithReusePort(conf.reuseport), WithTicker(true), WithTCPKeepAlive(time.Minute), WithTCPNoDelay(TCPDelay), - WithLoadBalancing(lb)) + WithLoadBalancing(conf.lb)) } assert.NoError(t, err) } diff --git a/options.go b/options.go index ed1f8e2ec..545532443 100644 --- a/options.go +++ b/options.go @@ -134,6 +134,14 @@ type Options struct { // Don't enable it unless you are 100% sure what you are doing. // Note that this option is only available for stream-oriented protocol. EdgeTriggeredIO bool + + // EdgeTriggeredIOChunk specifies the number of bytes that `gnet` can + // read/write up to in one event loop of ET. This option implies + // EdgeTriggeredIO when it is set to a value greater than 0. + // If EdgeTriggeredIO is set to true and EdgeTriggeredIOChunk is not set, + // 1MB is used. The value of EdgeTriggeredIOChunk must be a power of 2, + // otherwise, it will be rounded up to the nearest power of 2. + EdgeTriggeredIOChunk int } // WithOptions sets up all options. @@ -268,3 +276,11 @@ func WithEdgeTriggeredIO(et bool) Option { opts.EdgeTriggeredIO = et } } + +// WithEdgeTriggeredIOChunk sets the number of bytes that `gnet` can +// read/write up to in one event loop of ET. +func WithEdgeTriggeredIOChunk(chunk int) Option { + return func(opts *Options) { + opts.EdgeTriggeredIOChunk = chunk + } +}