From 87a7e44fcfaf2056dfa1191477e02ed225063286 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Wed, 09 Nov 2022 23:33:37 +0000 Subject: [PATCH] perf: destruct capacity hints --- --- a/crates/jrsonnet-evaluator/src/function/parse.rs +++ b/crates/jrsonnet-evaluator/src/function/parse.rs @@ -44,7 +44,8 @@ args: &dyn ArgsLike, tailstrict: bool, ) -> Result { - let mut passed_args = GcHashMap::with_capacity(params.len()); + let mut passed_args = + GcHashMap::with_capacity(params.iter().map(|p| p.0.capacity_hint()).sum()); if args.unnamed_len() > params.len() { throw!(TooManyArgsFunctionHas( params.len(), @@ -83,8 +84,10 @@ // Some args are unset, but maybe we have defaults for them // Default values should be created in newly created context let fctx = Context::new_future(); - let mut defaults = - GcHashMap::with_capacity(params.len() - filled_named - filled_positionals); + let mut defaults = GcHashMap::with_capacity( + params.iter().map(|p| p.0.capacity_hint()).sum::() + - filled_named - filled_positionals, + ); for (idx, param) in params.iter().enumerate().filter(|p| p.1 .1.is_some()) { if let Some(name) = param.0.name() { @@ -241,7 +244,7 @@ let fctx = Context::new_future(); - let mut bindings = GcHashMap::new(); + let mut bindings = GcHashMap::with_capacity(params.iter().map(|p| p.0.capacity_hint()).sum()); for param in params.iter() { if let Some(v) = ¶m.1 { --- a/crates/jrsonnet-parser/src/expr.rs +++ b/crates/jrsonnet-parser/src/expr.rs @@ -228,6 +228,39 @@ _ => None, } } + pub fn capacity_hint(&self) -> usize { + #[cfg(feature = "exp-destruct")] + fn cap_rest(rest: &Option) -> usize { + match rest { + Some(DestructRest::Keep(_)) => 1, + Some(DestructRest::Drop) => 0, + None => 0, + } + } + match self { + Self::Full(_) => 1, + #[cfg(feature = "exp-destruct")] + Self::Skip => 0, + #[cfg(feature = "exp-destruct")] + Self::Array { start, rest, end } => { + start.iter().map(Destruct::capacity_hint).sum::() + + end.iter().map(Destruct::capacity_hint).sum::() + + cap_rest(rest) + } + #[cfg(feature = "exp-destruct")] + Self::Object { fields, rest } => { + let mut out = 0; + for (_, into, _) in fields { + match into { + Some(v) => out += v.capacity_hint(), + // Field is destructured to default name + None => out += 1, + } + } + out + cap_rest(rest) + } + } + } } #[cfg_attr(feature = "structdump", derive(Codegen))] @@ -244,6 +277,14 @@ value: LocExpr, }, } +impl BindSpec { + pub fn capacity_hint(&self) -> usize { + match self { + BindSpec::Field { into, .. } => into.capacity_hint(), + BindSpec::Function { .. } => 1, + } + } +} #[cfg_attr(feature = "structdump", derive(Codegen))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -- gitstuff