Skip to content

Commit

Permalink
FF-3204 perf: compile regex during parsing (#31)
Browse files Browse the repository at this point in the history
* chore: add regex benchmark

* perf: compile regexes during configuration parsing
  • Loading branch information
rasendubi authored Sep 17, 2024
1 parent 7d6848f commit a92db5a
Show file tree
Hide file tree
Showing 7 changed files with 598 additions and 216 deletions.
29 changes: 29 additions & 0 deletions eppo_core/benches/evaluation_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,35 @@ fn criterion_benchmark(c: &mut Criterion) {
});
group.finish();
}

{
let mut group = c.benchmark_group("regex-flag");
group.throughput(Throughput::Elements(1));
let attributes = [("email".into(), "[email protected]".into())].into();
group.bench_function("get_assignment", |b| {
b.iter(|| {
get_assignment(
black_box(Some(&configuration)),
black_box("regex-flag"),
black_box("subject1"),
black_box(&attributes),
black_box(None),
)
})
});
group.bench_function("get_assignment_details", |b| {
b.iter(|| {
get_assignment_details(
black_box(Some(&configuration)),
black_box("regex-flag"),
black_box("subject1"),
black_box(&attributes),
black_box(None),
)
})
});
group.finish();
}
}

criterion_group!(
Expand Down
11 changes: 11 additions & 0 deletions eppo_core/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ pub enum AttributeValue {
/// A null value or absence of value.
Null,
}

impl AttributeValue {
pub fn as_str(&self) -> Option<&str> {
if let AttributeValue::String(s) = self {
Some(s.as_str())
} else {
None
}
}
}

impl From<&str> for AttributeValue {
fn from(value: &str) -> Self {
Self::String(value.to_owned())
Expand Down
4 changes: 2 additions & 2 deletions eppo_core/src/eval/eval_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};

use crate::{
error::{EvaluationError, EvaluationFailure},
ufc::{Condition, Shard, Value},
ufc::{ConditionWire, Shard, Value},
AttributeValue, Attributes,
};

Expand Down Expand Up @@ -135,7 +135,7 @@ pub struct RuleEvaluationDetails {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConditionEvaluationDetails {
pub condition: Condition,
pub condition: ConditionWire,
pub attribute_value: Option<AttributeValue>,
pub matched: bool,
}
Expand Down
18 changes: 16 additions & 2 deletions eppo_core/src/eval/eval_details_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use chrono::{DateTime, Utc};

use crate::{
error::EvaluationFailure,
ufc::{Allocation, Assignment, Condition, Flag, Rule, Shard, Split, Value, Variation},
ufc::{Allocation, Assignment, Condition, ConditionWire, Flag, Rule, Shard, Split, Value, Variation},
AttributeValue, Attributes, Configuration, EvaluationError,
};

Expand Down Expand Up @@ -384,11 +384,25 @@ impl<'a> EvalRuleVisitor for EvalRuleDetailsBuilder<'a> {
.conditions
.push(ConditionEvaluationDetails {
matched: result,
condition: condition.clone(),
condition: condition.clone().into(),
attribute_value: attribute_value.cloned(),
});
}

fn on_condition_skip(
&mut self,
condition: &serde_json::Value,
) {
let condition = match serde_json::from_value::<ConditionWire>(condition.clone()) {
Ok(condition_wire) => condition_wire,
Err(err) => {
log::warn!("condition cannot be parsed: {err:?}");
return;
}
};
self.rule_details.conditions.push(ConditionEvaluationDetails { condition, attribute_value: None, matched: false });
}

fn on_result(&mut self, result: bool) {
self.rule_details.matched = result;
}
Expand Down
Loading

0 comments on commit a92db5a

Please sign in to comment.