Skip to content

feat: perf(enforce): reuse buffers with sync.Pool to reduce allocations#1696

Merged
hsluoyz merged 2 commits intoapache:masterfrom
AKonnyaku:enforcer-test
Jan 26, 2026
Merged

feat: perf(enforce): reuse buffers with sync.Pool to reduce allocations#1696
hsluoyz merged 2 commits intoapache:masterfrom
AKonnyaku:enforcer-test

Conversation

@AKonnyaku
Copy link
Contributor

Local profiling on current master branch showed alloc_space hotspots dominated by make slices inside enforce. Heap profiles traced most churn to policyEffects and matcherResults buffers.

  • The fix replaces per-call allocations with sync.pool reuse for both buffers. It reduces gc pressure and stabilizes allocation behavior under load.
  • Global pools are used to avoid inflating the enforcer struct and to keep cache layout stable. Buffers are zeroed before use to prevent stale data effects.
  • Bench results show a ~26% drop in bytes/op for rbacModelWithDomainPatternLarge. Allocs/op fall ~11% in cachedAbacModel, basicModel, and abacModel.

@github-actions
Copy link

github-actions bot commented Jan 25, 2026

Benchmark Comparison

Comparing base branch (0fe9505)
vs PR branch (258643f)

goos: linux
goarch: amd64
pkg: github.com/casbin/casbin/v3
cpu: AMD EPYC 7763 64-Core Processor                
                                                 │ base-bench.txt │
                                                 │     sec/op     │
CachedRaw                                          15.40n ± ∞ ¹
CachedBasicModel                                   168.7n ± ∞ ¹
CachedRBACModel                                    171.6n ± ∞ ¹
CachedRBACModelSmall                               183.8n ± ∞ ¹
CachedRBACModelMedium                              181.2n ± ∞ ¹
CachedRBACModelLarge                               157.6n ± ∞ ¹
CachedRBACModelWithResourceRoles                   175.4n ± ∞ ¹
CachedRBACModelWithDomains                         173.5n ± ∞ ¹
CachedABACModel                                    2.689µ ± ∞ ¹
CachedKeyMatchModel                                184.9n ± ∞ ¹
CachedRBACModelWithDeny                            169.1n ± ∞ ¹
CachedPriorityModel                                169.7n ± ∞ ¹
CachedWithEnforceContext                           237.0n ± ∞ ¹
CachedRBACModelMediumParallel                      164.6n ± ∞ ¹
HasPolicySmall                                     431.1n ± ∞ ¹
HasPolicyMedium                                    442.5n ± ∞ ¹
HasPolicyLarge                                     486.2n ± ∞ ¹
AddPolicySmall                                     522.4n ± ∞ ¹
AddPolicyMedium                                    630.7n ± ∞ ¹
AddPolicyLarge                                     1.208µ ± ∞ ¹
RemovePolicySmall                                  507.1n ± ∞ ¹
RemovePolicyMedium                                 540.2n ± ∞ ¹
RemovePolicyLarge                                  598.6n ± ∞ ¹
Raw                                                15.08n ± ∞ ¹
BasicModel                                         3.498µ ± ∞ ¹
RBACModel                                          5.196µ ± ∞ ¹
RBACModelSizes/small                               48.31µ ± ∞ ¹
RBACModelSizes/medium                              478.1µ ± ∞ ¹
RBACModelSizes/large                               5.375m ± ∞ ¹
RBACModelSmall                                     57.58µ ± ∞ ¹
RBACModelMedium                                    558.1µ ± ∞ ¹
RBACModelLarge                                     5.905m ± ∞ ¹
RBACModelWithResourceRoles                         4.281µ ± ∞ ¹
RBACModelWithDomains                               4.870µ ± ∞ ¹
ABACModel                                          2.607µ ± ∞ ¹
ABACRuleModel                                      4.000m ± ∞ ¹
KeyMatchModel                                      5.932µ ± ∞ ¹
RBACModelWithDeny                                  6.651µ ± ∞ ¹
PriorityModel                                      4.033µ ± ∞ ¹
RBACModelWithDomainPatternLarge                    12.95µ ± ∞ ¹
RoleManagerSmall                                   47.69µ ± ∞ ¹
RoleManagerMedium                                  536.9µ ± ∞ ¹
RoleManagerLarge                                   5.913m ± ∞ ¹
BuildRoleLinksWithPatternLarge                     287.6m ± ∞ ¹
BuildRoleLinksWithDomainPatternLarge               9.062m ± ∞ ¹
BuildRoleLinksWithPatternAndDomainPatternLarge     294.5m ± ∞ ¹
HasLinkWithPatternLarge                            987.1n ± ∞ ¹
HasLinkWithDomainPatternLarge                      342.3n ± ∞ ¹
HasLinkWithPatternAndDomainPatternLarge            987.8n ± ∞ ¹
ConcurrentHasLinkWithMatching                      1.172µ ± ∞ ¹
geomean                                                                n/a (has zero)
¹ need >= 6 samples for confidence interval at level 0.95

                                                 │ base-bench.txt │
                                                 │      B/op      │
