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
|
nonblockWriteErr error
|
||||||
nonblockWriteN int
|
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
|
readDeadlineLock sync.Mutex
|
||||||
readDeadline time.Time
|
readDeadline time.Time
|
||||||
readNonblocking bool
|
readNonblocking bool
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ func (c *NetConn) realNonblockingWrite(b []byte) (n int, err error) {
|
|||||||
|
|
||||||
err = c.rawConn.Write(c.nonblockWriteFunc)
|
err = c.rawConn.Write(c.nonblockWriteFunc)
|
||||||
n = c.nonblockWriteN
|
n = c.nonblockWriteN
|
||||||
|
c.nonblockWriteBuf = nil // ensure that no reference to b is kept.
|
||||||
if err == nil && c.nonblockWriteErr != nil {
|
if err == nil && c.nonblockWriteErr != nil {
|
||||||
if errors.Is(c.nonblockWriteErr, syscall.EWOULDBLOCK) {
|
if errors.Is(c.nonblockWriteErr, syscall.EWOULDBLOCK) {
|
||||||
err = ErrWouldBlock
|
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) {
|
func (c *NetConn) realNonblockingRead(b []byte) (n int, err error) {
|
||||||
var funcErr error
|
if c.nonblockReadFunc == nil {
|
||||||
err = c.rawConn.Read(func(fd uintptr) (done bool) {
|
c.nonblockReadFunc = func(fd uintptr) (done bool) {
|
||||||
n, funcErr = syscall.Read(int(fd), b)
|
c.nonblockReadN, c.nonblockReadErr = syscall.Read(int(fd), c.nonblockReadBuf)
|
||||||
return true
|
return true
|
||||||
})
|
}
|
||||||
if err == nil && funcErr != nil {
|
}
|
||||||
if errors.Is(funcErr, syscall.EWOULDBLOCK) {
|
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
|
err = ErrWouldBlock
|
||||||
} else {
|
} else {
|
||||||
err = funcErr
|
err = c.nonblockReadErr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user