Commit 37519d95 authored by Rob Pike's avatar Rob Pike

encoding/gob: reduce decoder memory

Gob decoding reads a whole message into memory and then
copies it into a bytes.Buffer. For large messages this wastes
an entire copy of the message. In this CL, we use a staging
buffer to avoid the large temporary.

Update #2539
RSS drops to 775MB from 1GB.
Active memory drops to 858317048 from 1027878136,
essentially the size of one copy of the input file.

R=dsymonds, nigeltao
CC=golang-dev
https://golang.org/cl/6392057
parent 1255a630
...@@ -87,14 +87,29 @@ func (dec *Decoder) recvMessage() bool { ...@@ -87,14 +87,29 @@ func (dec *Decoder) recvMessage() bool {
// readMessage reads the next nbytes bytes from the input. // readMessage reads the next nbytes bytes from the input.
func (dec *Decoder) readMessage(nbytes int) { func (dec *Decoder) readMessage(nbytes int) {
// Allocate the buffer. // Allocate the dec.tmp buffer, up to 10KB.
if cap(dec.tmp) < nbytes { const maxBuf = 10 * 1024
dec.tmp = make([]byte, nbytes+100) // room to grow nTmp := nbytes
if nTmp > maxBuf {
nTmp = maxBuf
} }
dec.tmp = dec.tmp[:nbytes] if cap(dec.tmp) < nTmp {
nAlloc := nTmp + 100 // A little extra for growth.
if nAlloc > maxBuf {
nAlloc = maxBuf
}
dec.tmp = make([]byte, nAlloc)
}
dec.tmp = dec.tmp[:nTmp]
// Read the data // Read the data
_, dec.err = io.ReadFull(dec.r, dec.tmp) dec.buf.Grow(nbytes)
for nbytes > 0 {
if nbytes < nTmp {
dec.tmp = dec.tmp[:nbytes]
}
var nRead int
nRead, dec.err = io.ReadFull(dec.r, dec.tmp)
if dec.err != nil { if dec.err != nil {
if dec.err == io.EOF { if dec.err == io.EOF {
dec.err = io.ErrUnexpectedEOF dec.err = io.ErrUnexpectedEOF
...@@ -102,6 +117,8 @@ func (dec *Decoder) readMessage(nbytes int) { ...@@ -102,6 +117,8 @@ func (dec *Decoder) readMessage(nbytes int) {
return return
} }
dec.buf.Write(dec.tmp) dec.buf.Write(dec.tmp)
nbytes -= nRead
}
} }
// toInt turns an encoded uint64 into an int, according to the marshaling rules. // toInt turns an encoded uint64 into an int, according to the marshaling rules.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment