Skip to content

Commit 1796833

Browse files
committed
feat! Mimalloc as the default allocator
Using a custom allocator like Mimalloc brings upto 30% speed improvements for many workloads. Also added ACI benchmark to measure evaluation times. Signed-off-by: Anand Krishnamoorthi <[email protected]>
1 parent 9487def commit 1796833

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+16720
-14
lines changed

Cargo.lock

Lines changed: 21 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ http = []
3131
glob = ["dep:globset"]
3232
graph = []
3333
jsonschema = ["dep:jsonschema"]
34+
mimalloc = ["dep:mimalloc"]
3435
no_std = ["lazy_static/spin_no_std"]
3536
opa-runtime = []
3637
regex = ["dep:regex"]
@@ -49,6 +50,7 @@ full-opa = [
4950
"hex",
5051
"http",
5152
"jsonschema",
53+
"mimalloc",
5254
"opa-runtime",
5355
"regex",
5456
"semver",
@@ -109,6 +111,7 @@ rand = { version = "0.9.0", default-features = false, features = ["thread_rng"],
109111

110112
# Causes the project to link with the Spectre-mitigated CRT and libs.
111113
msvc_spectre_libs = { version = "0.1", features = ["error"], optional = true }
114+
mimalloc = { path = "mimalloc", optional = true }
112115

113116
[dev-dependencies]
114117
anyhow = "1.0.45"
@@ -148,6 +151,10 @@ test=false
148151
name = "regorus_benchmark"
149152
harness = false
150153

154+
[[bench]]
155+
name = "aci_benchmark"
156+
harness = false
157+
151158
[[example]]
152159
name="regorus"
153160
harness=false

README.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,84 @@ Benchmark 1: opa eval -b tests/aci -d tests/aci/data.json -i tests/aci/input.jso
274274
Range (min … max): 43.8 ms … 46.7 ms 62 runs
275275

276276
```
277+
278+
Note that the above comparison includes the overhead of parsing and processing policies as well as launching
279+
the regorus and opa executables each time. OPA is intended to preload the policies (bundle) beforehand and then evaluate
280+
the same policies on different inputs. See [details](https://github.com/open-policy-agent/opa/pull/7298).
281+
282+
Regorus microbenchmarks can be run for a deeper look:
283+
284+
```bash
285+
$ cargo bench --frozen aci
286+
Finished `bench` profile [optimized + debuginfo] target(s) in 0.40s
287+
Running unittests src/lib.rs (target/release/deps/regorus-9c0b72d40d272320)
288+
289+
running 0 tests
290+
291+
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 112 filtered out; finished in 0.00s
292+
293+
Running benches/aci_benchmark.rs (target/release/deps/aci_benchmark-9a0c12733454b523)
294+
Gnuplot not found, using plotters backend
295+
case /aci/mount_device data.policy.mount_device
296+
time: [11.539 µs 11.549 µs 11.562 µs]
297+
Found 18 outliers among 100 measurements (18.00%)
298+
7 (7.00%) high mild
299+
11 (11.00%) high severe
300+
301+
case /aci/mount_overlay data.policy.mount_overlay
302+
time: [27.436 µs 27.481 µs 27.550 µs]
303+
Found 11 outliers among 100 measurements (11.00%)
304+
2 (2.00%) high mild
305+
9 (9.00%) high severe
306+
307+
case /aci/scratch_mount data.policy.scratch_mount
308+
time: [7.1673 µs 7.1756 µs 7.1877 µs]
309+
Found 11 outliers among 100 measurements (11.00%)
310+
3 (3.00%) high mild
311+
8 (8.00%) high severe
312+
313+
case /aci/create_container data.policy.create_container
314+
time: [290.22 µs 290.52 µs 290.77 µs]
315+
Found 10 outliers among 100 measurements (10.00%)
316+
2 (2.00%) high mild
317+
8 (8.00%) high severe
318+
319+
case /aci/shutdown_container data.policy.shutdown_container
320+
time: [4.0729 µs 4.0886 µs 4.1024 µs]
321+
Found 8 outliers among 100 measurements (8.00%)
322+
4 (4.00%) high mild
323+
4 (4.00%) high severe
324+
325+
case /aci/scratch_unmount data.policy.scratch_unmount
326+
time: [3.4765 µs 3.4808 µs 3.4861 µs]
327+
Found 10 outliers among 100 measurements (10.00%)
328+
2 (2.00%) high mild
329+
8 (8.00%) high severe
330+
331+
case /aci/unmount_overlay data.policy.unmount_overlay
332+
time: [3.4646 µs 3.4793 µs 3.4958 µs]
333+
Found 28 outliers among 100 measurements (28.00%)
334+
16 (16.00%) low mild
335+
3 (3.00%) high mild
336+
9 (9.00%) high severe
337+
338+
case /aci/unmount_device data.policy.unmount_device
339+
time: [3.5041 µs 3.5080 µs 3.5120 µs]
340+
Found 14 outliers among 100 measurements (14.00%)
341+
2 (2.00%) high mild
342+
12 (12.00%) high severe
343+
344+
case /aci/load_fragment data.policy.load_fragment
345+
time: [45.028 µs 45.081 µs 45.130 µs]
346+
Found 26 outliers among 100 measurements (26.00%)
347+
16 (16.00%) low mild
348+
1 (1.00%) high mild
349+
9 (9.00%) high severe
350+
351+
Running benches/regorus_benchmark.rs (target/release/deps/regorus_benchmark-c6a3f929bb7168bc)
352+
```
353+
354+
277355
## OPA Conformance
278356
279357
Regorus has been verified to be compliant with [OPA v1.2.0](https://github.com/open-policy-agent/opa/releases/tag/v1.2.0)

benches/aci_benchmark.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
use regorus::{Engine, Value};
4+
5+
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
6+
use serde::{Deserialize, Serialize};
7+
use walkdir::WalkDir;
8+
9+
use std::path::Path;
10+
11+
#[derive(Serialize, Deserialize, PartialEq, Debug)]
12+
struct TestCase {
13+
note: String,
14+
data: Value,
15+
input: Value,
16+
modules: Vec<String>,
17+
query: String,
18+
want_result: Value,
19+
}
20+
21+
#[derive(Serialize, Deserialize, PartialEq, Debug)]
22+
struct YamlTest {
23+
cases: Vec<TestCase>,
24+
}
25+
26+
fn aci_policy_eval(c: &mut Criterion) {
27+
let dir = Path::new("tests/aci");
28+
for entry in WalkDir::new(dir)
29+
.sort_by_file_name()
30+
.into_iter()
31+
.filter_map(|e| e.ok())
32+
{
33+
let path = entry.path();
34+
if !path.to_string_lossy().ends_with(".yaml") {
35+
continue;
36+
}
37+
38+
let yaml = std::fs::read(path).expect("failed to read yaml test");
39+
let yaml = String::from_utf8_lossy(&yaml);
40+
let test: YamlTest = serde_yaml::from_str(&yaml).expect("failed to deserialize yaml test");
41+
42+
for case in &test.cases {
43+
let rule = case.query.replace("=x", "");
44+
c.bench_with_input(
45+
BenchmarkId::new("case ", format!("{} {}", &case.note, &rule)),
46+
&case,
47+
|b, case| {
48+
let mut engine = Engine::new();
49+
engine.set_rego_v0(true);
50+
51+
engine
52+
.add_data(case.data.clone())
53+
.expect("failed to add data");
54+
engine.set_input(case.input.clone());
55+
56+
for (idx, rego) in case.modules.iter().enumerate() {
57+
if rego.ends_with(".rego") {
58+
let path = dir.join(rego);
59+
let path = path.to_str().expect("not a valid path");
60+
engine
61+
.add_policy_from_file(path)
62+
.expect("failed to add policy");
63+
} else {
64+
engine
65+
.add_policy(format!("rego{idx}.rego"), rego.clone())
66+
.expect("failed to add policy");
67+
}
68+
}
69+
70+
b.iter(|| {
71+
engine.eval_rule(rule.clone()).unwrap();
72+
})
73+
},
74+
);
75+
}
76+
}
77+
}
78+
79+
criterion_group!(aci_benches, aci_policy_eval);
80+
criterion_main!(aci_benches);

benches/regorus_benchmark.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::hint::black_box;
22

3-
use regorus::Engine;
3+
use regorus::{Engine, Value};
44

55
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
66
use serde_json::json;
@@ -93,9 +93,44 @@ fn allow_with_simple_membership(c: &mut Criterion) {
9393
group.finish();
9494
}
9595

96+
fn aci_policy_eval(c: &mut Criterion) {
97+
let mut group = c.benchmark_group("ACI Policy Eval");
98+
let rules = ["data.policy.mount_overlay", "data.policy.mount_device"];
99+
for rule in rules {
100+
group.bench_with_input(BenchmarkId::new("rule", rule), &rule, |b, rule| {
101+
let mut engine = Engine::new();
102+
engine.set_rego_v0(true);
103+
104+
engine
105+
.add_policy_from_file("tests/aci/api.rego")
106+
.expect("failed to add api.rego");
107+
engine
108+
.add_policy_from_file("tests/aci/framework.rego")
109+
.expect("failed to add framework.rego");
110+
engine
111+
.add_policy_from_file("tests/aci/policy.rego")
112+
.expect("failed to add policy.rego");
113+
engine
114+
.add_data(
115+
Value::from_json_file("tests/aci/data.json").expect("failed to load data.json"),
116+
)
117+
.expect("failed to add data");
118+
let input =
119+
Value::from_json_file("tests/aci/input.json").expect("failed to load input.json");
120+
engine.set_input(input.clone());
121+
engine.eval_rule(rule.to_string()).unwrap();
122+
b.iter(|| {
123+
engine.eval_rule(rule.to_string()).unwrap();
124+
})
125+
});
126+
}
127+
group.finish();
128+
}
129+
96130
criterion_group!(
97131
benches,
98132
allow_with_simple_equality,
99-
allow_with_simple_membership
133+
allow_with_simple_membership,
134+
aci_policy_eval
100135
);
101136
criterion_main!(benches);

bindings/ffi/Cargo.lock

Lines changed: 21 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)