|
|
|
@ -4,9 +4,11 @@ use oxigraph::io::GraphFormat; |
|
|
|
|
use oxigraph::model::GraphNameRef; |
|
|
|
|
use oxigraph::sparql::{Query, QueryResults, Update}; |
|
|
|
|
use oxigraph::store::Store; |
|
|
|
|
use std::fs::File; |
|
|
|
|
use rand::random; |
|
|
|
|
use std::env::temp_dir; |
|
|
|
|
use std::fs::{remove_dir_all, File}; |
|
|
|
|
use std::io::{BufRead, BufReader, Cursor, Read}; |
|
|
|
|
use std::path::Path; |
|
|
|
|
use std::path::{Path, PathBuf}; |
|
|
|
|
|
|
|
|
|
fn store_load(c: &mut Criterion) { |
|
|
|
|
let mut data = Vec::new(); |
|
|
|
@ -17,27 +19,22 @@ fn store_load(c: &mut Criterion) { |
|
|
|
|
let mut group = c.benchmark_group("store load"); |
|
|
|
|
group.throughput(Throughput::Bytes(data.len() as u64)); |
|
|
|
|
group.sample_size(10); |
|
|
|
|
group.bench_function("load BSBM explore 1000", |b| { |
|
|
|
|
group.bench_function("load BSBM explore 1000 in memory", |b| { |
|
|
|
|
b.iter(|| { |
|
|
|
|
let store = Store::new().unwrap(); |
|
|
|
|
store |
|
|
|
|
.load_graph( |
|
|
|
|
Cursor::new(&data), |
|
|
|
|
GraphFormat::NTriples, |
|
|
|
|
GraphNameRef::DefaultGraph, |
|
|
|
|
None, |
|
|
|
|
) |
|
|
|
|
.unwrap(); |
|
|
|
|
do_load(&store, &data); |
|
|
|
|
}) |
|
|
|
|
}); |
|
|
|
|
group.bench_function("load BSBM explore 1000 in on disk", |b| { |
|
|
|
|
b.iter(|| { |
|
|
|
|
let path = TempDir::default(); |
|
|
|
|
let store = Store::open(&path.0).unwrap(); |
|
|
|
|
do_load(&store, &data); |
|
|
|
|
}) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn store_query_and_update(c: &mut Criterion) { |
|
|
|
|
let mut data = Vec::new(); |
|
|
|
|
read_data("explore-1000.nt.zst") |
|
|
|
|
.read_to_end(&mut data) |
|
|
|
|
.unwrap(); |
|
|
|
|
let store = Store::new().unwrap(); |
|
|
|
|
fn do_load(store: &Store, data: &[u8]) { |
|
|
|
|
store |
|
|
|
|
.load_graph( |
|
|
|
|
Cursor::new(&data), |
|
|
|
@ -46,6 +43,14 @@ fn store_query_and_update(c: &mut Criterion) { |
|
|
|
|
None, |
|
|
|
|
) |
|
|
|
|
.unwrap(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn store_query_and_update(c: &mut Criterion) { |
|
|
|
|
let mut data = Vec::new(); |
|
|
|
|
read_data("explore-1000.nt.zst") |
|
|
|
|
.read_to_end(&mut data) |
|
|
|
|
.unwrap(); |
|
|
|
|
|
|
|
|
|
let operations = read_data("mix-exploreAndUpdate-1000.tsv.zst") |
|
|
|
|
.lines() |
|
|
|
|
.map(|l| { |
|
|
|
@ -60,32 +65,59 @@ fn store_query_and_update(c: &mut Criterion) { |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.collect::<Vec<_>>(); |
|
|
|
|
let query_operations = operations |
|
|
|
|
.iter() |
|
|
|
|
.filter(|o| matches!(o, Operation::Query(_))) |
|
|
|
|
.cloned() |
|
|
|
|
.collect::<Vec<_>>(); |
|
|
|
|
|
|
|
|
|
let mut group = c.benchmark_group("store operations"); |
|
|
|
|
group.throughput(Throughput::Elements(operations.len() as u64)); |
|
|
|
|
group.sample_size(10); |
|
|
|
|
group.bench_function("BSBM explore 1000 queryAndUpdate", |b| { |
|
|
|
|
b.iter(|| { |
|
|
|
|
for operation in &operations { |
|
|
|
|
match operation { |
|
|
|
|
Operation::Query(q) => match store.query(q.clone()).unwrap() { |
|
|
|
|
QueryResults::Boolean(_) => (), |
|
|
|
|
QueryResults::Solutions(s) => { |
|
|
|
|
for s in s { |
|
|
|
|
s.unwrap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
QueryResults::Graph(g) => { |
|
|
|
|
for t in g { |
|
|
|
|
t.unwrap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
Operation::Update(u) => store.update(u.clone()).unwrap(), |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
let memory_store = Store::new().unwrap(); |
|
|
|
|
do_load(&memory_store, &data); |
|
|
|
|
group.bench_function("BSBM explore 1000 query in memory", |b| { |
|
|
|
|
b.iter(|| run_operation(&memory_store, &query_operations)) |
|
|
|
|
}); |
|
|
|
|
group.bench_function("BSBM explore 1000 queryAndUpdate in memory", |b| { |
|
|
|
|
b.iter(|| run_operation(&memory_store, &operations)) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
let path = TempDir::default(); |
|
|
|
|
let disk_store = Store::open(&path.0).unwrap(); |
|
|
|
|
do_load(&disk_store, &data); |
|
|
|
|
group.bench_function("BSBM explore 1000 query on disk", |b| { |
|
|
|
|
b.iter(|| run_operation(&disk_store, &query_operations)) |
|
|
|
|
}); |
|
|
|
|
group.bench_function("BSBM explore 1000 queryAndUpdate on disk", |b| { |
|
|
|
|
b.iter(|| run_operation(&disk_store, &operations)) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn run_operation(store: &Store, operations: &[Operation]) { |
|
|
|
|
for operation in operations { |
|
|
|
|
match operation { |
|
|
|
|
Operation::Query(q) => match store.query(q.clone()).unwrap() { |
|
|
|
|
QueryResults::Boolean(_) => (), |
|
|
|
|
QueryResults::Solutions(s) => { |
|
|
|
|
for s in s { |
|
|
|
|
s.unwrap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
}); |
|
|
|
|
QueryResults::Graph(g) => { |
|
|
|
|
for t in g { |
|
|
|
|
t.unwrap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
Operation::Update(u) => store.update(u.clone()).unwrap(), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
criterion_group!(store, store_query_and_update, store_load); |
|
|
|
@ -113,7 +145,22 @@ fn read_data(file: &str) -> impl BufRead { |
|
|
|
|
BufReader::new(zstd::Decoder::new(File::open(file).unwrap()).unwrap()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Clone)] |
|
|
|
|
enum Operation { |
|
|
|
|
Query(Query), |
|
|
|
|
Update(Update), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct TempDir(PathBuf); |
|
|
|
|
|
|
|
|
|
impl Default for TempDir { |
|
|
|
|
fn default() -> Self { |
|
|
|
|
Self(temp_dir().join(format!("oxigraph-bench-{}", random::<u128>()))) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Drop for TempDir { |
|
|
|
|
fn drop(&mut self) { |
|
|
|
|
remove_dir_all(&self.0).unwrap() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|