Skip to content

Commit aad7682

Browse files
committed
internal: parallel the reader goroutine
The execution of the reader goroutine is the bottleneck for our benchmarks. About 1/3 of this goroutine's execution time is spent searching for the future and setting the response. This part of the work can easily be moved to a separate goroutine. In practice, the data transfer through the channel is not much efficient, but this can be improved later.
1 parent 59ad9bf commit aad7682

2 files changed

Lines changed: 28 additions & 12 deletions

File tree

connection.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,32 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
849849

850850
go conn.eventer(events)
851851

852+
type resp struct {
853+
header Header
854+
buf smallBuf
855+
}
856+
857+
resps := make(chan resp, 1024)
858+
defer close(resps)
859+
860+
go func() {
861+
var r resp
862+
863+
for r = range resps {
864+
fut := conn.fetchFuture(r.header.RequestId)
865+
if fut == nil {
866+
conn.opts.Logger.Report(LogUnexpectedResultId, conn, r.header)
867+
868+
continue
869+
}
870+
871+
if err := fut.setResponse(r.header, &r.buf); err != nil {
872+
fut.setError(fmt.Errorf("failed to set response: %w", err))
873+
}
874+
conn.markDone(fut)
875+
}
876+
}()
877+
852878
buf := smallBuf{}
853879

854880
for atomic.LoadUint32(&conn.state) != connClosed {
@@ -874,7 +900,6 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
874900
return
875901
}
876902

877-
var fut *future = nil
878903
if code == iproto.IPROTO_EVENT {
879904
if event, err := readWatchEvent(&buf); err == nil {
880905
events <- event
@@ -889,16 +914,7 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
889914
} else if code == iproto.IPROTO_CHUNK {
890915
conn.opts.Logger.Report(LogBoxSessionPushUnsupported, conn, header)
891916
} else {
892-
if fut = conn.fetchFuture(header.RequestId); fut != nil {
893-
if err := fut.setResponse(header, &buf); err != nil {
894-
fut.setError(fmt.Errorf("failed to set response: %w", err))
895-
}
896-
conn.markDone(fut)
897-
}
898-
}
899-
900-
if fut == nil {
901-
conn.opts.Logger.Report(LogUnexpectedResultId, conn, header)
917+
resps <- resp{header: header, buf: buf}
902918
}
903919
}
904920
}

dial_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ func TestConn_ReadWrite(t *testing.T) {
277277
conn.read = make(chan struct{})
278278
conn.written = make(chan struct{})
279279
conn.writeWgDelay = 1
280+
conn.readWgDelay = 2
280281
conn.readbuf.Write([]byte{
281282
0xce, 0x00, 0x00, 0x00, 0x0a, // Length.
282283
0x82, // Header map.
@@ -296,7 +297,6 @@ func TestConn_ReadWrite(t *testing.T) {
296297
<-dialer.conn.written
297298
dialer.conn.written = nil
298299

299-
dialer.conn.readWg.Done()
300300
<-dialer.conn.read
301301
<-dialer.conn.read
302302

0 commit comments

Comments
 (0)