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
1515import java .io .IOException ;
1616import java .io .InputStream ;
1717import java .nio .charset .StandardCharsets ;
18- import java .util .List ;
1918import java .util .concurrent .TimeUnit ;
19+ import java .util .stream .Stream ;
2020
2121import org .apache .commons .io .FileUtils ;
2222import org .apache .commons .io .IOUtils ;
2323import org .assertj .core .util .Files ;
24- import org .eclipse .rdf4j .common .iteration .Iterations ;
2524import 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 ;
2927import org .eclipse .rdf4j .repository .sail .SailRepository ;
3028import org .eclipse .rdf4j .repository .sail .SailRepositoryConnection ;
3129import org .eclipse .rdf4j .rio .RDFFormat ;
4846import 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 )
6058public 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