Merge pull request #636 from quake/quake/StraightHashMap
perf: change BTreeMap to StraightHashMap
This commit is contained in:
commit
0f4df9c4e7
@ -27,6 +27,7 @@ rhai_codegen = { version = "1.4.1", path = "codegen", default-features = false }
|
|||||||
|
|
||||||
no-std-compat = { version = "0.4", default-features = false, features = ["alloc"], optional = true }
|
no-std-compat = { version = "0.4", default-features = false, features = ["alloc"], optional = true }
|
||||||
libm = { version = "0.2", default-features = false, optional = true }
|
libm = { version = "0.2", default-features = false, optional = true }
|
||||||
|
hashbrown = { version = "0.12", optional = true }
|
||||||
core-error = { version = "0.0", default-features = false, features = ["alloc"], optional = true }
|
core-error = { version = "0.0", default-features = false, features = ["alloc"], optional = true }
|
||||||
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"], optional = true }
|
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"], optional = true }
|
||||||
serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true }
|
serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true }
|
||||||
@ -63,7 +64,7 @@ debugging = ["internals"] # enable debugging
|
|||||||
serde = ["dep:serde", "smartstring/serde", "smallvec/serde"] # implement serde for rhai types
|
serde = ["dep:serde", "smartstring/serde", "smallvec/serde"] # implement serde for rhai types
|
||||||
|
|
||||||
# compiling for no-std
|
# compiling for no-std
|
||||||
no_std = ["no-std-compat", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng"]
|
no_std = ["no-std-compat", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng", "hashbrown"]
|
||||||
|
|
||||||
# compiling for WASM
|
# compiling for WASM
|
||||||
wasm-bindgen = ["instant/wasm-bindgen"]
|
wasm-bindgen = ["instant/wasm-bindgen"]
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
//! System caches.
|
//! System caches.
|
||||||
|
|
||||||
use crate::func::CallableFunction;
|
use crate::func::{CallableFunction, StraightHashMap};
|
||||||
use crate::{Identifier, StaticVec};
|
use crate::{Identifier, StaticVec};
|
||||||
|
use std::marker::PhantomData;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{collections::BTreeMap, marker::PhantomData};
|
|
||||||
|
|
||||||
/// _(internals)_ An entry in a function resolution cache.
|
/// _(internals)_ An entry in a function resolution cache.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
@ -21,7 +21,7 @@ pub struct FnResolutionCacheEntry {
|
|||||||
///
|
///
|
||||||
/// [`FnResolutionCacheEntry`] is [`Box`]ed in order to pack as many entries inside a single B-Tree
|
/// [`FnResolutionCacheEntry`] is [`Box`]ed in order to pack as many entries inside a single B-Tree
|
||||||
/// level as possible.
|
/// level as possible.
|
||||||
pub type FnResolutionCache = BTreeMap<u64, Option<FnResolutionCacheEntry>>;
|
pub type FnResolutionCache = StraightHashMap<u64, Option<FnResolutionCacheEntry>>;
|
||||||
|
|
||||||
/// _(internals)_ A type containing system-wide caches.
|
/// _(internals)_ A type containing system-wide caches.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
@ -66,7 +66,7 @@ impl Caches<'_> {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_fn_resolution_cache(&mut self) {
|
pub fn push_fn_resolution_cache(&mut self) {
|
||||||
self.fn_resolution.push(BTreeMap::new());
|
self.fn_resolution.push(StraightHashMap::default());
|
||||||
}
|
}
|
||||||
/// Rewind the function resolution caches stack to a particular size.
|
/// Rewind the function resolution caches stack to a particular size.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -11,8 +11,12 @@ use crate::func::{
|
|||||||
use crate::types::dynamic::AccessMode;
|
use crate::types::dynamic::AccessMode;
|
||||||
use crate::{Dynamic, Engine, Module, Position, RhaiResult, RhaiResultOf, Scope, ERR};
|
use crate::{Dynamic, Engine, Module, Position, RhaiResult, RhaiResultOf, Scope, ERR};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
|
use hashbrown::hash_map::Entry;
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
|
use std::num::NonZeroUsize;
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{collections::btree_map::Entry, num::NonZeroUsize};
|
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
/// Search for a module within an imports stack.
|
/// Search for a module within an imports stack.
|
||||||
|
@ -7,6 +7,16 @@ use std::{
|
|||||||
hash::{BuildHasher, Hash, Hasher},
|
hash::{BuildHasher, Hash, Hasher},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
pub type StraightHashMap<K, V> = hashbrown::HashMap<K, V, StraightHasherBuilder>;
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
pub type StraightHashSet<K> = hashbrown::HashSet<K, StraightHasherBuilder>;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
pub type StraightHashMap<K, V> = std::collections::HashMap<K, V, StraightHasherBuilder>;
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
pub type StraightHashSet<K> = std::collections::HashSet<K, StraightHasherBuilder>;
|
||||||
|
|
||||||
/// Dummy hash value to map zeros to. This value can be anything.
|
/// Dummy hash value to map zeros to. This value can be anything.
|
||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
@ -30,7 +40,7 @@ pub const ALT_ZERO_HASH: u64 = 42;
|
|||||||
///
|
///
|
||||||
/// Panics when hashing any data type other than a [`u64`].
|
/// Panics when hashing any data type other than a [`u64`].
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
struct StraightHasher(u64);
|
pub struct StraightHasher(u64);
|
||||||
|
|
||||||
impl Hasher for StraightHasher {
|
impl Hasher for StraightHasher {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -38,23 +48,22 @@ impl Hasher for StraightHasher {
|
|||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write(&mut self, bytes: &[u8]) {
|
fn write(&mut self, _bytes: &[u8]) {
|
||||||
assert_eq!(bytes.len(), 8, "StraightHasher can only hash u64 values");
|
panic!("StraightHasher can only hash u64 values");
|
||||||
|
}
|
||||||
|
|
||||||
let mut key = [0_u8; 8];
|
fn write_u64(&mut self, i: u64) {
|
||||||
key.copy_from_slice(bytes);
|
if i == 0 {
|
||||||
|
|
||||||
self.0 = u64::from_ne_bytes(key);
|
|
||||||
|
|
||||||
if self.0 == 0 {
|
|
||||||
self.0 = ALT_ZERO_HASH;
|
self.0 = ALT_ZERO_HASH;
|
||||||
|
} else {
|
||||||
|
self.0 = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A hash builder for `StraightHasher`.
|
/// A hash builder for `StraightHasher`.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
|
||||||
struct StraightHasherBuilder;
|
pub struct StraightHasherBuilder;
|
||||||
|
|
||||||
impl BuildHasher for StraightHasherBuilder {
|
impl BuildHasher for StraightHasherBuilder {
|
||||||
type Hasher = StraightHasher;
|
type Hasher = StraightHasher;
|
||||||
|
@ -21,7 +21,7 @@ pub use callable_function::CallableFunction;
|
|||||||
pub use func::Func;
|
pub use func::Func;
|
||||||
pub use hashing::{
|
pub use hashing::{
|
||||||
calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, calc_qualified_var_hash,
|
calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, calc_qualified_var_hash,
|
||||||
combine_hashes, get_hasher,
|
combine_hashes, get_hasher, StraightHashMap, StraightHashSet,
|
||||||
};
|
};
|
||||||
pub use native::{
|
pub use native::{
|
||||||
locked_read, locked_write, shared_get_mut, shared_make_mut, shared_take, shared_take_or_clone,
|
locked_read, locked_write, shared_get_mut, shared_make_mut, shared_take, shared_take_or_clone,
|
||||||
|
@ -23,6 +23,8 @@ use std::{
|
|||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
use crate::func::register::Mut;
|
use crate::func::register::Mut;
|
||||||
|
|
||||||
|
use crate::func::{StraightHashMap, StraightHashSet};
|
||||||
|
|
||||||
/// A type representing the namespace of a function.
|
/// A type representing the namespace of a function.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
#[cfg_attr(feature = "metadata", derive(serde::Serialize))]
|
#[cfg_attr(feature = "metadata", derive(serde::Serialize))]
|
||||||
@ -267,18 +269,18 @@ pub struct Module {
|
|||||||
/// [`Module`] variables.
|
/// [`Module`] variables.
|
||||||
variables: BTreeMap<Identifier, Dynamic>,
|
variables: BTreeMap<Identifier, Dynamic>,
|
||||||
/// Flattened collection of all [`Module`] variables, including those in sub-modules.
|
/// Flattened collection of all [`Module`] variables, including those in sub-modules.
|
||||||
all_variables: BTreeMap<u64, Dynamic>,
|
all_variables: StraightHashMap<u64, Dynamic>,
|
||||||
/// Functions (both native Rust and scripted).
|
/// Functions (both native Rust and scripted).
|
||||||
functions: BTreeMap<u64, Box<FuncInfo>>,
|
functions: StraightHashMap<u64, Box<FuncInfo>>,
|
||||||
/// Flattened collection of all functions, native Rust and scripted.
|
/// Flattened collection of all functions, native Rust and scripted.
|
||||||
/// including those in sub-modules.
|
/// including those in sub-modules.
|
||||||
all_functions: BTreeMap<u64, CallableFunction>,
|
all_functions: StraightHashMap<u64, CallableFunction>,
|
||||||
/// Native Rust functions (in scripted hash format) that contain [`Dynamic`] parameters.
|
/// Native Rust functions (in scripted hash format) that contain [`Dynamic`] parameters.
|
||||||
dynamic_functions: BTreeSet<u64>,
|
dynamic_functions: StraightHashSet<u64>,
|
||||||
/// Iterator functions, keyed by the type producing the iterator.
|
/// Iterator functions, keyed by the type producing the iterator.
|
||||||
type_iterators: BTreeMap<TypeId, Shared<IteratorFn>>,
|
type_iterators: StraightHashMap<TypeId, Shared<IteratorFn>>,
|
||||||
/// Flattened collection of iterator functions, including those in sub-modules.
|
/// Flattened collection of iterator functions, including those in sub-modules.
|
||||||
all_type_iterators: BTreeMap<TypeId, Shared<IteratorFn>>,
|
all_type_iterators: StraightHashMap<TypeId, Shared<IteratorFn>>,
|
||||||
/// Is the [`Module`] indexed?
|
/// Is the [`Module`] indexed?
|
||||||
indexed: bool,
|
indexed: bool,
|
||||||
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
|
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
|
||||||
@ -372,12 +374,12 @@ impl Module {
|
|||||||
custom_types: CustomTypesCollection::new(),
|
custom_types: CustomTypesCollection::new(),
|
||||||
modules: BTreeMap::new(),
|
modules: BTreeMap::new(),
|
||||||
variables: BTreeMap::new(),
|
variables: BTreeMap::new(),
|
||||||
all_variables: BTreeMap::new(),
|
all_variables: StraightHashMap::default(),
|
||||||
functions: BTreeMap::new(),
|
functions: StraightHashMap::default(),
|
||||||
all_functions: BTreeMap::new(),
|
all_functions: StraightHashMap::default(),
|
||||||
dynamic_functions: BTreeSet::new(),
|
dynamic_functions: StraightHashSet::default(),
|
||||||
type_iterators: BTreeMap::new(),
|
type_iterators: StraightHashMap::default(),
|
||||||
all_type_iterators: BTreeMap::new(),
|
all_type_iterators: StraightHashMap::default(),
|
||||||
indexed: true,
|
indexed: true,
|
||||||
contains_indexed_global_functions: false,
|
contains_indexed_global_functions: false,
|
||||||
}
|
}
|
||||||
@ -2137,9 +2139,9 @@ impl Module {
|
|||||||
fn index_module<'a>(
|
fn index_module<'a>(
|
||||||
module: &'a Module,
|
module: &'a Module,
|
||||||
path: &mut Vec<&'a str>,
|
path: &mut Vec<&'a str>,
|
||||||
variables: &mut BTreeMap<u64, Dynamic>,
|
variables: &mut StraightHashMap<u64, Dynamic>,
|
||||||
functions: &mut BTreeMap<u64, CallableFunction>,
|
functions: &mut StraightHashMap<u64, CallableFunction>,
|
||||||
type_iterators: &mut BTreeMap<TypeId, Shared<IteratorFn>>,
|
type_iterators: &mut StraightHashMap<TypeId, Shared<IteratorFn>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut contains_indexed_global_functions = false;
|
let mut contains_indexed_global_functions = false;
|
||||||
|
|
||||||
@ -2201,9 +2203,9 @@ impl Module {
|
|||||||
|
|
||||||
if !self.indexed {
|
if !self.indexed {
|
||||||
let mut path = Vec::with_capacity(4);
|
let mut path = Vec::with_capacity(4);
|
||||||
let mut variables = BTreeMap::new();
|
let mut variables = StraightHashMap::default();
|
||||||
let mut functions = BTreeMap::new();
|
let mut functions = StraightHashMap::default();
|
||||||
let mut type_iterators = BTreeMap::new();
|
let mut type_iterators = StraightHashMap::default();
|
||||||
|
|
||||||
path.push("");
|
path.push("");
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use crate::ast::{
|
|||||||
};
|
};
|
||||||
use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS};
|
use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS};
|
||||||
use crate::eval::GlobalRuntimeState;
|
use crate::eval::GlobalRuntimeState;
|
||||||
use crate::func::hashing::get_hasher;
|
use crate::func::{hashing::get_hasher, StraightHashMap};
|
||||||
use crate::tokenizer::{
|
use crate::tokenizer::{
|
||||||
is_keyword_function, is_valid_function_name, is_valid_identifier, Token, TokenStream,
|
is_keyword_function, is_valid_function_name, is_valid_identifier, Token, TokenStream,
|
||||||
TokenizerControl,
|
TokenizerControl,
|
||||||
@ -32,7 +32,7 @@ use std::{
|
|||||||
|
|
||||||
pub type ParseResult<T> = Result<T, ParseError>;
|
pub type ParseResult<T> = Result<T, ParseError>;
|
||||||
|
|
||||||
type FnLib = BTreeMap<u64, Shared<ScriptFnDef>>;
|
type FnLib = StraightHashMap<u64, Shared<ScriptFnDef>>;
|
||||||
|
|
||||||
const KEYWORD_SEMICOLON: &str = Token::SemiColon.literal_syntax();
|
const KEYWORD_SEMICOLON: &str = Token::SemiColon.literal_syntax();
|
||||||
|
|
||||||
@ -3790,7 +3790,7 @@ impl Engine {
|
|||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
_optimization_level: OptimizationLevel,
|
_optimization_level: OptimizationLevel,
|
||||||
) -> ParseResult<AST> {
|
) -> ParseResult<AST> {
|
||||||
let mut functions = BTreeMap::new();
|
let mut functions = StraightHashMap::default();
|
||||||
|
|
||||||
let mut options = self.options;
|
let mut options = self.options;
|
||||||
options.remove(LangOptions::STMT_EXPR);
|
options.remove(LangOptions::STMT_EXPR);
|
||||||
@ -3850,7 +3850,7 @@ impl Engine {
|
|||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
) -> ParseResult<(StmtBlockContainer, StaticVec<Shared<ScriptFnDef>>)> {
|
) -> ParseResult<(StmtBlockContainer, StaticVec<Shared<ScriptFnDef>>)> {
|
||||||
let mut statements = StmtBlockContainer::new_const();
|
let mut statements = StmtBlockContainer::new_const();
|
||||||
let mut functions = BTreeMap::new();
|
let mut functions = StraightHashMap::default();
|
||||||
|
|
||||||
while !input.peek().expect(NEVER_ENDS).0.is_eof() {
|
while !input.peek().expect(NEVER_ENDS).0.is_eof() {
|
||||||
let settings = ParseSettings {
|
let settings = ParseSettings {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use crate::func::hashing::get_hasher;
|
use crate::func::{hashing::get_hasher, StraightHashMap};
|
||||||
use crate::ImmutableString;
|
use crate::ImmutableString;
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
|
||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
@ -21,14 +20,14 @@ pub const MAX_STRING_LEN: usize = 24;
|
|||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// Normal identifiers, property getters and setters are interned separately.
|
/// Normal identifiers, property getters and setters are interned separately.
|
||||||
#[derive(Clone, Hash)]
|
#[derive(Clone)]
|
||||||
pub struct StringsInterner<'a> {
|
pub struct StringsInterner<'a> {
|
||||||
/// Maximum number of strings interned.
|
/// Maximum number of strings interned.
|
||||||
pub capacity: usize,
|
pub capacity: usize,
|
||||||
/// Maximum string length.
|
/// Maximum string length.
|
||||||
pub max_string_len: usize,
|
pub max_string_len: usize,
|
||||||
/// Normal strings.
|
/// Normal strings.
|
||||||
strings: BTreeMap<u64, ImmutableString>,
|
strings: StraightHashMap<u64, ImmutableString>,
|
||||||
/// Take care of the lifetime parameter.
|
/// Take care of the lifetime parameter.
|
||||||
dummy: PhantomData<&'a ()>,
|
dummy: PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
@ -55,7 +54,7 @@ impl StringsInterner<'_> {
|
|||||||
Self {
|
Self {
|
||||||
capacity: MAX_INTERNED_STRINGS,
|
capacity: MAX_INTERNED_STRINGS,
|
||||||
max_string_len: MAX_STRING_LEN,
|
max_string_len: MAX_STRING_LEN,
|
||||||
strings: BTreeMap::new(),
|
strings: StraightHashMap::default(),
|
||||||
dummy: PhantomData,
|
dummy: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user