From 61b0c7b2b3e2a88e638d0ef5ea09679802770fcb Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 12 Mar 2021 22:30:08 +0800 Subject: [PATCH] Optimize imports layout. --- src/engine.rs | 36 +++++++++++++++--------------------- src/fn_call.rs | 5 ++++- src/module/mod.rs | 25 +++++++++++-------------- src/token.rs | 12 ++++++------ 4 files changed, 36 insertions(+), 42 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 973cf56b..bcc06b83 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -53,7 +53,7 @@ pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical // the module name will live beyond the AST of the eval script text. // The best we can do is a shared reference. #[derive(Debug, Clone, Default)] -pub struct Imports(StaticVec<(ImmutableString, Shared)>); +pub struct Imports(StaticVec, StaticVec>); impl Imports { /// Get the length of this stack of imported [modules][Module]. @@ -69,7 +69,7 @@ impl Imports { /// Get the imported [modules][Module] at a particular index. #[inline(always)] pub fn get(&self, index: usize) -> Option> { - self.0.get(index).map(|(_, m)| m).cloned() + self.1.get(index).cloned() } /// Get the index of an imported [modules][Module] by name. #[inline(always)] @@ -78,18 +78,19 @@ impl Imports { .iter() .enumerate() .rev() - .find(|(_, (key, _))| key.as_str() == name) - .map(|(index, _)| index) + .find_map(|(i, key)| if key.as_str() == name { Some(i) } else { None }) } /// Push an imported [modules][Module] onto the stack. #[inline(always)] pub fn push(&mut self, name: impl Into, module: impl Into>) { - self.0.push((name.into(), module.into())); + self.0.push(name.into()); + self.1.push(module.into()); } /// Truncate the stack of imported [modules][Module] to a particular length. #[inline(always)] pub fn truncate(&mut self, size: usize) { self.0.truncate(size); + self.1.truncate(size); } /// Get an iterator to this stack of imported [modules][Module] in reverse order. #[allow(dead_code)] @@ -97,6 +98,7 @@ impl Imports { pub fn iter(&self) -> impl Iterator { self.0 .iter() + .zip(self.1.iter()) .rev() .map(|(name, module)| (name.as_str(), module.as_ref())) } @@ -104,52 +106,44 @@ impl Imports { #[allow(dead_code)] #[inline(always)] pub(crate) fn iter_raw(&self) -> impl Iterator)> { - self.0.iter().rev().map(|(n, m)| (n, m)) + self.0.iter().rev().zip(self.1.iter().rev()) } /// Get an iterator to this stack of imported [modules][Module] in forward order. #[allow(dead_code)] #[inline(always)] pub(crate) fn scan_raw(&self) -> impl Iterator)> { - self.0.iter().map(|(n, m)| (n, m)) + self.0.iter().zip(self.1.iter()) } /// Get a consuming iterator to this stack of imported [modules][Module] in reverse order. #[inline(always)] pub fn into_iter(self) -> impl Iterator)> { - self.0.into_iter().rev() - } - /// Add a stream of imported [modules][Module]. - #[inline(always)] - pub fn extend(&mut self, stream: impl Iterator)>) { - self.0.extend(stream) + self.0.into_iter().rev().zip(self.1.into_iter().rev()) } /// Does the specified function hash key exist in this stack of imported [modules][Module]? #[allow(dead_code)] #[inline(always)] pub fn contains_fn(&self, hash: u64) -> bool { - self.0.iter().any(|(_, m)| m.contains_qualified_fn(hash)) + self.1.iter().any(|m| m.contains_qualified_fn(hash)) } /// Get specified function via its hash key. #[inline(always)] pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&ImmutableString>)> { - self.0 + self.1 .iter() .rev() - .find_map(|(_, m)| m.get_qualified_fn(hash).map(|f| (f, m.id_raw()))) + .find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw()))) } /// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of /// imported [modules][Module]? #[allow(dead_code)] #[inline(always)] pub fn contains_iter(&self, id: TypeId) -> bool { - self.0.iter().any(|(_, m)| m.contains_qualified_iter(id)) + self.1.iter().any(|m| m.contains_qualified_iter(id)) } /// Get the specified [`TypeId`][std::any::TypeId] iterator. #[inline(always)] pub fn get_iter(&self, id: TypeId) -> Option { - self.0 - .iter() - .rev() - .find_map(|(_, m)| m.get_qualified_iter(id)) + self.1.iter().rev().find_map(|m| m.get_qualified_iter(id)) } } diff --git a/src/fn_call.rs b/src/fn_call.rs index 8a008ee1..f8a0d38f 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -539,7 +539,10 @@ impl Engine { #[cfg(not(feature = "no_module"))] if !fn_def.mods.is_empty() { - mods.extend(fn_def.mods.iter_raw().map(|(n, m)| (n.clone(), m.clone()))); + fn_def + .mods + .iter_raw() + .for_each(|(n, m)| mods.push(n.clone(), m.clone())); } // Evaluate the function diff --git a/src/module/mod.rs b/src/module/mod.rs index 7ff74104..18c7f3f1 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -1836,7 +1836,7 @@ impl Module { // Collect a particular module. fn index_module<'a>( module: &'a Module, - qualifiers: &mut Vec<&'a str>, + path: &mut Vec<&'a str>, variables: &mut HashMap, functions: &mut HashMap, type_iterators: &mut HashMap, @@ -1845,16 +1845,16 @@ impl Module { module.modules.iter().for_each(|(name, m)| { // Index all the sub-modules first. - qualifiers.push(name); - if index_module(m, qualifiers, variables, functions, type_iterators) { + path.push(name); + if index_module(m, path, variables, functions, type_iterators) { contains_indexed_global_functions = true; } - qualifiers.pop(); + path.pop(); }); // Index all variables module.variables.iter().for_each(|(var_name, value)| { - let hash_var = crate::calc_fn_hash(qualifiers.iter().map(|&v| v), var_name, 0); + let hash_var = crate::calc_fn_hash(path.iter().map(|&v| v), var_name, 0); variables.insert(hash_var, value.clone()); }); @@ -1880,15 +1880,12 @@ impl Module { } if !f.func.is_script() { - let hash_qualified_fn = calc_native_fn_hash( - qualifiers.iter().cloned(), - f.name.as_str(), - &f.param_types, - ); + let hash_qualified_fn = + calc_native_fn_hash(path.iter().cloned(), f.name.as_str(), &f.param_types); functions.insert(hash_qualified_fn, f.func.clone()); } else if cfg!(not(feature = "no_function")) { let hash_qualified_script = - crate::calc_fn_hash(qualifiers.iter().cloned(), f.name.as_str(), f.params); + crate::calc_fn_hash(path.iter().cloned(), f.name.as_str(), f.params); functions.insert(hash_qualified_script, f.func.clone()); } }); @@ -1897,16 +1894,16 @@ impl Module { } if !self.indexed { - let mut qualifiers = Vec::with_capacity(4); + let mut path = Vec::with_capacity(4); let mut variables = HashMap::with_capacity_and_hasher(16, StraightHasherBuilder); let mut functions = HashMap::with_capacity_and_hasher(256, StraightHasherBuilder); let mut type_iterators = HashMap::with_capacity(16); - qualifiers.push("root"); + path.push("root"); self.contains_indexed_global_functions = index_module( self, - &mut qualifiers, + &mut path, &mut variables, &mut functions, &mut type_iterators, diff --git a/src/token.rs b/src/token.rs index d0cdcf9e..0d68c460 100644 --- a/src/token.rs +++ b/src/token.rs @@ -840,8 +840,8 @@ pub fn parse_string_literal( pos: &mut Position, enclosing_char: char, ) -> Result { - let mut result: StaticVec = Default::default(); - let mut escape: StaticVec = Default::default(); + let mut result: smallvec::SmallVec<[char; 16]> = Default::default(); + let mut escape: smallvec::SmallVec<[char; 12]> = Default::default(); let start = *pos; @@ -1109,7 +1109,7 @@ fn get_next_token_inner( // digit ... ('0'..='9', _) => { - let mut result: StaticVec = Default::default(); + let mut result: smallvec::SmallVec<[char; 16]> = Default::default(); let mut radix_base: Option = None; let mut valid: fn(char) -> bool = is_numeric_digit; result.push(c); @@ -1596,7 +1596,7 @@ fn get_identifier( start_pos: Position, first_char: char, ) -> Option<(Token, Position)> { - let mut result: StaticVec<_> = Default::default(); + let mut result: smallvec::SmallVec<[char; 8]> = Default::default(); result.push(first_char); while let Some(next_char) = stream.peek_next() { @@ -1691,10 +1691,10 @@ pub fn is_id_continue(x: char) -> bool { pub struct MultiInputsStream<'a> { /// Buffered character, if any. buf: Option, - /// The input character streams. - streams: StaticVec>>, /// The current stream index. index: usize, + /// The input character streams. + streams: StaticVec>>, } impl InputStream for MultiInputsStream<'_> {