Skip to content

Commit 3996cd8

Browse files
authored
GH-4896 LMDB: Update benchmarks and improve performance (#4897)
2 parents 440dc0e + ff0e425 commit 3996cd8

17 files changed

Lines changed: 725 additions & 104 deletions

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/ValueStoreRevision.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,28 @@ class Lazy extends Base implements Serializable {
7070
private static final long serialVersionUID = -2434063125560285009L;
7171

7272
private final ValueStoreRevision revision;
73+
private final long revisionId;
74+
private final ValueStore valueStore;
7375

7476
public Lazy(ValueStoreRevision revision) {
7577
this.revision = revision;
78+
this.revisionId = revision.getRevisionId();
79+
this.valueStore = revision.getValueStore();
7680
}
7781

7882
@Override
7983
public long getRevisionId() {
80-
return revision.getRevisionId();
84+
return revisionId;
8185
}
8286

8387
@Override
8488
public ValueStore getValueStore() {
85-
return revision.getValueStore();
89+
return valueStore;
8690
}
8791

8892
@Override
8993
public boolean resolveValue(long id, LmdbValue value) {
90-
if (revision.resolveValue(id, value)) {
94+
if (valueStore.resolveValue(id, value)) {
9195
// set unwrapped version of revision
9296
value.setInternalID(id, revision);
9397
return true;
Lines changed: 134 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2021 Eclipse RDF4J contributors.
2+
* Copyright (c) 2022 Eclipse RDF4J contributors.
33
*
44
* All rights reserved. This program and the accompanying materials
55
* are made available under the terms of the Eclipse Distribution License v1.0
@@ -15,17 +15,15 @@
1515
import java.io.IOException;
1616
import java.io.InputStream;
1717
import java.nio.charset.StandardCharsets;
18-
import java.util.List;
1918
import java.util.concurrent.TimeUnit;
19+
import java.util.stream.Stream;
2020

2121
import org.apache.commons.io.FileUtils;
2222
import org.apache.commons.io.IOUtils;
2323
import org.assertj.core.util.Files;
24-
import org.eclipse.rdf4j.common.iteration.Iterations;
2524
import org.eclipse.rdf4j.common.transaction.IsolationLevels;
26-
import org.eclipse.rdf4j.model.Resource;
27-
import org.eclipse.rdf4j.model.Statement;
28-
import org.eclipse.rdf4j.model.vocabulary.RDF;
25+
import org.eclipse.rdf4j.query.BindingSet;
26+
import org.eclipse.rdf4j.query.TupleQueryResult;
2927
import org.eclipse.rdf4j.repository.sail.SailRepository;
3028
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
3129
import org.eclipse.rdf4j.rio.RDFFormat;
@@ -48,46 +46,73 @@
4846
import org.openjdk.jmh.runner.options.OptionsBuilder;
4947

5048
/**
51-
* Benchmarks query performance with real data.
49+
* @author Håvard Ottestad
5250
*/
5351
@State(Scope.Benchmark)
54-
@Warmup(iterations = 2)
52+
@Warmup(iterations = 5)
5553
@BenchmarkMode({ Mode.AverageTime })
56-
@Fork(value = 1, jvmArgs = { "-Xms2G", "-Xmx2G", "-Xmn1G", "-XX:+UseSerialGC" })
57-
//@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC", "-XX:+UnlockCommercialFeatures", "-XX:StartFlightRecording=delay=60s,duration=120s,filename=recording.jfr,settings=profile", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
54+
@Fork(value = 1, jvmArgs = { "-Xms1G", "-Xmx1G" })
55+
//@Fork(value = 1, jvmArgs = {"-Xms1G", "-Xmx1G", "-XX:StartFlightRecording=delay=60s,duration=120s,filename=recording.jfr,settings=profile", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
5856
@Measurement(iterations = 5)
5957
@OutputTimeUnit(TimeUnit.MILLISECONDS)
6058
public class QueryBenchmark {
6159

6260
private SailRepository repository;
6361

6462
private static final String query1;
65-
private static final String query2;
66-
private static final String query3;
6763
private static final String query4;
68-
private static final String query5;
6964
private static final String query7_pathexpression1;
65+
private static final String query8_pathexpression2;
66+
67+
private static final String common_themes;
68+
private static final String different_datasets_with_similar_distributions;
69+
private static final String long_chain;
70+
private static final String lots_of_optional;
71+
private static final String minus;
72+
private static final String nested_optionals;
73+
private static final String particularly_large_join_surface;
74+
private static final String query_distinct_predicates;
75+
private static final String simple_filter_not;
76+
private static final String wild_card_chain_with_common_ends;
7077

7178
static {
7279
try {
80+
common_themes = IOUtils.toString(getResourceAsStream("benchmarkFiles/common-themes.qr"),
81+
StandardCharsets.UTF_8);
82+
different_datasets_with_similar_distributions = IOUtils.toString(
83+
getResourceAsStream("benchmarkFiles/different-datasets-with-similar-distributions.qr"),
84+
StandardCharsets.UTF_8);
85+
long_chain = IOUtils.toString(getResourceAsStream("benchmarkFiles/long-chain.qr"), StandardCharsets.UTF_8);
86+
lots_of_optional = IOUtils.toString(getResourceAsStream("benchmarkFiles/lots-of-optional.qr"),
87+
StandardCharsets.UTF_8);
88+
minus = IOUtils.toString(getResourceAsStream("benchmarkFiles/minus.qr"), StandardCharsets.UTF_8);
89+
nested_optionals = IOUtils.toString(getResourceAsStream("benchmarkFiles/nested-optionals.qr"),
90+
StandardCharsets.UTF_8);
91+
particularly_large_join_surface = IOUtils.toString(
92+
getResourceAsStream("benchmarkFiles/particularly-large-join-surface.qr"), StandardCharsets.UTF_8);
7393
query1 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query1.qr"), StandardCharsets.UTF_8);
74-
query2 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query2.qr"), StandardCharsets.UTF_8);
75-
query3 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query3.qr"), StandardCharsets.UTF_8);
7694
query4 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query4.qr"), StandardCharsets.UTF_8);
77-
query5 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query5.qr"), StandardCharsets.UTF_8);
7895
query7_pathexpression1 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query7-pathexpression1.qr"),
7996
StandardCharsets.UTF_8);
97+
query8_pathexpression2 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query8-pathexpression2.qr"),
98+
StandardCharsets.UTF_8);
99+
query_distinct_predicates = IOUtils.toString(
100+
getResourceAsStream("benchmarkFiles/query-distinct-predicates.qr"), StandardCharsets.UTF_8);
101+
simple_filter_not = IOUtils.toString(getResourceAsStream("benchmarkFiles/simple-filter-not.qr"),
102+
StandardCharsets.UTF_8);
103+
wild_card_chain_with_common_ends = IOUtils.toString(
104+
getResourceAsStream("benchmarkFiles/wild-card-chain-with-common-ends.qr"), StandardCharsets.UTF_8);
105+
80106
} catch (IOException e) {
81107
throw new RuntimeException(e);
82108
}
83109
}
84110

85-
List<Statement> statementList;
86111
private File file;
87112

88113
public static void main(String[] args) throws RunnerException {
89114
Options opt = new OptionsBuilder()
90-
.include("QueryBenchmark") // adapt to control which benchmark tests to run
115+
.include("QueryBenchmark") // adapt to run other benchmark tests
91116
.forks(1)
92117
.build();
93118

@@ -96,28 +121,17 @@ public static void main(String[] args) throws RunnerException {
96121

97122
@Setup(Level.Trial)
98123
public void beforeClass() throws IOException {
99-
100124
file = Files.newTemporaryFolder();
101125

102126
repository = new SailRepository(new LmdbStore(file, ConfigUtil.createConfig()));
103127

104128
try (SailRepositoryConnection connection = repository.getConnection()) {
105129
connection.begin(IsolationLevels.NONE);
106-
connection.add(getResourceAsStream("benchmarkFiles/datagovbe-valid.ttl"), "", RDFFormat.TURTLE);
130+
try (InputStream resourceAsStream = getResourceAsStream("benchmarkFiles/datagovbe-valid.ttl")) {
131+
connection.add(resourceAsStream, RDFFormat.TURTLE);
132+
}
107133
connection.commit();
108134
}
109-
110-
try (SailRepositoryConnection connection = repository.getConnection()) {
111-
112-
statementList = Iterations.asList(connection.getStatements(null, RDF.TYPE, null, false));
113-
}
114-
115-
System.gc();
116-
117-
}
118-
119-
private static InputStream getResourceAsStream(String name) {
120-
return QueryBenchmark.class.getClassLoader().getResourceAsStream(name);
121135
}
122136

123137
@TearDown(Level.Trial)
@@ -126,125 +140,148 @@ public void afterClass() throws IOException {
126140
FileUtils.deleteDirectory(file);
127141
}
128142

143+
private static long count(TupleQueryResult evaluate) {
144+
try (Stream<BindingSet> stream = evaluate.stream()) {
145+
return stream.count();
146+
}
147+
}
148+
129149
@Benchmark
130150
public long groupByQuery() {
131-
132151
try (SailRepositoryConnection connection = repository.getConnection()) {
133-
return connection
152+
return count(connection
134153
.prepareTupleQuery(query1)
135-
.evaluate()
136-
.stream()
137-
.count();
154+
.evaluate());
138155
}
139156
}
140157

141158
@Benchmark
142159
public long complexQuery() {
143-
144160
try (SailRepositoryConnection connection = repository.getConnection()) {
145-
return connection
161+
return count(connection
146162
.prepareTupleQuery(query4)
147163
.evaluate()
148-
.stream()
149-
.count();
164+
);
150165
}
151166
}
152167

153168
@Benchmark
154-
public long distinctPredicatesQuery() {
169+
public long pathExpressionQuery1() {
155170

156171
try (SailRepositoryConnection connection = repository.getConnection()) {
157-
return connection
158-
.prepareTupleQuery(query5)
159-
.evaluate()
160-
.stream()
161-
.count();
172+
return count(connection
173+
.prepareTupleQuery(query7_pathexpression1)
174+
.evaluate());
175+
162176
}
163177
}
164178

165179
@Benchmark
166-
public long pathExpressionQuery1() {
167-
180+
public long pathExpressionQuery2() {
168181
try (SailRepositoryConnection connection = repository.getConnection()) {
169-
return connection
170-
.prepareTupleQuery(query7_pathexpression1)
171-
.evaluate()
172-
.stream()
173-
.count();
174-
182+
return count(connection
183+
.prepareTupleQuery(query8_pathexpression2)
184+
.evaluate());
175185
}
176186
}
177187

178-
@Benchmark
179-
public boolean removeByQuery() {
188+
// @Benchmark
189+
// public long common_themes() {
190+
// try (SailRepositoryConnection connection = repository.getConnection()) {
191+
// return connection
192+
// .prepareTupleQuery(common_themes)
193+
// .evaluate()
194+
// .stream()
195+
// .count();
196+
// }
197+
// }
180198

199+
@Benchmark
200+
public long different_datasets_with_similar_distributions() {
181201
try (SailRepositoryConnection connection = repository.getConnection()) {
182-
connection.begin(IsolationLevels.NONE);
183-
connection.remove((Resource) null, RDF.TYPE, null);
184-
connection.commit();
185-
connection.begin(IsolationLevels.NONE);
186-
connection.add(statementList);
187-
connection.commit();
202+
return count(connection
203+
.prepareTupleQuery(different_datasets_with_similar_distributions)
204+
.evaluate());
188205
}
189-
return hasStatement();
190-
191206
}
192207

193208
@Benchmark
194-
public boolean removeByQueryReadCommitted() {
195-
209+
public long long_chain() {
196210
try (SailRepositoryConnection connection = repository.getConnection()) {
197-
connection.begin(IsolationLevels.READ_COMMITTED);
198-
connection.remove((Resource) null, RDF.TYPE, null);
199-
connection.commit();
200-
connection.begin(IsolationLevels.READ_COMMITTED);
201-
connection.add(statementList);
202-
connection.commit();
211+
return count(connection
212+
.prepareTupleQuery(long_chain)
213+
.evaluate());
203214
}
204-
return hasStatement();
205-
206215
}
207216

208217
@Benchmark
209-
public boolean simpleUpdateQueryIsolationReadCommitted() {
210-
218+
public long lots_of_optional() {
211219
try (SailRepositoryConnection connection = repository.getConnection()) {
212-
connection.begin(IsolationLevels.READ_COMMITTED);
213-
connection.prepareUpdate(query2).execute();
214-
connection.commit();
220+
return count(connection
221+
.prepareTupleQuery(lots_of_optional)
222+
.evaluate());
215223
}
224+
}
216225

226+
@Benchmark
227+
public long minus() {
217228
try (SailRepositoryConnection connection = repository.getConnection()) {
218-
connection.begin(IsolationLevels.READ_COMMITTED);
219-
connection.prepareUpdate(query3).execute();
220-
connection.commit();
229+
return count(connection
230+
.prepareTupleQuery(minus)
231+
.evaluate());
221232
}
222-
return hasStatement();
223-
224233
}
225234

226235
@Benchmark
227-
public boolean simpleUpdateQueryIsolationNone() {
228-
236+
public long nested_optionals() {
229237
try (SailRepositoryConnection connection = repository.getConnection()) {
230-
connection.begin(IsolationLevels.NONE);
231-
connection.prepareUpdate(query2).execute();
232-
connection.commit();
238+
return count(connection
239+
.prepareTupleQuery(nested_optionals)
240+
.evaluate());
233241
}
242+
}
234243

244+
// @Benchmark
245+
// public long particularly_large_join_surface() {
246+
// try (SailRepositoryConnection connection = repository.getConnection()) {
247+
// return connection
248+
// .prepareTupleQuery(particularly_large_join_surface)
249+
// .evaluate()
250+
// .stream()
251+
// .count();
252+
// }
253+
// }
254+
255+
@Benchmark
256+
public long query_distinct_predicates() {
235257
try (SailRepositoryConnection connection = repository.getConnection()) {
236-
connection.begin(IsolationLevels.NONE);
237-
connection.prepareUpdate(query3).execute();
238-
connection.commit();
258+
return count(connection
259+
.prepareTupleQuery(query_distinct_predicates)
260+
.evaluate());
239261
}
240-
return hasStatement();
241-
242262
}
243263

244-
private boolean hasStatement() {
264+
@Benchmark
265+
public long simple_filter_not() {
245266
try (SailRepositoryConnection connection = repository.getConnection()) {
246-
return connection.hasStatement(RDF.TYPE, RDF.TYPE, RDF.TYPE, true);
267+
return count(connection
268+
.prepareTupleQuery(simple_filter_not)
269+
.evaluate());
247270
}
248271
}
249272

273+
// @Benchmark
274+
// public long wild_card_chain_with_common_ends() {
275+
// try (SailRepositoryConnection connection = repository.getConnection()) {
276+
// return connection
277+
// .prepareTupleQuery(wild_card_chain_with_common_ends)
278+
// .evaluate()
279+
// .stream()
280+
// .count();
281+
// }
282+
// }
283+
284+
private static InputStream getResourceAsStream(String filename) {
285+
return QueryBenchmark.class.getClassLoader().getResourceAsStream(filename);
286+
}
250287
}

0 commit comments

Comments
 (0)