difftreelog
perf add string extension threshold
in: master
2 files changed
crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth24 })24 })25}25}2627/// Arbitrary threshold282629pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {27pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {30 use Val::*;28 use Val::*;31 Ok(match (a, b) {29 Ok(match (a, b) {32 (Str(a), Str(b)) if a.is_empty() => Val::Str(b.clone()),33 (Str(a), Str(b)) if b.is_empty() => Val::Str(a.clone()),34 (Str(v1), Str(v2)) => Str(StrValue::concat(v1.clone(), v2.clone())),30 (Str(v1), Str(v2)) => Str(StrValue::concat(v1.clone(), v2.clone())),353136 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)32 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth199}199}200impl StrValue {200impl StrValue {201 pub fn concat(a: StrValue, b: StrValue) -> Self {201 pub fn concat(a: StrValue, b: StrValue) -> Self {202 // TODO: benchmark for an optimal value, currently just a arbitrary choice203 const STRING_EXTEND_THRESHOLD: usize = 100;204202 if a.is_empty() {205 if a.is_empty() {203 b206 b204 } else if b.is_empty() {207 } else if b.is_empty() {205 a208 a206 } else {209 } else if a.len() + b.len() < STRING_EXTEND_THRESHOLD {210 Self::Flat(format!("{a}{b}").into())211 } else {207 let len = a.len() + b.len();212 let len = a.len() + b.len();208 Self::Tree(Rc::new((a, b, len)))213 Self::Tree(Rc::new((a, b, len)))209 }214 }210 }215 }211 pub fn into_flat(self) -> IStr {216 pub fn into_flat(self) -> IStr {212 match self {217 #[cold]213 StrValue::Flat(f) => f,214 StrValue::Tree(_) => {215 let mut buf = String::new();216 self.into_flat_buf(&mut buf);217 buf.into()218 }219 }220 }221 fn into_flat_buf(&self, out: &mut String) {218 fn write_buf(s: &StrValue, out: &mut String) {222 match self {219 match s {223 StrValue::Flat(f) => out.push_str(f),220 StrValue::Flat(f) => out.push_str(f),224 StrValue::Tree(t) => {221 StrValue::Tree(t) => {225 t.0.into_flat_buf(out);222 write_buf(&t.0, out);226 t.1.into_flat_buf(out);223 write_buf(&t.1, out);227 }224 }228 }225 }229 }226 }227 match self {228 StrValue::Flat(f) => f,229 StrValue::Tree(_) => {230 let mut buf = String::with_capacity(self.len());231 write_buf(&self, &mut buf);232 buf.into()233 }234 }235 }230 pub fn len(&self) -> usize {236 pub fn len(&self) -> usize {231 match self {237 match self {232 StrValue::Flat(v) => v.len(),238 StrValue::Flat(v) => v.len(),236 pub fn is_empty(&self) -> bool {242 pub fn is_empty(&self) -> bool {237 match self {243 match self {238 Self::Flat(v) => v.is_empty(),244 Self::Flat(v) => v.is_empty(),245 // Can't create non-flat empty string239 _ => false,246 Self::Tree(_) => false,240 }247 }241 }248 }242}249}