From 8b365ce37e04c661320dff233e8d7e4b7675fc3a Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sat, 4 May 2019 11:01:09 -0500 Subject: [PATCH] Extract int16SlicePool --- conn.go | 20 +++++--------------- int16_slice_pool.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 int16_slice_pool.go diff --git a/conn.go b/conn.go index 629aafad..6bfe515d 100644 --- a/conn.go +++ b/conn.go @@ -49,9 +49,8 @@ type Conn struct { wbuf []byte preallocatedRows []connRows - paramFormats []int16 + int16SlicePool int16SlicePool paramValues [][]byte - resultFormats []int16 } // PreparedStatement is a description of a prepared statement @@ -160,9 +159,7 @@ func connect(ctx context.Context, config *ConnConfig) (c *Conn, err error) { c.doneChan = make(chan struct{}) c.closedChan = make(chan error) c.wbuf = make([]byte, 0, 1024) - c.paramFormats = make([]int16, 0, 16) c.paramValues = make([][]byte, 0, 16) - c.resultFormats = make([]int16, 0, 32) // Replication connections can't execute the queries to // populate the c.PgTypes and c.pgsqlAfInet @@ -651,12 +648,7 @@ optionLoop: return rows, rows.err } - var paramFormats []int16 - if len(args) > cap(c.paramFormats) { - paramFormats = make([]int16, len(args)) - } else { - paramFormats = c.paramFormats[:len(args)] - } + paramFormats := c.int16SlicePool.get(len(args)) var paramValues [][]byte if len(args) > cap(c.paramValues) { @@ -682,11 +674,7 @@ optionLoop: } if resultFormats == nil { - if len(ps.FieldDescriptions) > cap(c.resultFormats) { - resultFormats = make([]int16, len(ps.FieldDescriptions)) - } else { - resultFormats = c.resultFormats[:len(ps.FieldDescriptions)] - } + resultFormats = c.int16SlicePool.get(len(ps.FieldDescriptions)) for i := range resultFormats { if dt, ok := c.ConnInfo.DataTypeForOID(ps.FieldDescriptions[i].DataType); ok { @@ -701,6 +689,8 @@ optionLoop: rows.resultReader = c.pgConn.ExecPrepared(ctx, ps.Name, paramValues, paramFormats, resultFormats) + c.int16SlicePool.reset() + return rows, rows.err } diff --git a/int16_slice_pool.go b/int16_slice_pool.go new file mode 100644 index 00000000..2e7c3939 --- /dev/null +++ b/int16_slice_pool.go @@ -0,0 +1,42 @@ +package pgx + +const int16SlicePoolSizeStep = 16 + +type int16SlicePool struct { + buf []int16 + pos int + allocCount int + resetCount int +} + +func (p *int16SlicePool) get(n int) []int16 { + if n > len(p.buf[p.pos:]) { + growthStep := ((n / int16SlicePoolSizeStep) + 1) * int16SlicePoolSizeStep + p.buf = make([]int16, len(p.buf)+growthStep) + p.pos = 0 + } + + result := p.buf[p.pos : p.pos+n] + p.pos += n + + p.allocCount += n + + return result +} + +func (p *int16SlicePool) reset() { + p.pos = 0 + p.resetCount += 1 + + if p.resetCount == 128 { + allocsPerReset := p.allocCount / p.resetCount + maxSize := allocsPerReset + (int16SlicePoolSizeStep * 4) + + if len(p.buf) > maxSize { + p.buf = make([]int16, maxSize) + } + + p.allocCount = 0 + p.resetCount = 0 + } +}