From 37fd83174fd6523cf0d9e56ef20d6725ab25718e Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Tue, 13 Nov 2018 18:18:05 +0900 Subject: [PATCH 1/2] buffer: Improve cap consistency. --- buffer.go | 20 ++++++++++++++------ packets.go | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/buffer.go b/buffer.go index eb4748bf4..2dc27cbf5 100644 --- a/buffer.go +++ b/buffer.go @@ -30,9 +30,8 @@ type buffer struct { } func newBuffer(nc net.Conn) buffer { - var b [defaultBufSize]byte return buffer{ - buf: b[:], + buf: make([]byte, defaultBufSize, defaultBufSize), nc: nc, } } @@ -51,7 +50,8 @@ func (b *buffer) fill(need int) error { // Maybe keep the org buf slice and swap back? if need > len(b.buf) { // Round up to the next multiple of the default size - newBuf := make([]byte, ((need/defaultBufSize)+1)*defaultBufSize) + newSize := ((need / defaultBufSize) + 1) * defaultBufSize + newBuf := make([]byte, newSize, newSize) copy(newBuf, b.buf) b.buf = newBuf } @@ -114,13 +114,12 @@ func (b *buffer) takeBuffer(length int) []byte { return nil } - // test (cheap) general case first - if length <= defaultBufSize || length <= cap(b.buf) { + if length <= len(b.buf) { return b.buf[:length] } if length < maxPacketSize { - b.buf = make([]byte, length) + b.buf = make([]byte, length, length) return b.buf } return make([]byte, length) @@ -145,3 +144,12 @@ func (b *buffer) takeCompleteBuffer() []byte { } return b.buf } + +// setGrownBuffer set buf as internal buffer if cap(buf) is larger +// than len(b.buf). It can be used when you took buffer by +// takeCompleteBuffer and append some data to it. +func (b *buffer) setGrownBuffer(buf []byte) { + if cap(buf) >= len(b.buf) { + b.buf = buf[:cap(buf)] + } +} diff --git a/packets.go b/packets.go index 9ed640850..527488319 100644 --- a/packets.go +++ b/packets.go @@ -1076,7 +1076,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error { // In that case we must build the data packet with the new values buffer if valuesCap != cap(paramValues) { data = append(data[:pos], paramValues...) - mc.buf.buf = data + mc.buf.setGrownBuffer(data) } pos += len(paramValues) From c189d6a99adbb793bbcc7279b153bcd22e78f0b3 Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Tue, 13 Nov 2018 18:38:17 +0900 Subject: [PATCH 2/2] cap(make([]byte, n)) == n https://golang.org/ref/spec#Making_slices_maps_and_channels --- buffer.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/buffer.go b/buffer.go index 2dc27cbf5..4d705a5a6 100644 --- a/buffer.go +++ b/buffer.go @@ -31,7 +31,7 @@ type buffer struct { func newBuffer(nc net.Conn) buffer { return buffer{ - buf: make([]byte, defaultBufSize, defaultBufSize), + buf: make([]byte, defaultBufSize), nc: nc, } } @@ -50,8 +50,7 @@ func (b *buffer) fill(need int) error { // Maybe keep the org buf slice and swap back? if need > len(b.buf) { // Round up to the next multiple of the default size - newSize := ((need / defaultBufSize) + 1) * defaultBufSize - newBuf := make([]byte, newSize, newSize) + newBuf := make([]byte, ((need/defaultBufSize)+1)*defaultBufSize) copy(newBuf, b.buf) b.buf = newBuf } @@ -119,7 +118,7 @@ func (b *buffer) takeBuffer(length int) []byte { } if length < maxPacketSize { - b.buf = make([]byte, length, length) + b.buf = make([]byte, length) return b.buf } return make([]byte, length) @@ -149,7 +148,9 @@ func (b *buffer) takeCompleteBuffer() []byte { // than len(b.buf). It can be used when you took buffer by // takeCompleteBuffer and append some data to it. func (b *buffer) setGrownBuffer(buf []byte) { - if cap(buf) >= len(b.buf) { - b.buf = buf[:cap(buf)] + // buf may be grown by `buf = append(buf, ...)`. So set len=cap explicitly. + buf = buf[:cap(buf)] + if len(buf) > len(b.buf) { + b.buf = buf } }