CachedRaw                                           0.000 ± ∞ ¹
CachedBasicModel                                    104.0 ± ∞ ¹
CachedRBACModel                                     104.0 ± ∞ ¹
CachedRBACModelSmall                                104.0 ± ∞ ¹
CachedRBACModelMedium                               104.0 ± ∞ ¹
CachedRBACModelLarge                                96.00 ± ∞ ¹
CachedRBACModelWithResourceRoles                    104.0 ± ∞ ¹
CachedRBACModelWithDomains                          120.0 ± ∞ ¹
CachedABACModel                                   1.511Ki ± ∞ ¹
CachedKeyMatchModel                                 152.0 ± ∞ ¹
CachedRBACModelWithDeny                             104.0 ± ∞ ¹
CachedPriorityModel                                 104.0 ± ∞ ¹
CachedWithEnforceContext                            176.0 ± ∞ ¹
CachedRBACModelMediumParallel                       104.0 ± ∞ ¹
HasPolicySmall                                      102.0 ± ∞ ¹
HasPolicyMedium                                     109.0 ± ∞ ¹
HasPolicyLarge                                      117.0 ± ∞ ¹
AddPolicySmall                                      152.0 ± ∞ ¹
AddPolicyMedium                                     166.0 ± ∞ ¹
AddPolicyLarge                                      426.0 ± ∞ ¹
RemovePolicySmall                                   166.0 ± ∞ ¹
RemovePolicyMedium                                  174.0 ± ∞ ¹
RemovePolicyLarge                                   181.0 ± ∞ ¹
Raw                                                 0.000 ± ∞ ¹
BasicModel                                        1.485Ki ± ∞ ¹
RBACModel                                         2.028Ki ± ∞ ¹
RBACModelSizes/small                              19.83Ki ± ∞ ¹
RBACModelSizes/medium                             187.2Ki ± ∞ ¹
RBACModelSizes/large                              1.810Mi ± ∞ ¹
RBACModelSmall                                    20.00Ki ± ∞ ¹
RBACModelMedium                                   189.8Ki ± ∞ ¹
RBACModelLarge                                    1.840Mi ± ∞ ¹
RBACModelWithResourceRoles                        1.806Ki ± ∞ ¹
RBACModelWithDomains                              1.798Ki ± ∞ ¹
ABACModel                                         1.504Ki ± ∞ ¹
ABACRuleModel                                     1.256Mi ± ∞ ¹
KeyMatchModel                                     3.012Ki ± ∞ ¹
RBACModelWithDeny                                 2.439Ki ± ∞ ¹
PriorityModel                                     1.734Ki ± ∞ ¹
RBACModelWithDomainPatternLarge                   8.696Ki ± ∞ ¹
RoleManagerSmall                                    800.0 ± ∞ ¹
RoleManagerMedium                                 13.63Ki ± ∞ ¹
RoleManagerLarge                                  224.6Ki ± ∞ ¹
BuildRoleLinksWithPatternLarge                    60.79Mi ± ∞ ¹
BuildRoleLinksWithDomainPatternLarge              3.951Mi ± ∞ ¹
BuildRoleLinksWithPatternAndDomainPatternLarge    62.48Mi ± ∞ ¹
HasLinkWithPatternLarge                             112.0 ± ∞ ¹
HasLinkWithDomainPatternLarge                       16.00 ± ∞ ¹
HasLinkWithPatternAndDomainPatternLarge             112.0 ± ∞ ¹
ConcurrentHasLinkWithMatching                       736.0 ± ∞ ¹
geomean                                                                n/a (has zero)
¹ need >= 6 samples for confidence interval at level 0.95
² summaries must be >0 to compute geomean

                                                 │ base-bench.txt │
                                                 │   allocs/op    │
