diff --git a/server/handler.go b/server/handler.go index 14b40582d8..cc344b3ff0 100644 --- a/server/handler.go +++ b/server/handler.go @@ -920,6 +920,9 @@ func (h *Handler) resultForValueRowIter(ctx *sql.Context, c *mysql.Conn, schema return sqlErr } + // TODO: hope it's safe to release here + sql.ValueRowPoolManager.Put(row) + ctx.GetLogger().Tracef("spooling result row %s", outRow) res.Rows[res.RowsAffected] = outRow res.RowsAffected++ diff --git a/sql/plan/filter.go b/sql/plan/filter.go index 4e78b50500..b0e514415c 100644 --- a/sql/plan/filter.go +++ b/sql/plan/filter.go @@ -150,6 +150,7 @@ func (i *FilterIter) NextValueRow(ctx *sql.Context) (sql.ValueRow, error) { if res.Val[0] == 1 { return row, nil } + sql.ValueRowPoolManager.Put(row) } } diff --git a/sql/value_row.go b/sql/value_row.go index f9140c41c5..ed0f9e8853 100644 --- a/sql/value_row.go +++ b/sql/value_row.go @@ -21,6 +21,7 @@ import ( ) const ( + valueRowSize = 48 // TODO: adjust valueArrSize = 64 fieldArrSize = 2048 ) @@ -52,6 +53,32 @@ func (v Value) IsNull() bool { return (v.Val == nil && v.WrappedVal == nil) || v.Typ == query.Type_NULL_TYPE } +var valueRowPool = sync.Pool{ + New: func() interface{} { + return make(ValueRow, 0, valueRowSize) + }, +} + +type valueRowPoolManager struct{} + +func (valueRowPoolManager) Get(n int) ValueRow { + if n > valueRowSize { + return make(ValueRow, n) + } + res := valueRowPool.Get().(ValueRow) + return res[:n] +} + +func (valueRowPoolManager) Put(val ValueRow) { + if len(val) > valueRowSize { + return + } + val = val[:0] // TODO: might need more work to properly reset + valueRowPool.Put(val) +} + +var ValueRowPoolManager = valueRowPoolManager{} + type RowFrame struct { Types []query.Type