Save memory on non blocking read path
Only create RawConn.Read callback once and have it use NetConn fields. Avoids the closure and some allocations. https://github.com/jackc/pgx/issues/1481
This commit is contained in:
@@ -79,6 +79,13 @@ type NetConn struct {
|
||||
nonblockWriteErr error
|
||||
nonblockWriteN int
|
||||
|
||||
// non-blocking reads with syscall.RawConn are done with a callback function. By using these fields instead of the
|
||||
// callback functions closure to pass the buf argument and receive the n and err results we avoid some allocations.
|
||||
nonblockReadFunc func(fd uintptr) (done bool)
|
||||
nonblockReadBuf []byte
|
||||
nonblockReadErr error
|
||||
nonblockReadN int
|
||||
|
||||
readDeadlineLock sync.Mutex
|
||||
readDeadline time.Time
|
||||
readNonblocking bool
|
||||
|
||||
@@ -24,6 +24,7 @@ func (c *NetConn) realNonblockingWrite(b []byte) (n int, err error) {
|
||||
|
||||
err = c.rawConn.Write(c.nonblockWriteFunc)
|
||||
n = c.nonblockWriteN
|
||||
c.nonblockWriteBuf = nil // ensure that no reference to b is kept.
|
||||
if err == nil && c.nonblockWriteErr != nil {
|
||||
if errors.Is(c.nonblockWriteErr, syscall.EWOULDBLOCK) {
|
||||
err = ErrWouldBlock
|
||||
@@ -44,16 +45,24 @@ func (c *NetConn) realNonblockingWrite(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (c *NetConn) realNonblockingRead(b []byte) (n int, err error) {
|
||||
var funcErr error
|
||||
err = c.rawConn.Read(func(fd uintptr) (done bool) {
|
||||
n, funcErr = syscall.Read(int(fd), b)
|
||||
return true
|
||||
})
|
||||
if err == nil && funcErr != nil {
|
||||
if errors.Is(funcErr, syscall.EWOULDBLOCK) {
|
||||
if c.nonblockReadFunc == nil {
|
||||
c.nonblockReadFunc = func(fd uintptr) (done bool) {
|
||||
c.nonblockReadN, c.nonblockReadErr = syscall.Read(int(fd), c.nonblockReadBuf)
|
||||
return true
|
||||
}
|
||||
}
|
||||
c.nonblockReadBuf = b
|
||||
c.nonblockReadN = 0
|
||||
c.nonblockReadErr = nil
|
||||
|
||||
err = c.rawConn.Read(c.nonblockReadFunc)
|
||||
n = c.nonblockReadN
|
||||
c.nonblockReadBuf = nil // ensure that no reference to b is kept.
|
||||
if err == nil && c.nonblockReadErr != nil {
|
||||
if errors.Is(c.nonblockReadErr, syscall.EWOULDBLOCK) {
|
||||
err = ErrWouldBlock
|
||||
} else {
|
||||
err = funcErr
|
||||
err = c.nonblockReadErr
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user