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.Reader buf *[]byte rp, wp int// buf read position and write position minBufSize int}// newChunkReader creates and returns a new chunkReader for r with default configuration. If minBufSize is <= 0 it uses// a default value.func newChunkReader( 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 {iflen(*.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 bytesiflen(*.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 {returnnil, } = (*.buf)[.rp : .rp+ : .rp+] .rp += return , nil}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.