mirror of
https://github.com/loot/loot-condition-interpreter.git
synced 2026-07-27 14:16:09 -07:00
Add benchmarks to help optimise result caching
This commit is contained in:
@@ -11,4 +11,9 @@ regex = "1.0.5"
|
|||||||
unicase = "2.2.0"
|
unicase = "2.2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
criterion = "0.2.0"
|
||||||
tempfile = "3.0.0"
|
tempfile = "3.0.0"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "eval"
|
||||||
|
harness = false
|
||||||
|
|||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate criterion;
|
||||||
|
extern crate loot_condition_interpreter;
|
||||||
|
|
||||||
|
use criterion::Criterion;
|
||||||
|
use loot_condition_interpreter::{Expression, GameType, State};
|
||||||
|
|
||||||
|
fn generate_active_plugins() -> Vec<String> {
|
||||||
|
let mut vec: Vec<String> = (0..255).map(|i| format!("Blank{}.esm", i)).collect();
|
||||||
|
vec.push("Blank.esm".into());
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_plugin_versions() -> Vec<(String, String)> {
|
||||||
|
let mut vec: Vec<(String, String)> = (0..255)
|
||||||
|
.map(|i| (format!("Blank{}.esm", i), "5".to_string()))
|
||||||
|
.collect();
|
||||||
|
vec.push(("Blank.esm".into(), "5".into()));
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
fn criterion_benchmark(c: &mut Criterion) {
|
||||||
|
c.bench_function("Expression.eval() file(path)", |b| {
|
||||||
|
let state = State::new(GameType::Tes4, ".".into(), ".".into());
|
||||||
|
let expression = Expression::parse("file(\"Cargo.toml\")").unwrap().1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() file(regex)", |b| {
|
||||||
|
let state = State::new(GameType::Tes4, ".".into(), ".".into());
|
||||||
|
let expression = Expression::parse("file(\"Cargo.*\")").unwrap().1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() active(path)", |b| {
|
||||||
|
let state = State::new(
|
||||||
|
GameType::Tes4,
|
||||||
|
"testing-plugins/Oblivion/Data".into(),
|
||||||
|
".".into(),
|
||||||
|
).with_active_plugins(&generate_active_plugins());
|
||||||
|
|
||||||
|
let expression = Expression::parse("active(\"Blank.esm\")").unwrap().1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() active(regex)", |b| {
|
||||||
|
let state = State::new(
|
||||||
|
GameType::Tes4,
|
||||||
|
"testing-plugins/Oblivion/Data".into(),
|
||||||
|
".".into(),
|
||||||
|
).with_active_plugins(&generate_active_plugins());
|
||||||
|
|
||||||
|
let expression = Expression::parse("active(\"Blank.*\")").unwrap().1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() many()", |b| {
|
||||||
|
let state = State::new(GameType::Tes4, ".".into(), ".".into());
|
||||||
|
let expression = Expression::parse("many(\"Cargo.*\")").unwrap().1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() many_active()", |b| {
|
||||||
|
let state = State::new(
|
||||||
|
GameType::Tes4,
|
||||||
|
"testing-plugins/Oblivion/Data".into(),
|
||||||
|
".".into(),
|
||||||
|
).with_active_plugins(&generate_active_plugins());
|
||||||
|
|
||||||
|
let expression = Expression::parse("many_active(\"Blank.*\")").unwrap().1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() checksum()", |b| {
|
||||||
|
let state = State::new(
|
||||||
|
GameType::Tes4,
|
||||||
|
"testing-plugins/Oblivion/Data".into(),
|
||||||
|
".".into(),
|
||||||
|
);
|
||||||
|
let expression = Expression::parse("checksum(\"Blank.esm\", 374E2A6F)")
|
||||||
|
.unwrap()
|
||||||
|
.1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() version(plugin)", |b| {
|
||||||
|
let state = State::new(
|
||||||
|
GameType::Tes4,
|
||||||
|
"testing-plugins/Oblivion/Data".into(),
|
||||||
|
".".into(),
|
||||||
|
).with_plugin_versions(&generate_plugin_versions());
|
||||||
|
|
||||||
|
let expression = Expression::parse("version(\"Blank.esm\", \"5.0\", ==)")
|
||||||
|
.unwrap()
|
||||||
|
.1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("Expression.eval() version(executable)", |b| {
|
||||||
|
let state = State::new(GameType::Tes4, ".".into(), ".".into());
|
||||||
|
let expression = Expression::parse(
|
||||||
|
"version(\"loot_api-0.13.8-0-g47797cc_dev-win32/loot_api.dll\", \"0.13.8.0\", ==)",
|
||||||
|
).unwrap()
|
||||||
|
.1;
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
assert!(expression.eval(&state).unwrap());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
criterion_group!(benches, criterion_benchmark);
|
||||||
|
criterion_main!(benches);
|
||||||
+35
@@ -52,6 +52,7 @@ impl From<pelite::resources::FindError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum GameType {
|
pub enum GameType {
|
||||||
Tes4,
|
Tes4,
|
||||||
Tes5,
|
Tes5,
|
||||||
@@ -84,6 +85,7 @@ impl GameType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
game_type: GameType,
|
game_type: GameType,
|
||||||
/// Game Data folder path.
|
/// Game Data folder path.
|
||||||
@@ -100,6 +102,39 @@ pub struct State {
|
|||||||
condition_cache: RwLock<HashMap<Function, bool>>,
|
condition_cache: RwLock<HashMap<Function, bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub fn new(game_type: GameType, data_path: PathBuf, loot_path: PathBuf) -> Self {
|
||||||
|
State {
|
||||||
|
game_type,
|
||||||
|
data_path,
|
||||||
|
loot_path,
|
||||||
|
active_plugins: HashSet::default(),
|
||||||
|
crc_cache: RwLock::default(),
|
||||||
|
plugin_versions: HashMap::default(),
|
||||||
|
condition_cache: RwLock::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_plugin_versions<T: AsRef<str>, V: ToString>(
|
||||||
|
mut self,
|
||||||
|
plugin_versions: &[(T, V)],
|
||||||
|
) -> Self {
|
||||||
|
self.plugin_versions = plugin_versions
|
||||||
|
.iter()
|
||||||
|
.map(|(p, v)| (p.as_ref().to_lowercase(), v.to_string()))
|
||||||
|
.collect();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_active_plugins<T: AsRef<str>>(mut self, active_plugins: &[T]) -> Self {
|
||||||
|
self.active_plugins = active_plugins
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.as_ref().to_lowercase())
|
||||||
|
.collect();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Compound conditions joined by 'or'
|
/// Compound conditions joined by 'or'
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub struct Expression(Vec<CompoundCondition>);
|
pub struct Expression(Vec<CompoundCondition>);
|
||||||
|
|||||||
Reference in New Issue
Block a user