From e6c28692f33436f17cd537f3cb42ff5a48483769 Mon Sep 17 00:00:00 2001 From: Konnyaku <50104361+AKonnyaku@users.noreply.github.com> Date: Mon, 26 Jan 2026 02:05:58 +0800 Subject: [PATCH 1/2] perf(enforce): reuse pooled buffers to reduce allocations --- enforcer.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/enforcer.go b/enforcer.go index a6bf1740..8392ff83 100644 --- a/enforcer.go +++ b/enforcer.go @@ -679,6 +679,47 @@ func (e *Enforcer) invalidateMatcherMap() { e.matcherMap = sync.Map{} } +type policyEffectsBuffer struct { + values []effector.Effect +} + +type matcherResultsBuffer struct { + values []float64 +} + +var globalPolicyEffectsPool = sync.Pool{New: func() interface{} { return &policyEffectsBuffer{values: make([]effector.Effect, 0)} }} +var globalMatcherResultsPool = sync.Pool{New: func() interface{} { return &matcherResultsBuffer{values: make([]float64, 0)} }} + +func (e *Enforcer) getPolicyEffectsBuffer(size int) ([]effector.Effect, *policyEffectsBuffer) { + buffer := globalPolicyEffectsPool.Get().(*policyEffectsBuffer) + if cap(buffer.values) < size { + buffer.values = make([]effector.Effect, size) + } else { + buffer.values = buffer.values[:size] + } + return buffer.values, buffer +} + +func (e *Enforcer) putPolicyEffectsBuffer(buffer *policyEffectsBuffer) { + buffer.values = buffer.values[:0] + globalPolicyEffectsPool.Put(buffer) +} + +func (e *Enforcer) getMatcherResultsBuffer(size int) ([]float64, *matcherResultsBuffer) { + buffer := globalMatcherResultsPool.Get().(*matcherResultsBuffer) + if cap(buffer.values) < size { + buffer.values = make([]float64, size) + } else { + buffer.values = buffer.values[:size] + } + return buffer.values, buffer +} + +func (e *Enforcer) putMatcherResultsBuffer(buffer *matcherResultsBuffer) { + buffer.values = buffer.values[:0] + globalMatcherResultsPool.Put(buffer) +} + // enforce use a custom matcher to decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (matcher, sub, obj, act), use model matcher by default when matcher is "". func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interface{}) (ok bool, err error) { //nolint:funlen,cyclop,gocyclo // TODO: reduce function complexity logEntry := e.onLogBeforeEventInEnforce(rvals) @@ -793,15 +834,22 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac rvals) } - var policyEffects []effector.Effect - var matcherResults []float64 - var effect effector.Effect var explainIndex int if policyLen := len(e.model["p"][pType].Policy); policyLen != 0 && strings.Contains(expString, pType+"_") { //nolint:nestif // TODO: reduce function complexity - policyEffects = make([]effector.Effect, policyLen) - matcherResults = make([]float64, policyLen) + policyEffects, policyEffectsBuffer := e.getPolicyEffectsBuffer(policyLen) + matcherResults, matcherResultsBuffer := e.getMatcherResultsBuffer(policyLen) + defer func() { + e.putPolicyEffectsBuffer(policyEffectsBuffer) + e.putMatcherResultsBuffer(matcherResultsBuffer) + }() + for i := range matcherResults { + matcherResults[i] = 0 + } + for i := range policyEffects { + policyEffects[i] = 0 + } for policyIndex, pvals := range e.model["p"][pType].Policy { // log.LogPrint("Policy Rule: ", pvals) @@ -867,8 +915,12 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac return false, errors.New("please make sure rule exists in policy when using eval() in matcher") } - policyEffects = make([]effector.Effect, 1) - matcherResults = make([]float64, 1) + policyEffects, policyEffectsBuffer := e.getPolicyEffectsBuffer(1) + matcherResults, matcherResultsBuffer := e.getMatcherResultsBuffer(1) + defer func() { + e.putPolicyEffectsBuffer(policyEffectsBuffer) + e.putMatcherResultsBuffer(matcherResultsBuffer) + }() matcherResults[0] = 1 parameters.pVals = make([]string, len(parameters.pTokens)) From 258643fed59fd925826c59421e5799204c8c765f Mon Sep 17 00:00:00 2001 From: Yang Luo Date: Mon, 26 Jan 2026 23:25:29 +0800 Subject: [PATCH 2/2] Update enforcer.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- enforcer.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/enforcer.go b/enforcer.go index 8392ff83..641fcd6d 100644 --- a/enforcer.go +++ b/enforcer.go @@ -844,12 +844,6 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac e.putPolicyEffectsBuffer(policyEffectsBuffer) e.putMatcherResultsBuffer(matcherResultsBuffer) }() - for i := range matcherResults { - matcherResults[i] = 0 - } - for i := range policyEffects { - policyEffects[i] = 0 - } for policyIndex, pvals := range e.model["p"][pType].Policy { // log.LogPrint("Policy Rule: ", pvals)