mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-23 00:34:48 -06:00
3e1af3bd6a
Some work I did during the holidays as part of improving the performance of interpolated strings. This change is however not isolated to those, but updates the `String()` implementation of all AST node types (term values and policy components). This change also lays the groundwork for migrating OPA to the `json/v2` package once that's stable. The `json/v2` package provides low-level functions for zero alloc marshalling via appenders — and well, here they are. The appenders here should be usable for that purpose with only a few tweaks needed for the few cases where our `String()` implementations aren't also valid JSON. Creating perfectly sized buffers requires knowing the expected length beforehand. In order to do this, each component now implements not only `encoding.AppendText` but a new custom `StringLengther` interface, which allows asking any AST node about its `StringLength()` before `make`ing a buffer of that length. We could definitely consider adding these to e.g. the `Value` or `Node` interfaces, but I've left that out of this PR as it's an easy thing to do later should we want to, and I guess there's always some concerns about changing public interfaces even when they're not meant to be implemented by external code. While no `Value` appenders allocate and almost none of the policy appenders do either, one notable exception is `Module` when there are annotations present, as they are a bit of a (YAML) special case. It's doable, but as serializing full modules isn't on a hot path anywhere, I have chosen to defer that work to the future. Signed-off-by: Anders Eknert <anders.eknert@apple.com>
39 lines
608 B
Go
39 lines
608 B
Go
package ast
|
|
|
|
import (
|
|
"bytes"
|
|
"sync"
|
|
|
|
"github.com/open-policy-agent/opa/v1/util"
|
|
)
|
|
|
|
var (
|
|
TermPtrPool = util.NewSyncPool[Term]()
|
|
BytesReaderPool = util.NewSyncPool[bytes.Reader]()
|
|
IndexResultPool = util.NewSyncPool[IndexResult]()
|
|
|
|
// Needs custom pool because of custom Put logic.
|
|
varVisitorPool = &vvPool{
|
|
pool: sync.Pool{
|
|
New: func() any {
|
|
return NewVarVisitor()
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
type vvPool struct {
|
|
pool sync.Pool
|
|
}
|
|
|
|
func (p *vvPool) Get() *VarVisitor {
|
|
return p.pool.Get().(*VarVisitor)
|
|
}
|
|
|
|
func (p *vvPool) Put(vv *VarVisitor) {
|
|
if vv != nil {
|
|
vv.Clear()
|
|
p.pool.Put(vv)
|
|
}
|
|
}
|