diff --git a/benches/display_value.rs b/benches/display_value.rs new file mode 100644 index 0000000..4b0a1c7 --- /dev/null +++ b/benches/display_value.rs @@ -0,0 +1,29 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use expression_engine::Value; + +fn bench_display_value(c: &mut Criterion) { + let mut list = Vec::new(); + for i in 0..10 { + list.push(Value::from(i)); + } + + let mut map = Vec::new(); + for i in 0..10 { + map.push((Value::from(format!("key{}", i)), Value::from(i))); + } + + let val = Value::List(vec![ + Value::from("hello"), + Value::from(42), + Value::from(true), + Value::List(list), + Value::Map(map), + ]); + + c.bench_function("display_value", |b| { + b.iter(|| format!("{}", black_box(&val))) + }); +} + +criterion_group!(benches, bench_display_value); +criterion_main!(benches); diff --git a/src/value.rs b/src/value.rs index d1b9133..5494866 100644 --- a/src/value.rs +++ b/src/value.rs @@ -13,29 +13,29 @@ pub enum Value { None, } +// Optimization: Write directly to `std::fmt::Formatter` instead of creating intermediate +// strings and calling `format!()` in a loop. +// Impact: Reduces heap allocations, avoiding O(N) allocations for Lists and Maps. #[cfg(not(tarpaulin_include))] impl fmt::Display for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::String(val) => write!(f, "value string: {}", val.clone()), - Self::Number(val) => write!(f, "value number: {}", val.clone()), - Self::Bool(val) => write!(f, "value bool: {}", val.clone()), + Self::String(val) => write!(f, "value string: {}", val), + Self::Number(val) => write!(f, "value number: {}", val), + Self::Bool(val) => write!(f, "value bool: {}", val), Self::List(values) => { - let mut s = String::from("["); + write!(f, "value list: [")?; for value in values { - s.push_str(format!("{},", value.clone()).as_str()); + write!(f, "{},", value)?; } - s.push_str("]"); - write!(f, "value list: {}", s) + write!(f, "]") } Self::Map(m) => { - let mut s = String::from("{"); + write!(f, "value map: {{")?; for (k, v) in m { - s.push_str(format!("key: {},", k.clone()).as_str()); - s.push_str(format!("value: {}; ", v.clone()).as_str()); + write!(f, "key: {},value: {}; ", k, v)?; } - s.push_str("}"); - write!(f, "value map: {}", s) + write!(f, "}}") } Self::None => write!(f, "None"), }