Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,27 @@ cucumber = "0.22.1"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
async-trait = "0.1"
glob = "0.3"
criterion = { version = "0.5", features = ["html_reports"] }

[[bench]]
name = "evaluation"
harness = false

[[bench]]
name = "operators"
harness = false

[[bench]]
name = "state"
harness = false

[[bench]]
name = "concurrency"
harness = false

[[bench]]
name = "comparison"
harness = false

[profile.release]
# Optimize for speed instead of size for better runtime performance
Expand Down
130 changes: 130 additions & 0 deletions benches/comparison.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//! Comparison benchmarks: DataLogic direct evaluation vs FlagEvaluator.
//!
//! Measures the overhead that FlagEvaluator adds on top of raw DataLogic
//! evaluation (state lookup, context enrichment with $flagd properties, etc.).

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use flagd_evaluator::{create_evaluator, FlagEvaluator, ValidationMode};
use serde_json::json;

/// Flag configuration for FlagEvaluator benchmarks.
const BENCH_CONFIG: &str = r#"{
"flags": {
"simpleFlag": {
"state": "ENABLED",
"variants": {
"on": true,
"off": false
},
"defaultVariant": "on"
},
"complexFlag": {
"state": "ENABLED",
"variants": {
"premium": "premium-tier",
"standard": "standard-tier",
"basic": "basic-tier"
},
"defaultVariant": "basic",
"targeting": {
"if": [
{"and": [
{"==": [{"var": "tier"}, "premium"]},
{">": [{"var": "score"}, 90]}
]},
"premium",
{"if": [
{"or": [
{"==": [{"var": "tier"}, "standard"]},
{">": [{"var": "score"}, 50]}
]},
"standard",
"basic"
]}
]
}
}
}
}"#;

// ---------------------------------------------------------------------------
// X1: Simple rule - DataLogic vs FlagEvaluator
// ---------------------------------------------------------------------------

/// X1a: Direct DataLogic evaluation of a trivial rule.
/// Measures the raw JSON Logic engine performance.
fn comparison_simple_datalogic(c: &mut Criterion) {
let logic = create_evaluator();
let rule = r#"{"==":[1,1]}"#;
let data = r#"{}"#;

c.bench_function("comparison_simple_datalogic", |b| {
b.iter(|| logic.evaluate_json(black_box(rule), black_box(data)))
});
}

/// X1b: FlagEvaluator evaluation of a simple (non-targeting) flag.
/// Measures DataLogic + state lookup + context enrichment overhead.
fn comparison_simple_flag_evaluator(c: &mut Criterion) {
let mut evaluator = FlagEvaluator::new(ValidationMode::Permissive);
evaluator.update_state(BENCH_CONFIG).unwrap();
let context = json!({});

c.bench_function("comparison_simple_flag_evaluator", |b| {
b.iter(|| evaluator.evaluate_flag(black_box("simpleFlag"), black_box(&context)))
});
}

// ---------------------------------------------------------------------------
// X2: Complex targeting rule - DataLogic vs FlagEvaluator
// ---------------------------------------------------------------------------

/// X2a: Direct DataLogic evaluation of the same complex targeting rule
/// used in the FlagEvaluator benchmark. The data includes $flagd properties
/// that would be injected by the evaluator, so the rule logic is equivalent.
fn comparison_complex_datalogic(c: &mut Criterion) {
let logic = create_evaluator();
let rule = r#"{
"if": [
{"and": [
{"==": [{"var": "tier"}, "premium"]},
{">": [{"var": "score"}, 90]}
]},
"premium",
{"if": [
{"or": [
{"==": [{"var": "tier"}, "standard"]},
{">": [{"var": "score"}, 50]}
]},
"standard",
"basic"
]}
]
}"#;
let data = r#"{"tier":"standard","score":75,"targetingKey":"","$flagd":{"flagKey":"complexFlag","timestamp":1700000000}}"#;

c.bench_function("comparison_complex_datalogic", |b| {
b.iter(|| logic.evaluate_json(black_box(rule), black_box(data)))
});
}

/// X2b: FlagEvaluator evaluation of a complex flag with nested targeting rules.
/// Includes state lookup, context enrichment, and variant resolution overhead.
fn comparison_complex_flag_evaluator(c: &mut Criterion) {
let mut evaluator = FlagEvaluator::new(ValidationMode::Permissive);
evaluator.update_state(BENCH_CONFIG).unwrap();
let context = json!({"tier": "standard", "score": 75});

c.bench_function("comparison_complex_flag_evaluator", |b| {
b.iter(|| evaluator.evaluate_flag(black_box("complexFlag"), black_box(&context)))
});
}

criterion_group!(
benches,
comparison_simple_datalogic,
comparison_simple_flag_evaluator,
comparison_complex_datalogic,
comparison_complex_flag_evaluator,
);
criterion_main!(benches);
Loading
Loading