drop too large values from memory pools

This commit is contained in:
merlin 2024-10-01 17:16:02 +03:00
parent 90a77b13b2
commit 47cbd8edb8
No known key found for this signature in database
GPG Key ID: 7EDDCEA6A90062E0

View File

@ -26,11 +26,17 @@ type Query struct {
// https://github.com/jackc/pgx/issues/1380 // https://github.com/jackc/pgx/issues/1380
const replacementcharacterwidth = 3 const replacementcharacterwidth = 3
const maxBufSize = 16384 // 16 Ki
var bufPool = &pool[*bytes.Buffer]{ var bufPool = &pool[*bytes.Buffer]{
new: func() *bytes.Buffer { new: func() *bytes.Buffer {
return &bytes.Buffer{} return &bytes.Buffer{}
}, },
reset: (*bytes.Buffer).Reset, reset: func(b *bytes.Buffer) bool {
n := b.Len()
b.Reset()
return n < maxBufSize
},
} }
var null = []byte("null") var null = []byte("null")
@ -110,20 +116,23 @@ var sqlLexerPool = &pool[*sqlLexer]{
new: func() *sqlLexer { new: func() *sqlLexer {
return &sqlLexer{} return &sqlLexer{}
}, },
reset: func(sl *sqlLexer) { reset: func(sl *sqlLexer) bool {
*sl = sqlLexer{} *sl = sqlLexer{}
return true
}, },
} }
func (q *Query) init(sql string) { func (q *Query) init(sql string) {
parts := q.Parts[:0] parts := q.Parts[:0]
if parts == nil { if parts == nil {
// dirty, but fast heuristic to preallocate for ~90% usecases
n := strings.Count(sql, "$") + strings.Count(sql, "--") + 1 n := strings.Count(sql, "$") + strings.Count(sql, "--") + 1
parts = make([]Part, 0, n) parts = make([]Part, 0, n)
} }
l := sqlLexerPool.get() l := sqlLexerPool.get()
defer sqlLexerPool.put(l) defer sqlLexerPool.put(l)
l.src = sql l.src = sql
l.stateFn = rawState l.stateFn = rawState
l.parts = parts l.parts = parts
@ -393,8 +402,10 @@ var queryPool = &pool[*Query]{
new: func() *Query { new: func() *Query {
return &Query{} return &Query{}
}, },
reset: func(q *Query) { reset: func(q *Query) bool {
n := len(q.Parts)
q.Parts = q.Parts[:0] q.Parts = q.Parts[:0]
return n < 64 // drop too large queries
}, },
} }
@ -412,7 +423,7 @@ func SanitizeSQL(sql string, args ...any) (string, error) {
type pool[E any] struct { type pool[E any] struct {
p sync.Pool p sync.Pool
new func() E new func() E
reset func(E) reset func(E) bool
} }
func (pool *pool[E]) get() E { func (pool *pool[E]) get() E {
@ -425,6 +436,7 @@ func (pool *pool[E]) get() E {
} }
func (p *pool[E]) put(v E) { func (p *pool[E]) put(v E) {
p.reset(v) if p.reset(v) {
p.p.Put(v) p.p.Put(v)
}
} }