CachedRaw                                           0.000 ± ∞ ¹
CachedBasicModel                                    4.000 ± ∞ ¹
CachedRBACModel                                     4.000 ± ∞ ¹
CachedRBACModelSmall                                4.000 ± ∞ ¹
CachedRBACModelMedium                               4.000 ± ∞ ¹
CachedRBACModelLarge                                3.000 ± ∞ ¹
CachedRBACModelWithResourceRoles                    4.000 ± ∞ ¹
CachedRBACModelWithDomains                          4.000 ± ∞ ¹
CachedABACModel                                     18.00 ± ∞ ¹
CachedKeyMatchModel                                 4.000 ± ∞ ¹
CachedRBACModelWithDeny                             4.000 ± ∞ ¹
CachedPriorityModel                                 4.000 ± ∞ ¹
CachedWithEnforceContext                            4.000 ± ∞ ¹
CachedRBACModelMediumParallel                       4.000 ± ∞ ¹
HasPolicySmall                                      4.000 ± ∞ ¹
HasPolicyMedium                                     4.000 ± ∞ ¹
HasPolicyLarge                                      5.000 ± ∞ ¹
AddPolicySmall                                      6.000 ± ∞ ¹
AddPolicyMedium                                     7.000 ± ∞ ¹
AddPolicyLarge                                      9.000 ± ∞ ¹
RemovePolicySmall                                   7.000 ± ∞ ¹
RemovePolicyMedium                                  7.000 ± ∞ ¹
RemovePolicyLarge                                   8.000 ± ∞ ¹
Raw                                                 0.000 ± ∞ ¹
BasicModel                                          18.00 ± ∞ ¹
RBACModel                                           36.00 ± ∞ ¹
RBACModelSizes/small                                481.0 ± ∞ ¹
RBACModelSizes/medium                              4.829k ± ∞ ¹
RBACModelSizes/large                               48.12k ± ∞ ¹
RBACModelSmall                                      616.0 ± ∞ ¹
RBACModelMedium                                    6.016k ± ∞ ¹
RBACModelLarge                                     60.08k ± ∞ ¹
RBACModelWithResourceRoles                          28.00 ± ∞ ¹
RBACModelWithDomains                                26.00 ± ∞ ¹
ABACModel                                           17.00 ± ∞ ¹
ABACRuleModel                                      37.09k ± ∞ ¹
KeyMatchModel                                       38.00 ± ∞ ¹
RBACModelWithDeny                                   50.00 ± ∞ ¹
PriorityModel                                       23.00 ± ∞ ¹
RBACModelWithDomainPatternLarge                     73.00 ± ∞ ¹
RoleManagerSmall                                    100.0 ± ∞ ¹
RoleManagerMedium                                  1.744k ± ∞ ¹
RoleManagerLarge                                   19.74k ± ∞ ¹
BuildRoleLinksWithPatternLarge                     3.560M ± ∞ ¹
BuildRoleLinksWithDomainPatternLarge               120.2k ± ∞ ¹
BuildRoleLinksWithPatternAndDomainPatternLarge     3.637M ± ∞ ¹
HasLinkWithPatternLarge                             9.000 ± ∞ ¹
HasLinkWithDomainPatternLarge                       1.000 ± ∞ ¹
HasLinkWithPatternAndDomainPatternLarge             9.000 ± ∞ ¹
ConcurrentHasLinkWithMatching                       11.00 ± ∞ ¹
geomean                                                                n/a (has zero)
¹ need >= 6 samples for confidence interval at level 0.95
² summaries must be >0 to compute geomean

🤖 This comment will be automatically updated with the latest benchmark results.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Reduces allocations in the enforce hot path by reusing policyEffects and matcherResults slices via sync.Pool, aiming to lower GC pressure under load.

Changes:

  • Added global sync.Pool instances and helper methods to reuse policyEffects and matcherResults buffers.
  • Updated enforce to borrow/return buffers instead of allocating slices per call.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@hsluoyz hsluoyz changed the title perf(enforce): reuse buffers with sync.Pool to reduce allocations feat: perf(enforce): reuse buffers with sync.Pool to reduce allocations Jan 26, 2026
@hsluoyz hsluoyz merged commit c1b0237 into apache:master Jan 26, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants