Fine tune hash map sizes.
This commit is contained in:
parent
bde8917ed4
commit
c919ee4e46
@ -259,7 +259,7 @@ impl Module {
|
||||
let mut mod_all = mod_all.unwrap();
|
||||
let mod_name = mod_all.ident.clone();
|
||||
let (_, orig_content) = mod_all.content.take().unwrap();
|
||||
let mod_attrs = mem::replace(&mut mod_all.attrs, Vec::with_capacity(0));
|
||||
let mod_attrs = mem::take(&mut mod_all.attrs);
|
||||
|
||||
if !params.skip {
|
||||
// Generate new module items.
|
||||
|
20
src/ast.rs
20
src/ast.rs
@ -16,10 +16,10 @@ use crate::FLOAT;
|
||||
use crate::engine::Imports;
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
use crate::engine::TYPICAL_ARRAY_SIZE;
|
||||
use crate::{engine::TYPICAL_ARRAY_SIZE, Array};
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
use crate::engine::TYPICAL_MAP_SIZE;
|
||||
use crate::{engine::TYPICAL_MAP_SIZE, Map};
|
||||
|
||||
use crate::stdlib::{
|
||||
borrow::Cow,
|
||||
@ -129,7 +129,7 @@ impl fmt::Display for ScriptFnDef {
|
||||
/// # Thread Safety
|
||||
///
|
||||
/// Currently, `AST` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AST(
|
||||
/// Global statements.
|
||||
Vec<Stmt>,
|
||||
@ -137,11 +137,17 @@ pub struct AST(
|
||||
Module,
|
||||
);
|
||||
|
||||
impl Default for AST {
|
||||
fn default() -> Self {
|
||||
Self(Vec::with_capacity(16), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl AST {
|
||||
/// Create a new `AST`.
|
||||
#[inline(always)]
|
||||
pub fn new(statements: Vec<Stmt>, lib: Module) -> Self {
|
||||
Self(statements, lib)
|
||||
pub fn new(statements: impl IntoIterator<Item = Stmt>, lib: Module) -> Self {
|
||||
Self(statements.into_iter().collect(), lib)
|
||||
}
|
||||
/// Get the statements.
|
||||
#[cfg(not(feature = "internals"))]
|
||||
@ -937,14 +943,14 @@ impl Expr {
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Self::Array(x, _) if self.is_constant() => {
|
||||
let mut arr = Vec::with_capacity(max(TYPICAL_ARRAY_SIZE, x.len()));
|
||||
let mut arr = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, x.len()));
|
||||
arr.extend(x.iter().map(|v| v.get_constant_value().unwrap()));
|
||||
Dynamic(Union::Array(Box::new(arr)))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Self::Map(x, _) if self.is_constant() => {
|
||||
let mut map = HashMap::with_capacity(max(TYPICAL_MAP_SIZE, x.len()));
|
||||
let mut map = Map::with_capacity(max(TYPICAL_MAP_SIZE, x.len()));
|
||||
map.extend(
|
||||
x.iter()
|
||||
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap())),
|
||||
|
@ -720,10 +720,10 @@ impl Engine {
|
||||
#[cfg(any(feature = "no_std", target_arch = "wasm32",))]
|
||||
module_resolver: None,
|
||||
|
||||
type_names: HashMap::with_capacity(8),
|
||||
disabled_symbols: HashSet::with_capacity(4),
|
||||
custom_keywords: HashMap::with_capacity(4),
|
||||
custom_syntax: HashMap::with_capacity(4),
|
||||
type_names: Default::default(),
|
||||
disabled_symbols: Default::default(),
|
||||
custom_keywords: Default::default(),
|
||||
custom_syntax: Default::default(),
|
||||
|
||||
// variable resolver
|
||||
resolve_var: None,
|
||||
@ -777,10 +777,10 @@ impl Engine {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
module_resolver: None,
|
||||
|
||||
type_names: HashMap::with_capacity(8),
|
||||
disabled_symbols: HashSet::with_capacity(4),
|
||||
custom_keywords: HashMap::with_capacity(4),
|
||||
custom_syntax: HashMap::with_capacity(4),
|
||||
type_names: Default::default(),
|
||||
disabled_symbols: Default::default(),
|
||||
custom_keywords: Default::default(),
|
||||
custom_syntax: Default::default(),
|
||||
|
||||
resolve_var: None,
|
||||
|
||||
@ -1726,7 +1726,7 @@ impl Engine {
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Expr::Array(x, _) => {
|
||||
let mut arr = Vec::with_capacity(max(TYPICAL_ARRAY_SIZE, x.len()));
|
||||
let mut arr = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, x.len()));
|
||||
for item in x.as_ref() {
|
||||
arr.push(self.eval_expr(scope, mods, state, lib, this_ptr, item, level)?);
|
||||
}
|
||||
@ -1735,7 +1735,7 @@ impl Engine {
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Expr::Map(x, _) => {
|
||||
let mut map = HashMap::with_capacity(max(TYPICAL_MAP_SIZE, x.len()));
|
||||
let mut map = Map::with_capacity(max(TYPICAL_MAP_SIZE, x.len()));
|
||||
for (IdentX { name: key, .. }, expr) in x.as_ref() {
|
||||
map.insert(
|
||||
key.clone(),
|
||||
|
@ -81,12 +81,12 @@ pub struct Module {
|
||||
impl Default for Module {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
modules: HashMap::with_capacity(4),
|
||||
variables: HashMap::with_capacity(4),
|
||||
all_variables: HashMap::with_capacity_and_hasher(32, StraightHasherBuilder),
|
||||
modules: Default::default(),
|
||||
variables: Default::default(),
|
||||
all_variables: Default::default(),
|
||||
functions: HashMap::with_capacity_and_hasher(64, StraightHasherBuilder),
|
||||
all_functions: HashMap::with_capacity_and_hasher(256, StraightHasherBuilder),
|
||||
type_iterators: HashMap::with_capacity(4),
|
||||
type_iterators: Default::default(),
|
||||
indexed: false,
|
||||
}
|
||||
}
|
||||
@ -1477,8 +1477,8 @@ impl Module {
|
||||
|
||||
if !self.indexed {
|
||||
let mut qualifiers = Vec::with_capacity(4);
|
||||
let mut variables = Vec::with_capacity(8);
|
||||
let mut functions = Vec::with_capacity(16);
|
||||
let mut variables = Vec::with_capacity(16);
|
||||
let mut functions = Vec::with_capacity(256);
|
||||
|
||||
qualifiers.push("root");
|
||||
|
||||
|
@ -753,7 +753,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
||||
}
|
||||
|
||||
fn optimize(
|
||||
statements: Vec<Stmt>,
|
||||
mut statements: Vec<Stmt>,
|
||||
engine: &Engine,
|
||||
scope: &Scope,
|
||||
lib: &[&Module],
|
||||
@ -761,6 +761,7 @@ fn optimize(
|
||||
) -> Vec<Stmt> {
|
||||
// If optimization level is None then skip optimizing
|
||||
if level == OptimizationLevel::None {
|
||||
statements.shrink_to_fit();
|
||||
return statements;
|
||||
}
|
||||
|
||||
@ -779,16 +780,14 @@ fn optimize(
|
||||
|
||||
let orig_constants_len = state.constants.len();
|
||||
|
||||
let mut result = statements;
|
||||
|
||||
// Optimization loop
|
||||
loop {
|
||||
state.reset();
|
||||
state.restore_constants(orig_constants_len);
|
||||
|
||||
let num_statements = result.len();
|
||||
let num_statements = statements.len();
|
||||
|
||||
result.iter_mut().enumerate().for_each(|(i, stmt)| {
|
||||
statements.iter_mut().enumerate().for_each(|(i, stmt)| {
|
||||
match stmt {
|
||||
Stmt::Const(var_def, expr, _, _) if expr.is_some() => {
|
||||
// Load constants
|
||||
@ -828,26 +827,27 @@ fn optimize(
|
||||
}
|
||||
|
||||
// Eliminate code that is pure but always keep the last statement
|
||||
let last_stmt = result.pop();
|
||||
let last_stmt = statements.pop();
|
||||
|
||||
// Remove all pure statements at global level
|
||||
result.retain(|stmt| !stmt.is_pure());
|
||||
statements.retain(|stmt| !stmt.is_pure());
|
||||
|
||||
// Add back the last statement unless it is a lone No-op
|
||||
if let Some(stmt) = last_stmt {
|
||||
if !result.is_empty() || !stmt.is_noop() {
|
||||
result.push(stmt);
|
||||
if !statements.is_empty() || !stmt.is_noop() {
|
||||
statements.push(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
statements.shrink_to_fit();
|
||||
statements
|
||||
}
|
||||
|
||||
/// Optimize an AST.
|
||||
pub fn optimize_into_ast(
|
||||
engine: &Engine,
|
||||
scope: &Scope,
|
||||
statements: Vec<Stmt>,
|
||||
mut statements: Vec<Stmt>,
|
||||
_functions: Vec<ScriptFnDef>,
|
||||
level: OptimizationLevel,
|
||||
) -> AST {
|
||||
@ -922,6 +922,8 @@ pub fn optimize_into_ast(
|
||||
#[cfg(feature = "no_function")]
|
||||
let lib = Default::default();
|
||||
|
||||
statements.shrink_to_fit();
|
||||
|
||||
AST::new(
|
||||
match level {
|
||||
OptimizationLevel::None => statements,
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use crate::def_package;
|
||||
use crate::dynamic::Dynamic;
|
||||
use crate::engine::{Array, OP_EQUALS};
|
||||
use crate::engine::{Array, OP_EQUALS, TYPICAL_ARRAY_SIZE};
|
||||
use crate::fn_native::{FnPtr, NativeCallContext};
|
||||
use crate::plugin::*;
|
||||
use crate::result::EvalAltResult;
|
||||
@ -14,7 +14,7 @@ use crate::INT;
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
use crate::engine::Map;
|
||||
|
||||
use crate::stdlib::{any::TypeId, boxed::Box, cmp::Ordering, string::ToString};
|
||||
use crate::stdlib::{any::TypeId, boxed::Box, cmp::max, cmp::Ordering, string::ToString};
|
||||
|
||||
pub type Unit = ();
|
||||
|
||||
@ -201,7 +201,7 @@ mod array_functions {
|
||||
list: &mut Array,
|
||||
mapper: FnPtr,
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let mut array = Array::with_capacity(list.len());
|
||||
let mut array = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
||||
|
||||
for (i, item) in list.iter().enumerate() {
|
||||
array.push(
|
||||
@ -233,7 +233,7 @@ mod array_functions {
|
||||
list: &mut Array,
|
||||
filter: FnPtr,
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let mut array = Array::with_capacity(list.len());
|
||||
let mut array = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
||||
|
||||
for (i, item) in list.iter().enumerate() {
|
||||
if filter
|
||||
@ -537,7 +537,7 @@ mod array_functions {
|
||||
list: &mut Array,
|
||||
filter: FnPtr,
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let mut drained = Array::with_capacity(list.len());
|
||||
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
||||
|
||||
let mut i = list.len();
|
||||
|
||||
@ -596,7 +596,7 @@ mod array_functions {
|
||||
list: &mut Array,
|
||||
filter: FnPtr,
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let mut drained = Array::with_capacity(list.len());
|
||||
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
||||
|
||||
let mut i = list.len();
|
||||
|
||||
|
@ -130,7 +130,7 @@ macro_rules! def_package {
|
||||
|
||||
impl $package {
|
||||
pub fn new() -> Self {
|
||||
let mut module = $root::Module::new_with_capacity(512);
|
||||
let mut module = $root::Module::new_with_capacity(1024);
|
||||
<Self as $root::packages::Package>::init(&mut module);
|
||||
Self(module.into())
|
||||
}
|
||||
|
@ -41,9 +41,6 @@ use crate::stdlib::{
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
use crate::stdlib::collections::HashSet;
|
||||
|
||||
type PERR = ParseErrorType;
|
||||
|
||||
type FunctionsLib = HashMap<u64, ScriptFnDef, StraightHasherBuilder>;
|
||||
@ -99,7 +96,7 @@ impl<'e> ParseState<'e> {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
max_function_expr_depth,
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
externals: HashMap::with_capacity(8),
|
||||
externals: Default::default(),
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
allow_capture: true,
|
||||
strings: HashMap::with_capacity(64),
|
||||
@ -2211,7 +2208,7 @@ fn parse_export(
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let mut exports = Vec::new();
|
||||
let mut exports = Vec::with_capacity(4);
|
||||
|
||||
loop {
|
||||
let (id, id_pos) = match input.next().unwrap() {
|
||||
@ -2279,7 +2276,7 @@ fn parse_block(
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut statements = Vec::new();
|
||||
let mut statements = Vec::with_capacity(8);
|
||||
let prev_stack_len = state.stack.len();
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
@ -2584,7 +2581,7 @@ fn parse_fn(
|
||||
(_, pos) => return Err(PERR::FnMissingParams(name).into_err(*pos)),
|
||||
};
|
||||
|
||||
let mut params = Vec::new();
|
||||
let mut params: StaticVec<_> = Default::default();
|
||||
|
||||
if !match_token(input, Token::RightParen).0 {
|
||||
let sep_err = format!("to separate the parameters of function '{}'", name);
|
||||
@ -2716,7 +2713,7 @@ fn parse_anon_fn(
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut params = Vec::new();
|
||||
let mut params: StaticVec<_> = Default::default();
|
||||
|
||||
if input.next().unwrap().0 != Token::Or {
|
||||
if !match_token(input, Token::Pipe).0 {
|
||||
@ -2800,7 +2797,7 @@ fn parse_anon_fn(
|
||||
access: FnAccess::Public,
|
||||
params,
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
externals: HashSet::with_capacity(4),
|
||||
externals: Default::default(),
|
||||
body,
|
||||
lib: None,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
@ -2877,8 +2874,8 @@ impl Engine {
|
||||
script_hash: u64,
|
||||
input: &mut TokenStream,
|
||||
) -> Result<(Vec<Stmt>, Vec<ScriptFnDef>), ParseError> {
|
||||
let mut statements: Vec<Stmt> = Default::default();
|
||||
let mut functions = Default::default();
|
||||
let mut statements = Vec::with_capacity(16);
|
||||
let mut functions = HashMap::with_capacity_and_hasher(16, StraightHasherBuilder);
|
||||
let mut state = ParseState::new(
|
||||
self,
|
||||
script_hash,
|
||||
|
12
src/scope.rs
12
src/scope.rs
@ -65,7 +65,7 @@ impl EntryType {
|
||||
//
|
||||
// Since `Dynamic` is reasonably small, packing it tightly improves cache locality when variables are accessed.
|
||||
// The variable type is packed separately into another array because it is even smaller.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Scope<'a> {
|
||||
/// Current value of the entry.
|
||||
values: Vec<Dynamic>,
|
||||
@ -75,6 +75,16 @@ pub struct Scope<'a> {
|
||||
names: Vec<(Cow<'a, str>, Box<StaticVec<String>>)>,
|
||||
}
|
||||
|
||||
impl Default for Scope<'_> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
values: Vec::with_capacity(16),
|
||||
types: Vec::with_capacity(16),
|
||||
names: Vec::with_capacity(16),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Scope<'a> {
|
||||
/// Create a new Scope.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user