Source File
chunkreader.go
Belonging Package
github.com/jackc/pgx/v5/pgproto3
package pgproto3import ()// chunkReader is a io.Reader wrapper that minimizes IO reads and memory allocations. It allocates memory in chunks and// will read as much as will fit in the current buffer in a single call regardless of how large a read is actually// requested. The memory returned via Next is only valid until the next call to Next.//// This is roughly equivalent to a bufio.Reader that only uses Peek and Discard to never copy bytes.type chunkReader struct {r io.Readerbuf *[]byterp, wp int // buf read position and write positionminBufSize int}// newChunkReader creates and returns a new chunkReader for r with default configuration. If minBufSize is <= 0 it uses// a default value.func ( io.Reader, int) *chunkReader {if <= 0 {// By historical reasons Postgres currently has 8KB send buffer inside,// so here we want to have at least the same size buffer.// @see https://github.com/postgres/postgres/blob/249d64999615802752940e017ee5166e726bc7cd/src/backend/libpq/pqcomm.c#L134// @see https://www.postgresql.org/message-id/0cdc5485-cb3c-5e16-4a46-e3b2f7a41322%40ya.ru//// In addition, testing has found no benefit of any larger buffer.= 8192}return &chunkReader{r: ,minBufSize: ,buf: iobufpool.Get(),}}// Next returns buf filled with the next n bytes. buf is only valid until next call of Next. If an error occurs, buf// will be nil.func ( *chunkReader) ( int) ( []byte, error) {// Reset the buffer if it is emptyif .rp == .wp {if len(*.buf) != .minBufSize {iobufpool.Put(.buf).buf = iobufpool.Get(.minBufSize)}.rp = 0.wp = 0}// n bytes already in bufif (.wp - .rp) >= {= (*.buf)[.rp : .rp+ : .rp+].rp +=return ,}// buf is smaller than requested number of bytesif len(*.buf) < {:= iobufpool.Get().wp = copy((*), (*.buf)[.rp:.wp]).rp = 0iobufpool.Put(.buf).buf =}// buf is large enough, but need to shift filled area to start to make enough contiguous space:= - (.wp - .rp)if (len(*.buf) - .wp) < {.wp = copy((*.buf), (*.buf)[.rp:.wp]).rp = 0}// Read at least the required number of bytes from the underlying io.Reader, := io.ReadAtLeast(.r, (*.buf)[.wp:], ).wp +=// fmt.Println("read", n)if != nil {return nil,}= (*.buf)[.rp : .rp+ : .rp+].rp +=return , nil}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)