diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkABACModel.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkABACModel.java index ccc16629..493390b6 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkABACModel.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkABACModel.java @@ -25,10 +25,38 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for ABAC (Attribute-Based Access Control) model. + * + *
This benchmark tests ABAC authorization performance using attribute-based expressions. + * ABAC allows access decisions based on attributes of the subject, resource, and environment + * without requiring explicit policies for each permission combination. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Authorization Logic: + * The model uses attribute matching defined in the ABAC model configuration. + * Access is granted when the resource owner matches the requesting user. + * + *
Test Case: Enforce "alice", data1 (owned by "alice"), "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin ABAC Model + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkABACModel { - private static Enforcer e = new Enforcer("examples/abac_model.conf", "",false); + private static Enforcer e = new Enforcer("examples/abac_model.conf", "", false); private static ModelUnitTest.TestResource data1 = new ModelUnitTest.TestResource("data1", "alice"); public static void main(String args[]) throws RunnerException { @@ -36,9 +64,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkABACModel.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -46,8 +75,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkABACModel() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", data1, "read"); - } + e.enforce("alice", data1, "read"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkBasicModel.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkBasicModel.java index a50e1e2e..42a5fccc 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkBasicModel.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkBasicModel.java @@ -24,6 +24,34 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for ACL (Access Control List) model. + * + *
This benchmark tests basic ACL authorization performance with a simple subject-object-action policy. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Policy Structure: + *
+ * p, alice, data1, read + * p, bob, data2, write + *+ * + *
Test Case: Enforce "alice", "data1", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin ACL Model + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkBasicModel { @@ -34,9 +62,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkBasicModel.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,8 +73,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkBasicModel() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", "data1", "read"); - } + e.enforce("alice", "data1", "read"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkKeyMatchModel.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkKeyMatchModel.java index 0dfb16bd..d30ba038 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkKeyMatchModel.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkKeyMatchModel.java @@ -24,6 +24,39 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for RESTful/KeyMatch model. + * + *
This benchmark tests RESTful authorization performance with pattern matching. + * The KeyMatch model allows flexible URL pattern matching for RESTful APIs, + * supporting wildcards and path parameters. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Policy Structure: + *
+ * p, alice, /alice_data/*, GET + * p, alice, /alice_data/resource1, POST + * p, bob, /alice_data/resource2, GET + * p, bob, /bob_data/*, POST + * p, cathy, /cathy_data, (GET)|(POST) + *+ * + *
Test Case: Enforce "alice", "/alice_data/resource1", "GET" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin KeyMatch Functions + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkKeyMatchModel { @@ -34,9 +67,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkKeyMatchModel.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,8 +78,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkKeyMatchModel() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", "/alice_data/resource1", "GET"); - } + e.enforce("alice", "/alice_data/resource1", "GET"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkPriorityModel.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkPriorityModel.java index 18129381..fba6a7fb 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkPriorityModel.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkPriorityModel.java @@ -24,6 +24,44 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for priority-based model. + * + *
This benchmark tests priority-based authorization performance. + * The priority model allows policy evaluation based on explicit priority ordering, + * where higher priority policies override lower priority ones. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Policy Structure: + *
+ * p, alice, data1, read, allow + * p, data1_deny_group, data1, read, deny + * p, data1_deny_group, data1, write, deny + * p, alice, data1, write, allow + * g, alice, data1_deny_group + * p, data2_allow_group, data2, read, allow + * p, bob, data2, read, deny + * p, bob, data2, write, deny + * g, bob, data2_allow_group + *+ * + *
Test Case: Enforce "alice", "data1", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin Priority Model + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkPriorityModel { @@ -34,9 +72,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkPriorityModel.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,8 +83,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkPriorityModel() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", "data1", "read"); - } + e.enforce("alice", "data1", "read"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelLarge.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelLarge.java index c7a9b151..a7596454 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelLarge.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelLarge.java @@ -24,6 +24,38 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for RBAC model with large-scale data. + * + *
This benchmark tests RBAC authorization performance with a large dataset. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Generation Logic: + *
Test Case: Enforce "user50001", "data1500", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin RBAC Model + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkRBACModelLarge { @@ -33,10 +65,11 @@ public static void main(String args[]) throws RunnerException { Options opt = new OptionsBuilder() .include(BenchmarkRBACModelLarge.class.getName()) .exclude("Pref") - .warmupIterations(1) - .measurementIterations(1) + .warmupIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,19 +77,17 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkRBACModelLarge() { - for (int i = 0; i < 100000; i++) { - e.enforce("user50001", "data1500", "read"); - } + e.enforce("user50001", "data1500", "read"); } static { e.enableAutoBuildRoleLinks(false); // 10000 roles, 1000 resources. - e.enableAutoBuildRoleLinks(false); - for (int i=0;i<10000;i++) { + for (int i = 0; i < 10000; i++) { e.addPolicy(String.format("group%d", i), String.format("data%d", i/10), "read"); } - for (int i=0;i<100000;i++) { + // 100000 users. + for (int i = 0; i < 100000; i++) { e.addGroupingPolicy(String.format("user%d", i), String.format("group%d", i/10)); } e.buildRoleLinks(); diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelMedium.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelMedium.java index 0b24bd00..d77e6cc9 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelMedium.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelMedium.java @@ -24,6 +24,38 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for RBAC model with medium-scale data. + * + *
This benchmark tests RBAC authorization performance with a medium dataset. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Generation Logic: + *
Test Case: Enforce "user5001", "data150", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin RBAC Model + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkRBACModelMedium { @@ -34,9 +66,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkRBACModelMedium.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(1) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,19 +77,17 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkRBACModelMedium() { - for (int i = 0; i < 10000; i++) { - e.enforce("user5001", "data150", "read"); - } + e.enforce("user5001", "data150", "read"); } static { e.enableAutoBuildRoleLinks(false); // 1000 roles, 100 resources. - e.enableAutoBuildRoleLinks(false); - for (int i=0;i<1000;i++) { + for (int i = 0; i < 1000; i++) { e.addPolicy(String.format("group%d", i), String.format("data%d", i/10), "read"); } - for (int i=0;i<10000;i++) { + // 10000 users. + for (int i = 0; i < 10000; i++) { e.addGroupingPolicy(String.format("user%d", i), String.format("group%d", i/10)); } e.buildRoleLinks(); diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSingle.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSingle.java index 3d751941..d8a00f6e 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSingle.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSingle.java @@ -24,6 +24,38 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for basic RBAC (Role-Based Access Control) model. + * + *
This benchmark tests RBAC authorization performance with a single role assignment. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Policy Structure: + *
+ * p, alice, data1, read + * p, bob, data2, write + * p, data2_admin, data2, read + * p, data2_admin, data2, write + * g, alice, data2_admin + *+ * + *
Test Case: Enforce "alice", "data2", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin RBAC Model + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkRBACModelSingle { @@ -34,9 +66,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkRBACModelSingle.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,8 +77,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkRBACModel() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", "data2", "read"); - } + e.enforce("alice", "data2", "read"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSmall.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSmall.java index 18f60a06..462dacdb 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSmall.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelSmall.java @@ -24,6 +24,38 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for RBAC model with small-scale data. + * + *
This benchmark tests RBAC authorization performance with a small dataset. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Generation Logic: + *
Test Case: Enforce "user501", "data9", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin RBAC Model + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkRBACModelSmall { @@ -34,9 +66,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkRBACModelSmall.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(1) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,9 +77,7 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkRBACModelSmall() { - for (int i = 0; i < 1000; i++) { - e.enforce("user501", "data9", "read"); - } + e.enforce("user501", "data9", "read"); } static { diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDeny.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDeny.java index 5802a1b5..f8310f51 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDeny.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDeny.java @@ -24,6 +24,41 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for RBAC model with deny-override. + * + *
This benchmark tests RBAC authorization performance with explicit deny rules. + * The deny-override model allows explicit deny policies that take precedence over allow policies, + * enabling fine-grained access control. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Policy Structure: + *
+ * p, alice, data1, read, allow + * p, bob, data2, write, allow + * p, data2_admin, data2, read, allow + * p, data2_admin, data2, write, allow + * p, alice, data2, write, deny + * g, alice, data2_admin + *+ * + *
Test Case: Enforce "alice", "data1", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin RBAC with Deny + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkRBACModelWithDeny { @@ -34,9 +69,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkRBACModelWithDeny.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,8 +80,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkRBACModelWithDeny() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", "data1", "read"); - } + e.enforce("alice", "data1", "read"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDomains.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDomains.java index d6f581f6..bb2b0c22 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDomains.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithDomains.java @@ -24,6 +24,41 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for RBAC model with domains/tenants. + * + *
This benchmark tests RBAC authorization performance with multi-tenancy support. + * Domains (also called tenants) allow isolating permissions across different organizational units. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Policy Structure: + *
+ * p, admin, domain1, data1, read + * p, admin, domain1, data1, write + * p, admin, domain2, data2, read + * p, admin, domain2, data2, write + * g, alice, admin, domain1 + * g, bob, admin, domain2 + *+ * + *
Test Case: Enforce "alice", "domain1", "data1", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin RBAC with Domains + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkRBACModelWithDomains { @@ -34,9 +69,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkRBACModelWithDomains.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,8 +80,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkRBACModelWithDomains() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", "domain1", "data1", "read"); - } + e.enforce("alice", "domain1", "data1", "read"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithResourceRoles.java b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithResourceRoles.java index 61414979..9735d867 100644 --- a/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithResourceRoles.java +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/BenchmarkRBACModelWithResourceRoles.java @@ -24,6 +24,40 @@ import java.util.concurrent.TimeUnit; +/** + * Benchmark for RBAC model with resource roles. + * + *
This benchmark tests RBAC authorization performance with resource roles. + * Resource roles allow grouping resources into categories for easier permission management. + * The scenario uses deterministic policy generation to ensure reproducible results across runs. + * + *
Data Scale: + *
Policy Structure: + *
+ * p, alice, data1, read + * p, bob, data2, write + * p, data_group_admin, data_group, write + * g, alice, data_group_admin + * g2, data1, data_group + * g2, data2, data_group + *+ * + *
Test Case: Enforce "alice", "data1", "read" + * + *
Recommended JMH Options: + *
+ * -f 2 -wi 3 -i 5 -t 1 + * (2 forks, 3 warmup iterations, 5 measurement iterations, 1 thread) + *+ * + * @see Casbin RBAC with Resource Roles + */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class BenchmarkRBACModelWithResourceRoles { @@ -34,9 +68,10 @@ public static void main(String args[]) throws RunnerException { .include(BenchmarkRBACModelWithResourceRoles.class.getName()) .exclude("Pref") .warmupIterations(3) - .measurementIterations(3) + .measurementIterations(5) .addProfiler(GCProfiler.class) - .forks(1) + .forks(2) + .threads(1) .build(); new Runner(opt).run(); } @@ -44,8 +79,6 @@ public static void main(String args[]) throws RunnerException { @Threads(1) @Benchmark public static void benchmarkRBACModelWithResourceRoles() { - for (int i = 0; i < 1000; i++) { - e.enforce("alice", "data1", "read"); - } + e.enforce("alice", "data1", "read"); } } diff --git a/src/test/java/org/casbin/jcasbin/main/benchmark/README.md b/src/test/java/org/casbin/jcasbin/main/benchmark/README.md new file mode 100644 index 00000000..f0a9c4f2 --- /dev/null +++ b/src/test/java/org/casbin/jcasbin/main/benchmark/README.md @@ -0,0 +1,207 @@ +# JCasbin Benchmark Suite + +This directory contains the official JCasbin benchmark suite aligned with [go-casbin](https://github.com/casbin/casbin) standard benchmark scenarios. + +## Overview + +The benchmark suite tests authorization performance across different Casbin models and data scales. All benchmarks use deterministic data generation to ensure reproducible results across runs. + +## Benchmark Scenarios + +The following standard scenarios are implemented: + +| Scenario | Rules | Users | Roles | Resources/Domains | Description | +|----------|-------|-------|-------|------------------|-------------| +| **ACL** | 2 | 2 | - | - | Basic Access Control List | +| **RBAC** | 5 | 2 | 1 | - | Basic Role-Based Access Control | +| **RBAC Small** | 1,100 | 1,000 | 100 | 10 | Small-scale RBAC | +| **RBAC Medium** | 11,000 | 10,000 | 1,000 | 100 | Medium-scale RBAC | +| **RBAC Large** | 110,000 | 100,000 | 10,000 | 1,000 | Large-scale RBAC | +| **RBAC with Resource Roles** | 6 | 2 | 2 | - | RBAC with resource grouping | +| **RBAC with Domains** | 6 | 2 | 1 | 2 domains | Multi-tenant RBAC | +| **ABAC** | 0 | 0 | - | - | Attribute-Based Access Control | +| **RESTful/KeyMatch** | 5 | 3 | - | - | REST API pattern matching | +| **Deny-override** | 6 | 2 | 1 | - | RBAC with explicit deny | +| **Priority** | 9 | 2 | 2 | - | Priority-based authorization | + +## Running Benchmarks + +### Prerequisites + +- JDK 8 or higher +- Maven 3.x + +### Running All Benchmarks + +```bash +# Using Maven +mvn clean test-compile exec:java -Dexec.mainClass="org.openjdk.jmh.Main" -Dexec.classpathScope=test + +# Or build and run JMH benchmark JAR +mvn clean package +java -jar target/benchmarks.jar +``` + +### Running a Specific Benchmark + +```bash +# Run a single benchmark class +mvn clean test-compile exec:java -Dexec.mainClass="org.casbin.jcasbin.main.benchmark.BenchmarkBasicModel" -Dexec.classpathScope=test + +# Or using JMH pattern matching +java -jar target/benchmarks.jar BenchmarkBasicModel +``` + +### Recommended JMH Parameters + +All benchmarks are configured with the following recommended parameters to match go-casbin benchmark behavior: + +``` +-f 2 # 2 forks +-wi 3 # 3 warmup iterations +-i 5 # 5 measurement iterations +-t 1 # 1 thread +``` + +These can be overridden when running benchmarks: + +```bash +java -jar target/benchmarks.jar -f 1 -wi 5 -i 10 +``` + +## Benchmark Classes + +### BenchmarkBasicModel (ACL) +- **File**: `BenchmarkBasicModel.java` +- **Model**: ACL (Access Control List) +- **Scale**: 2 rules, 2 users +- **Test**: `enforce("alice", "data1", "read")` + +### BenchmarkRBACModelSingle (RBAC) +- **File**: `BenchmarkRBACModelSingle.java` +- **Model**: Basic RBAC +- **Scale**: 5 rules (4 policies + 1 role assignment), 2 users, 1 role +- **Test**: `enforce("alice", "data2", "read")` + +### BenchmarkRBACModelSmall +- **File**: `BenchmarkRBACModelSmall.java` +- **Model**: RBAC with small dataset +- **Scale**: 1,100 rules, 1,000 users, 100 roles, 10 resources +- **Test**: `enforce("user501", "data9", "read")` +- **Generation**: Every 10 roles → 1 resource, Every 10 users → 1 role + +### BenchmarkRBACModelMedium +- **File**: `BenchmarkRBACModelMedium.java` +- **Model**: RBAC with medium dataset +- **Scale**: 11,000 rules, 10,000 users, 1,000 roles, 100 resources +- **Test**: `enforce("user5001", "data150", "read")` +- **Generation**: Every 10 roles → 1 resource, Every 10 users → 1 role + +### BenchmarkRBACModelLarge +- **File**: `BenchmarkRBACModelLarge.java` +- **Model**: RBAC with large dataset +- **Scale**: 110,000 rules, 100,000 users, 10,000 roles, 1,000 resources +- **Test**: `enforce("user50001", "data1500", "read")` +- **Generation**: Every 10 roles → 1 resource, Every 10 users → 1 role + +### BenchmarkRBACModelWithResourceRoles +- **File**: `BenchmarkRBACModelWithResourceRoles.java` +- **Model**: RBAC with resource roles +- **Scale**: 6 rules, 2 users, 2 roles +- **Test**: `enforce("alice", "data1", "read")` + +### BenchmarkRBACModelWithDomains +- **File**: `BenchmarkRBACModelWithDomains.java` +- **Model**: RBAC with multi-tenancy +- **Scale**: 6 rules, 2 users, 1 role, 2 domains +- **Test**: `enforce("alice", "domain1", "data1", "read")` + +### BenchmarkABACModel +- **File**: `BenchmarkABACModel.java` +- **Model**: ABAC (Attribute-Based Access Control) +- **Scale**: 0 rules (attribute-based logic in model) +- **Test**: `enforce("alice", data1, "read")` + +### BenchmarkKeyMatchModel (RESTful) +- **File**: `BenchmarkKeyMatchModel.java` +- **Model**: RESTful with pattern matching +- **Scale**: 5 rules, 3 users +- **Test**: `enforce("alice", "/alice_data/resource1", "GET")` + +### BenchmarkRBACModelWithDeny (Deny-override) +- **File**: `BenchmarkRBACModelWithDeny.java` +- **Model**: RBAC with explicit deny +- **Scale**: 6 rules (5 policies + 1 role assignment), 2 users, 1 role +- **Test**: `enforce("alice", "data1", "read")` + +### BenchmarkPriorityModel +- **File**: `BenchmarkPriorityModel.java` +- **Model**: Priority-based authorization +- **Scale**: 9 rules (7 policies + 2 role assignments), 2 users, 2 roles +- **Test**: `enforce("alice", "data1", "read")` + +## Deterministic Data Generation + +All benchmarks use deterministic policy generation to ensure identical results across runs: + +- No randomness in data generation +- Loop counters use integer division for predictable patterns +- Static initialization blocks generate policies before benchmarking +- User/role/resource names follow consistent patterns: `user{i}`, `group{i}`, `data{i}` + +Example from RBAC Small: +```java +// 100 roles, 10 resources +for (int i = 0; i < 100; i++) { + e.addPolicy(String.format("group%d", i), String.format("data%d", i/10), "read"); +} +// 1000 users +for (int i = 0; i < 1000; i++) { + e.addGroupingPolicy(String.format("user%d", i), String.format("group%d", i/10)); +} +``` + +## JMH Configuration + +All benchmarks use the following JMH annotations: + +```java +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@BenchmarkMode(Mode.AverageTime) +@Threads(1) +``` + +This configuration measures average execution time per operation in milliseconds, similar to Go's `ns/op` metric. + +## Comparison with go-casbin + +These benchmarks are designed to be directly comparable with [go-casbin benchmarks](https://github.com/casbin/casbin/tree/master/benchmarks): + +- Identical data scales +- Same policy generation logic +- Same test cases (user, resource, action) +- Consistent naming conventions + +This allows for fair performance comparisons between JCasbin and go-casbin implementations. + +## Contributing + +When adding new benchmarks: + +1. Follow the naming convention: `Benchmark