Add functions lookup cache.
This commit is contained in:
parent
db7b9cb0f9
commit
d73f3a1d60
@ -24,7 +24,7 @@ use crate::stdlib::{
|
||||
string::{String, ToString},
|
||||
};
|
||||
use crate::syntax::CustomSyntax;
|
||||
use crate::utils::get_hasher;
|
||||
use crate::utils::{get_hasher, StraightHasherBuilder};
|
||||
use crate::{
|
||||
calc_native_fn_hash, Dynamic, EvalAltResult, FnPtr, ImmutableString, Module, Position, Scope,
|
||||
Shared, StaticVec,
|
||||
@ -476,7 +476,7 @@ impl<T: Into<Dynamic>> From<T> for Target<'_> {
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct State {
|
||||
/// Normally, access to variables are parsed with a relative offset into the scope to avoid a lookup.
|
||||
/// In some situation, e.g. after running an `eval` statement, subsequent offsets become mis-aligned.
|
||||
@ -489,6 +489,8 @@ pub struct State {
|
||||
pub operations: u64,
|
||||
/// Number of modules loaded.
|
||||
pub modules: usize,
|
||||
/// Cached lookup values for function hashes.
|
||||
pub functions_cache: HashMap<u64, Option<CallableFunction>, StraightHasherBuilder>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
@ -1886,6 +1888,10 @@ impl Engine {
|
||||
});
|
||||
|
||||
scope.rewind(prev_scope_len);
|
||||
if mods.len() != prev_mods_len {
|
||||
// If imports list is modified, clear the functions lookup cache
|
||||
state.functions_cache.clear();
|
||||
}
|
||||
mods.truncate(prev_mods_len);
|
||||
state.scope_level -= 1;
|
||||
|
||||
@ -2365,6 +2371,8 @@ impl Engine {
|
||||
} else {
|
||||
mods.push(name_def.name.clone(), module);
|
||||
}
|
||||
// When imports list is modified, clear the functions lookup cache
|
||||
state.functions_cache.clear();
|
||||
}
|
||||
|
||||
state.modules += 1;
|
||||
|
@ -170,14 +170,25 @@ impl Engine {
|
||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||
self.inc_operations(state)?;
|
||||
|
||||
// Search for the native function
|
||||
// First search registered functions (can override packages)
|
||||
// Then search packages
|
||||
let func = //lib.get_fn(hash_fn, pub_only)
|
||||
self.global_namespace.get_fn(hash_fn, pub_only)
|
||||
let func = state.functions_cache.get(&hash_fn).cloned();
|
||||
|
||||
let func = if let Some(ref f) = func {
|
||||
f.as_ref()
|
||||
} else {
|
||||
// Search for the native function
|
||||
// First search registered functions (can override packages)
|
||||
// Then search packages
|
||||
// lib.get_fn(hash_fn, pub_only)
|
||||
let f = self
|
||||
.global_namespace
|
||||
.get_fn(hash_fn, pub_only)
|
||||
.or_else(|| self.packages.get_fn(hash_fn))
|
||||
.or_else(|| mods.get_fn(hash_fn));
|
||||
|
||||
state.functions_cache.insert(hash_fn, f.cloned());
|
||||
f
|
||||
};
|
||||
|
||||
if let Some(func) = func {
|
||||
assert!(func.is_native());
|
||||
|
||||
@ -370,6 +381,9 @@ impl Engine {
|
||||
let mut lib_merged: StaticVec<_>;
|
||||
|
||||
let unified_lib = if let Some(ref env_lib) = fn_def.lib {
|
||||
// If the library is modified, clear the functions lookup cache
|
||||
state.functions_cache.clear();
|
||||
|
||||
lib_merged = Default::default();
|
||||
lib_merged.push(env_lib.as_ref());
|
||||
lib_merged.extend(lib.iter().cloned());
|
||||
|
Loading…
Reference in New Issue
Block a user