mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
dbba57f499
Introduce the notion of CompiledPolicy to hold stuff that remains immutable during evaluation - e.g. rules, function, schedules etc Cloning takes about 60 nano seconds for an engine loaded with ACI policies. Earlier it used to take 40 microseconds. Thus there is easily more than 100x speedup. Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
152 lines
4.4 KiB
Rust
152 lines
4.4 KiB
Rust
use std::hint::black_box;
|
|
|
|
use regorus::{Engine, Value};
|
|
|
|
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
|
use serde_json::json;
|
|
|
|
fn engine_with_policy(policy: &str) -> Engine {
|
|
let mut engine = Engine::new();
|
|
engine
|
|
.add_policy("policy.rego".to_string(), policy.to_string())
|
|
.unwrap();
|
|
engine
|
|
}
|
|
|
|
fn eval_principal(engine: &mut Engine) {
|
|
engine.set_input(black_box(json!({"principal": "admin"}).into()));
|
|
let result = engine
|
|
.eval_rule(black_box("data.bench.allow".to_string()))
|
|
.unwrap();
|
|
assert_eq!(result, true.into());
|
|
}
|
|
|
|
fn allow_with_simple_equality(c: &mut Criterion) {
|
|
c.bench_function("simple equality check with constant", |b| {
|
|
let mut engine = engine_with_policy(
|
|
r#"
|
|
package bench
|
|
allow if input.principal == "admin"
|
|
"#,
|
|
);
|
|
|
|
b.iter(|| eval_principal(&mut engine))
|
|
});
|
|
|
|
c.bench_function("simple equality check with data", |b| {
|
|
let mut engine = engine_with_policy(
|
|
r#"
|
|
package bench
|
|
allow if input.principal == data.allowed_principal
|
|
"#,
|
|
);
|
|
engine
|
|
.add_data(json!({"allowed_principal": "admin"}).into())
|
|
.unwrap();
|
|
|
|
b.iter(|| eval_principal(&mut engine))
|
|
});
|
|
}
|
|
|
|
fn allow_with_simple_membership(c: &mut Criterion) {
|
|
let generate_principals = |n: usize| {
|
|
(0..n)
|
|
.map(|i| i.to_string())
|
|
.chain(std::iter::once("admin".to_string()))
|
|
.collect::<Vec<_>>()
|
|
};
|
|
|
|
let mut group = c.benchmark_group("allow with simple membership");
|
|
for size in [32, 64, 128, 512, 1024, 2048].iter() {
|
|
group.bench_with_input(BenchmarkId::new("with constant", size), size, |b, &size| {
|
|
let principals = generate_principals(size).join("\",\"");
|
|
let mut engine = engine_with_policy(&format!(
|
|
r#"
|
|
package bench
|
|
|
|
allowed_principals := {{
|
|
"{principals}"
|
|
}}
|
|
|
|
allow if input.principal in allowed_principals
|
|
"#
|
|
));
|
|
|
|
b.iter(|| eval_principal(&mut engine))
|
|
});
|
|
|
|
group.bench_with_input(BenchmarkId::new("with data", size), size, |b, &size| {
|
|
let principals = generate_principals(size);
|
|
let mut engine = engine_with_policy(
|
|
r#"
|
|
package bench
|
|
allow if input.principal in data.allowed_principals
|
|
"#,
|
|
);
|
|
engine
|
|
.add_data(json!({"allowed_principals": principals}).into())
|
|
.unwrap();
|
|
|
|
b.iter(|| eval_principal(&mut engine))
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
fn clone(c: &mut Criterion) {
|
|
// Use Arc<BtreeMap> as a reference. Clone will only increment
|
|
// the reference count.
|
|
let mut m = std::collections::BTreeMap::default();
|
|
m.insert(1, 2);
|
|
let m = std::sync::Arc::new(m);
|
|
|
|
c.bench_function("clone: Arc<BTreeMap>", |b| {
|
|
b.iter(|| {
|
|
let _ = m.clone();
|
|
})
|
|
});
|
|
|
|
let mut engine = Engine::new();
|
|
engine.set_rego_v0(true);
|
|
engine
|
|
.add_policy_from_file("tests/aci/framework.rego")
|
|
.unwrap();
|
|
engine.add_policy_from_file("tests/aci/api.rego").unwrap();
|
|
engine
|
|
.add_policy_from_file("tests/aci/policy.rego")
|
|
.unwrap();
|
|
engine
|
|
.add_data(Value::from_json_file("tests/aci/data.json").expect("failed to load data.json"))
|
|
.expect("failed to add data");
|
|
engine.set_input(
|
|
Value::from_json_file("tests/aci/input.json").expect("failed to load input.json"),
|
|
);
|
|
|
|
// An engine without preparation will not have processed fields populated.
|
|
c.bench_function("clone: engine with aci policies", |b| {
|
|
b.iter(|| {
|
|
let _ = engine.clone();
|
|
})
|
|
});
|
|
|
|
// Trigger engine preparation.
|
|
let _ = engine.eval_query("data.framework.mount_overlay".to_string(), false);
|
|
|
|
// Prepared engine will have many more fields populated. But the fields are
|
|
// immutable after preparation and will be shared between clones.
|
|
c.bench_function("clone: prepared engine with aci policies", |b| {
|
|
b.iter(|| {
|
|
let _ = engine.clone();
|
|
})
|
|
});
|
|
}
|
|
|
|
criterion_group!(
|
|
benches,
|
|
allow_with_simple_equality,
|
|
allow_with_simple_membership,
|
|
clone
|
|
);
|
|
|
|
criterion_main!(benches);
|