diff --git a/testsuite/src/sparql_evaluator.rs b/testsuite/src/sparql_evaluator.rs index 4d01725d..67081be6 100644 --- a/testsuite/src/sparql_evaluator.rs +++ b/testsuite/src/sparql_evaluator.rs @@ -13,8 +13,9 @@ use sparopt::Optimizer; use std::collections::HashMap; use std::fmt::Write; use std::io::{self, BufReader, Cursor}; +use std::ops::Deref; use std::str::FromStr; -use std::sync::Arc; +use std::sync::{Arc, Mutex, OnceLock}; pub fn register_sparql_tests(evaluator: &mut TestEvaluator) { evaluator.register( @@ -138,7 +139,7 @@ fn evaluate_negative_result_syntax_test(test: &Test, format: QueryResultsFormat) } fn evaluate_evaluation_test(test: &Test) -> Result<()> { - let store = Store::new()?; + let store = get_store()?; if let Some(data) = &test.data { load_dataset_to_store(data, &store)?; } @@ -194,9 +195,10 @@ fn evaluate_evaluation_test(test: &Test) -> Result<()> { ensure!( are_query_results_isomorphic(&expected_results, &actual_results), - "Not isomorphic results.\n{}\nParsed query:\n{}\nData:\n{store}\n", + "Not isomorphic results.\n{}\nParsed query:\n{}\nData:\n{}\n", results_diff(expected_results, actual_results), - Query::parse(&read_file_to_string(query_file)?, Some(query_file)).unwrap() + Query::parse(&read_file_to_string(query_file)?, Some(query_file)).unwrap(), + &*store ); } Ok(()) @@ -227,7 +229,7 @@ fn evaluate_negative_update_syntax_test(test: &Test) -> Result<()> { } fn evaluate_update_evaluation_test(test: &Test) -> Result<()> { - let store = Store::new()?; + let store = get_store()?; if let Some(data) = &test.data { load_dataset_to_store(data, &store)?; } @@ -235,7 +237,7 @@ fn evaluate_update_evaluation_test(test: &Test) -> Result<()> { load_graph_to_store(value, &store, name.clone())?; } - let result_store = Store::new()?; + let result_store = get_store()?; if let Some(data) = &test.result { load_dataset_to_store(data, &result_store)?; } @@ -286,7 +288,7 @@ fn load_sparql_query_result(url: &str) -> Result { #[derive(Clone)] struct StaticServiceHandler { - services: Arc>, + services: Arc>, } impl StaticServiceHandler { @@ -297,7 +299,7 @@ impl StaticServiceHandler { .iter() .map(|(name, data)| { let name = NamedNode::new(name)?; - let store = Store::new()?; + let store = get_store()?; load_dataset_to_store(data, &store)?; Ok((name, store)) }) @@ -482,7 +484,7 @@ impl StaticQueryResults { fn from_graph(graph: &Graph) -> Result { // Hack to normalize literals - let store = Store::new()?; + let store = get_store()?; for t in graph { store.insert(t.in_graph(GraphNameRef::DefaultGraph))?; } @@ -736,3 +738,39 @@ fn evaluate_query_optimization_test(test: &Test) -> Result<()> { ); Ok(()) } + +// Pool of stores to avoid allocating/deallocating them a lot +static STORE_POOL: OnceLock>> = OnceLock::new(); + +fn get_store() -> Result { + let store = if let Some(store) = STORE_POOL.get_or_init(Mutex::default).lock().unwrap().pop() { + store + } else { + Store::new()? + }; + Ok(StoreRef { store }) +} + +struct StoreRef { + store: Store, +} + +impl Drop for StoreRef { + fn drop(&mut self) { + if self.store.clear().is_ok() { + STORE_POOL + .get_or_init(Mutex::default) + .lock() + .unwrap() + .push(self.store.clone()) + } + } +} + +impl Deref for StoreRef { + type Target = Store; + + fn deref(&self) -> &Store { + &self.store + } +}