Skip to content

chore(benchmark): align jcasbin benchmarks with go-casbin standard cases #472

@AKonnyaku

Description

@AKonnyaku

Role Definition

You will act as an experienced Java/JMH performance engineer, familiar with Casbin access-control models and the differences between Golang and Java.


Background

  • The official Casbin performance monitoring page lists multiple benchmark scenarios, including ACL, RBAC (large / medium / small), RBAC extended scenarios (resource roles, domains/tenants), ABAC, RESTful, Deny-override, and Priority.
    The table describes in detail the number of rules and objects for each scenario. For example:

    • RBAC small has 1100 rules (1000 users, 100 roles)
    • RBAC medium has 11000 rules (10000 users, 1000 roles)
    • RBAC large has 110000 rules
  • The current jcasbin repository contains only part of the JMH benchmark tests.
    The number of cases and their generation logic are not consistent with go-casbin, which makes fair horizontal comparison impossible.

  • We need to complete the missing benchmark scenarios in jcasbin and implement deterministic generation logic, so that anyone running the benchmarks with the same command can obtain identical results.


Task Requirements


1. Analyze go-casbin benchmark cases

Identify and implement all of the following standard benchmark scenarios (this is the full required scenario set). For each scenario, treat the rule size and object counts below as canonical and ensure the Java-side benchmark matches these scales:

  • ACL: 2 rules (2 users)
  • RBAC: 5 rules (2 users, 1 role)
  • RBAC (small): 1100 rules (1000 users, 100 roles)
  • RBAC (medium): 11000 rules (10000 users, 1000 roles)
  • RBAC (large): 110000 rules (100000 users, 10000 roles)
  • RBAC with resource roles: 6 rules (2 users, 2 roles)
  • RBAC with domains/tenants: 6 rules (2 users, 1 role, 2 domains)
  • ABAC: 0 rule (0 user)
  • RESTful: 5 rules (3 users)
  • Deny-override: 6 rules (2 users, 1 role)
  • Priority: 9 rules (2 users, 2 roles)

Make sure the implementation work that follows uses this list as the authoritative checklist of what must exist in jcasbin (either already present or newly added), and that each scenario’s benchmark logic and data scale match the counts above exactly.


2. Compare existing jcasbin benchmark cases

Search the jcasbin repository for existing JMH benchmark classes and identify:

  • Scenarios that are missing
  • Scenarios whose names do not match the go-casbin naming

For missing scenarios, new classes must be added.
For inconsistently named scenarios, class names must be adjusted to align with go-casbin.


3. Generate Java benchmark logic

  • Use OpenJDK JMH (org.openjdk.jmh) as the benchmarking framework.
  • Use @State(Scope.Benchmark) to manage the Enforcer instance and data initialization.

For each scenario, deterministically generate policies and role/user relationships according to go-casbin logic:

  • ACL

    • 2 rules, 2 users
    • Load directly via addPolicy and addGroupingPolicy
  • RBAC

    • 5 rules (2 users, 1 role)
  • RBAC small

    • Generate 100 roles, 1000 users, and 10 resources
    • Bind every 10 roles to 1 resource
    • Bind every 10 users to 1 role
    • Loop counts must exactly match the Go code
  • RBAC medium / large

    • Expand to 1000 roles / 10000 users and 10000 roles / 100000 users respectively
    • Loop logic remains unchanged; only counters differ
  • RBAC with resource roles

    • 2 users, 2 roles, 6 rules
  • RBAC with domains/tenants

    • 2 users, 1 role, 2 domains
    • Pass the domain parameter to Enforcer.addGroupingPolicy
    • Match the go-casbin domain::user format
  • ABAC

    • No rules
    • Test enforce performance via attribute expressions defined in the model
    • On the Java side, construct an empty policy file and call enforce inside the @Benchmark method
  • RESTful

    • 3 users
    • 5 REST-style rules (including HTTP method and path)
  • Deny-override and Priority

    • Implement deny-first and priority-based decisions according to policy ordering in the Go code

Each class must provide one @Benchmark method that calls enforce with the same parameters used in Go
(e.g. RBAC small must always use user501, data9).

No randomness is allowed.
Loop variables must generate strings using integer division, ensuring the generated data is bit-for-bit identical.


4. Execution parameters and reproducibility guarantees

  • In the benchmark class or README, specify the recommended JMH command:
-f 2 -wi 3 -i 5 -t 1

This means:

  • 2 forks
  • 3 warm-up iterations
  • 5 measurement iterations
  • single thread

These settings reduce noise and approximate the behavior of:

go test -bench=. -benchmem
  • On each @Benchmark, use:

    • @BenchmarkMode(Mode.AverageTime)
    • @OutputTimeUnit(TimeUnit.MILLISECONDS)
  • Add comments explaining that this is a conversion from Go’s ns/op

  • Instruct contributors to run:

    • mvn clean install -Pbenchmark
    • or ./mvnw
      to execute benchmarks and collect results

5. Output

In the Pull Request, submit all new or modified JMH benchmark classes under:

src/test/java/org/casbin/jcasbin/benchmark/

Ensure:

  • All existing unit tests pass
  • Newly added benchmarks do not affect CI

Notes

  • Do not modify Enforcer source code in benchmark classes
    Only use public APIs:

    • addPolicy
    • addGroupingPolicy
    • buildRoleLinks
    • enforce
  • According to the implementation of DefaultRoleManager.addLink on GitHub, role linking only performs simple role associations.
    Therefore, all loop-based generation logic must be implemented inside the benchmark classes themselves.

  • All newly created classes must include complete class-level Javadoc, explaining:

    • scenario name
    • data scale
      This is required to facilitate future migration to other language implementations.
  • Follow jcasbin code style strictly.
    File naming must follow the format:

Benchmark<Scenario>.java

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions