Skip to content

Commit 34cc43c

Browse files
committed
Don't use so many partitions in the benchmarks.
1 parent 3387213 commit 34cc43c

File tree

6 files changed

+138
-65
lines changed

6 files changed

+138
-65
lines changed

Cargo.lock

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/encoding/Cargo.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ rust-version.workspace = true
88

99
[dependencies]
1010
rdf-fusion-common.workspace = true
11-
rdf-fusion-functions-scalar.workspace = true
1211
rdf-fusion-model.workspace = true
1312
datafusion.workspace = true
14-
thiserror.workspace = true
15-
uuid.workspace = true
13+
14+
[dev-dependencies]
15+
codspeed-criterion-compat = { workspace = true, features = ["async_tokio"] }
1616

1717
[lints]
1818
workspace = true
19+
20+
[[bench]]
21+
name = "builders"
22+
harness = false

lib/encoding/benches/builders.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#![allow(clippy::panic)]
2+
3+
use codspeed_criterion_compat::{criterion_group, criterion_main, Criterion};
4+
use rdf_fusion_encoding::plain_term::PlainTermArrayBuilder;
5+
use rdf_fusion_encoding::sortable_term::SortableTermArrayBuilder;
6+
use rdf_fusion_encoding::typed_value::TypedValueArrayBuilder;
7+
use rdf_fusion_model::{NamedNodeRef, TermRef};
8+
use std::hint::black_box;
9+
10+
/// These benchmarks measure instantiating [PlainTermArrayBuilder].
11+
fn plain_term_builder_new(c: &mut Criterion) {
12+
c.bench_function("PlainTermArrayBuilder::new - Create empty builder", |b| {
13+
b.iter(|| black_box(PlainTermArrayBuilder::new(0)));
14+
});
15+
16+
c.bench_function(
17+
"PlainTermArrayBuilder::new - Create record batch builder",
18+
|b| {
19+
b.iter(|| black_box(PlainTermArrayBuilder::new(8192)));
20+
},
21+
);
22+
}
23+
24+
/// These benchmarks measure encoding quads and finishing the builder for [PlainTermArrayBuilder].
25+
fn plain_term_builder_build_array(c: &mut Criterion) {
26+
c.bench_function(
27+
"PlainTermArrayBuilder::append_term - With empty builder",
28+
|b| {
29+
b.iter(|| {
30+
let mut builder = PlainTermArrayBuilder::new(0);
31+
for _ in 0..8192 {
32+
builder.append_term(TermRef::NamedNode(NamedNodeRef::new_unchecked(
33+
"http://example.com/test",
34+
)))
35+
}
36+
let result = builder.finish();
37+
assert_eq!(result.len(), 8192);
38+
});
39+
},
40+
);
41+
c.bench_function(
42+
"PlainTermArrayBuilder::append_term - With pre-allocated builder",
43+
|b| {
44+
b.iter(|| {
45+
let mut builder = PlainTermArrayBuilder::new(8192);
46+
for _ in 0..8192 {
47+
builder.append_term(TermRef::NamedNode(NamedNodeRef::new_unchecked(
48+
"http://example.com/test",
49+
)))
50+
}
51+
let result = builder.finish();
52+
assert_eq!(result.len(), 8192);
53+
});
54+
},
55+
);
56+
}
57+
58+
/// These benchmarks measure instantiating [SortableTermArrayBuilder].
59+
fn sortable_term_builder_new(c: &mut Criterion) {
60+
c.bench_function(
61+
"SortableTermArrayBuilder::new - Create empty builder",
62+
|b| {
63+
b.iter(|| black_box(SortableTermArrayBuilder::new(0)));
64+
},
65+
);
66+
c.bench_function(
67+
"SortableTermArrayBuilder::new - Create record batch builder",
68+
|b| {
69+
b.iter(|| black_box(SortableTermArrayBuilder::new(8192)));
70+
},
71+
);
72+
}
73+
74+
/// These benchmarks measure instantiating [TypedValueArrayBuilder].
75+
fn typed_value_builder_default(c: &mut Criterion) {
76+
c.bench_function(
77+
"TypedValueArrayBuilder::default - Create empty builder",
78+
|b| {
79+
b.iter(|| black_box(TypedValueArrayBuilder::default()));
80+
},
81+
);
82+
}
83+
84+
criterion_group!(
85+
plain_term_builder,
86+
plain_term_builder_new,
87+
plain_term_builder_build_array
88+
);
89+
criterion_group!(sortable_term_builder, sortable_term_builder_new);
90+
criterion_group!(typed_value_array_builder, typed_value_builder_default);
91+
criterion_main!(
92+
plain_term_builder,
93+
sortable_term_builder,
94+
typed_value_array_builder
95+
);

lib/rdf-fusion/benches/store.rs

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,59 +21,41 @@ fn store_load(c: &mut Criterion) {
2121
});
2222
}
2323

24-
/// This benchmarks measure the duration of running a simple query (1 triple pattern). Hopefully,
24+
/// These benchmarks measure the duration of running a simple query (1 triple pattern). Hopefully,
2525
/// this can provide insights into the "baseline" overhead of the query engine.
2626
fn store_single_pattern(c: &mut Criterion) {
2727
let runtime = Builder::new_current_thread().enable_all().build().unwrap();
2828

2929
// No Quads
3030
c.bench_function("Store::query - Single Pattern / No Quads", |b| {
3131
let store = runtime.block_on(prepare_store_with_generated_triples(0));
32-
b.to_async(&runtime)
33-
.iter(|| async { trivial_query(&store, 0).await });
32+
b.to_async(&runtime).iter(|| trivial_query(&store, 0));
3433
});
3534
// One Quad
3635
c.bench_function("Store::query - Single Pattern / Single Quad", |b| {
3736
let store = runtime.block_on(prepare_store_with_generated_triples(1));
38-
b.to_async(&runtime)
39-
.iter(|| async { trivial_query(&store, 1).await });
37+
b.to_async(&runtime).iter(|| trivial_query(&store, 1));
4038
});
4139
// One Record Batch
42-
c.bench_function("Store::query - Single Pattern / 8096 Quads", |b| {
43-
let store = runtime.block_on(prepare_store_with_generated_triples(8096));
44-
b.to_async(&runtime)
45-
.iter(|| async { trivial_query(&store, 8096).await });
40+
c.bench_function("Store::query - Single Pattern / 8192 Quads", |b| {
41+
let store = runtime.block_on(prepare_store_with_generated_triples(8192));
42+
b.to_async(&runtime).iter(|| trivial_query(&store, 8192));
4643
});
4744
}
4845

49-
/// This benchmarks measure the duration of running a simple query that fixes a single part of the
46+
/// These benchmarks measure the duration of running a simple query that fixes a single part of the
5047
/// pattern (i.e., subject, predicate, object, graph).
5148
fn store_single_pattern_with_fixed_element(c: &mut Criterion) {
5249
let runtime = Builder::new_current_thread().enable_all().build().unwrap();
5350

54-
// Graph
55-
c.bench_function(
56-
"Store::query - Single Pattern With Fixed Element (graph)",
57-
|b| {
58-
let store = runtime.block_on(prepare_store_with_generated_triples(8096));
59-
b.to_async(&runtime).iter(|| async {
60-
let result = store
61-
.query("SELECT ?s ?p ?o { GRAPH <http://example.com/graph0> { ?s ?p ?o } }")
62-
.await
63-
.unwrap();
64-
assert_number_of_results(result, 1).await;
65-
});
66-
},
67-
);
68-
6951
// Subject
7052
c.bench_function(
7153
"Store::query - Single Pattern With Fixed Element (subject)",
7254
|b| {
73-
let store = runtime.block_on(prepare_store_with_generated_triples(8096));
55+
let store = runtime.block_on(prepare_store_with_generated_triples(8192));
7456
b.to_async(&runtime).iter(|| async {
7557
let result = store
76-
.query("SELECT ?g ?p ?o { GRAPH ?g { <http://example.com/subject0> ?p ?o } }")
58+
.query("SELECT ?p ?o { <http://example.com/subject0> ?p ?o }")
7759
.await
7860
.unwrap();
7961
assert_number_of_results(result, 1).await;
@@ -85,10 +67,10 @@ fn store_single_pattern_with_fixed_element(c: &mut Criterion) {
8567
c.bench_function(
8668
"Store::query - Single Pattern With Fixed Element (predicate)",
8769
|b| {
88-
let store = runtime.block_on(prepare_store_with_generated_triples(8096));
70+
let store = runtime.block_on(prepare_store_with_generated_triples(8192));
8971
b.to_async(&runtime).iter(|| async {
9072
let result = store
91-
.query("SELECT ?g ?s ?o { GRAPH ?g { ?s <http://example.com/predicate0> ?o } }")
73+
.query("SELECT ?s ?o { ?s <http://example.com/predicate0> ?o }")
9274
.await
9375
.unwrap();
9476
assert_number_of_results(result, 1).await;
@@ -100,10 +82,10 @@ fn store_single_pattern_with_fixed_element(c: &mut Criterion) {
10082
c.bench_function(
10183
"Store::query - Single Pattern With Fixed Element (object)",
10284
|b| {
103-
let store = runtime.block_on(prepare_store_with_generated_triples(8096));
85+
let store = runtime.block_on(prepare_store_with_generated_triples(8192));
10486
b.to_async(&runtime).iter(|| async {
10587
let result = store
106-
.query("SELECT ?g ?s ?p { GRAPH ?g { ?s ?p <http://example.com/object0> } }")
88+
.query("SELECT ?s ?p { ?s ?p <http://example.com/object0> }")
10789
.await
10890
.unwrap();
10991
assert_number_of_results(result, 1).await;
@@ -130,24 +112,20 @@ async fn prepare_store_with_generated_triples(n: usize) -> Store {
130112

131113
fn generate_quads(count: usize) -> impl Iterator<Item = Quad> {
132114
(0..count).map(|i| {
133-
let graph = format!("http://example.com/graph{}", i);
134115
let subject = format!("http://example.com/subject{}", i);
135116
let predicate = format!("http://example.com/predicate{}", i);
136117
let object = format!("http://example.com/object{}", i);
137118
Quad::new(
138119
Subject::NamedNode(NamedNode::new_unchecked(subject)),
139120
NamedNode::new_unchecked(predicate),
140121
Term::NamedNode(NamedNode::new_unchecked(object)),
141-
GraphName::NamedNode(NamedNode::new_unchecked(graph)),
122+
GraphName::DefaultGraph,
142123
)
143124
})
144125
}
145126

146127
async fn trivial_query(store: &Store, n: usize) {
147-
let result = store
148-
.query("SELECT ?s ?p ?o { GRAPH ?g { ?s ?p ?o } }")
149-
.await
150-
.unwrap();
128+
let result = store.query("SELECT ?s ?p ?o { ?s ?p ?o }").await.unwrap();
151129
assert_number_of_results(result, n).await;
152130
}
153131

lib/storage/src/oxigraph_memory/planner.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ impl ExtensionPlanner for OxigraphMemoryQuadNodePlanner {
8989
}
9090
}
9191
}
92+
9293
#[async_trait]
9394
impl QuadPatternEvaluator for MemoryStorageReader {
9495
fn quads_for_pattern(

lib/storage/src/oxigraph_memory/quad_storage_stream.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,24 @@ impl Stream for QuadIteratorBatchRecordStream {
3737
mut self: std::pin::Pin<&mut Self>,
3838
_ctx: &mut Context<'_>,
3939
) -> Poll<Option<Self::Item>> {
40-
let mut rb_builder = RdfQuadsRecordBatchBuilder::new();
40+
// Early return if the iterator is empty
41+
let Some(first_quad) = self.iterator.next() else {
42+
return Poll::Ready(None);
43+
};
4144

42-
while let Some(quad) = self.iterator.next() {
43-
rb_builder.encode_quad(&quad);
44-
if rb_builder.count() == self.batch_size {
45+
let mut rb_builder = RdfQuadsRecordBatchBuilder::new(self.batch_size);
46+
rb_builder.encode_quad(&first_quad);
47+
48+
for _ in 0..(self.batch_size - 1) {
49+
let Some(quad) = self.iterator.next() else {
4550
break;
46-
}
51+
};
52+
rb_builder.encode_quad(&quad);
4753
}
4854

4955
let record_batch = rb_builder.finish();
5056
match record_batch {
51-
Ok(Some(rb)) => Poll::Ready(Some(Ok(rb))),
52-
Ok(None) => Poll::Ready(None),
57+
Ok(rb) => Poll::Ready(Some(Ok(rb))),
5358
Err(err) => Poll::Ready(Some(Err(DataFusionError::External(Box::new(err))))),
5459
}
5560
}
@@ -71,20 +76,16 @@ struct RdfQuadsRecordBatchBuilder {
7176
}
7277

7378
impl RdfQuadsRecordBatchBuilder {
74-
fn new() -> Self {
79+
fn new(capacity: usize) -> Self {
7580
Self {
76-
graph: PlainTermArrayBuilder::new(0),
77-
subject: PlainTermArrayBuilder::new(0),
78-
predicate: PlainTermArrayBuilder::new(0),
79-
object: PlainTermArrayBuilder::new(0),
81+
graph: PlainTermArrayBuilder::new(capacity),
82+
subject: PlainTermArrayBuilder::new(capacity),
83+
predicate: PlainTermArrayBuilder::new(capacity),
84+
object: PlainTermArrayBuilder::new(capacity),
8085
count: 0,
8186
}
8287
}
8388

84-
fn count(&self) -> usize {
85-
self.count
86-
}
87-
8889
fn encode_quad(&mut self, quad: &EncodedQuad) {
8990
encode_term(&mut self.graph, &quad.graph_name);
9091
encode_term(&mut self.subject, &quad.subject);
@@ -93,11 +94,7 @@ impl RdfQuadsRecordBatchBuilder {
9394
self.count += 1;
9495
}
9596

96-
fn finish(self) -> AResult<Option<RecordBatch>> {
97-
if self.count == 0 {
98-
return Ok(None);
99-
}
100-
97+
fn finish(self) -> AResult<RecordBatch> {
10198
let fields: Vec<Arc<dyn Array>> = vec![
10299
Arc::new(self.graph.finish()),
103100
Arc::new(self.subject.finish()),
@@ -108,7 +105,7 @@ impl RdfQuadsRecordBatchBuilder {
108105
let options = RecordBatchOptions::default().with_row_count(Some(self.count));
109106
let record_batch =
110107
RecordBatch::try_new_with_options(Arc::clone(&DEFAULT_QUAD_SCHEMA), fields, &options)?;
111-
Ok(Some(record_batch))
108+
Ok(record_batch)
112109
}
113110
}
114111

0 commit comments

Comments
 (0)