Skip to content

Commit 7ac484a

Browse files
committed
GH-5691 CLI for running and storing query explanations
1 parent ea83bd7 commit 7ac484a

23 files changed

Lines changed: 4633 additions & 2 deletions

File tree

core/sail/lmdb/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@
210210
<artifactId>junit-jupiter-params</artifactId>
211211
<scope>test</scope>
212212
</dependency>
213+
<dependency>
214+
<groupId>${project.groupId}</groupId>
215+
<artifactId>rdf4j-queryrender</artifactId>
216+
<version>${project.version}</version>
217+
<scope>test</scope>
218+
</dependency>
213219
</dependencies>
214220
<build>
215221
<plugins>

core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/benchmark/ThemeQueryBenchmark.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,26 @@
1515

1616
import java.io.File;
1717
import java.io.IOException;
18+
import java.nio.file.Path;
1819
import java.util.concurrent.TimeUnit;
1920

2021
import org.apache.commons.io.FileUtils;
2122
import org.assertj.core.util.Files;
23+
import org.eclipse.rdf4j.benchmark.common.BenchmarkQuery;
2224
import org.eclipse.rdf4j.benchmark.common.ThemeQueryCatalog;
25+
import org.eclipse.rdf4j.benchmark.common.plan.FeatureFlagCollector;
26+
import org.eclipse.rdf4j.benchmark.common.plan.QueryPlanCapture;
27+
import org.eclipse.rdf4j.benchmark.common.plan.QueryPlanCaptureContext;
2328
import org.eclipse.rdf4j.benchmark.rio.util.ThemeDataSetGenerator;
2429
import org.eclipse.rdf4j.benchmark.rio.util.ThemeDataSetGenerator.Theme;
2530
import org.eclipse.rdf4j.common.transaction.IsolationLevels;
2631
import org.eclipse.rdf4j.query.explanation.Explanation;
32+
import org.eclipse.rdf4j.queryrender.sparql.TupleExprIRRenderer;
2733
import org.eclipse.rdf4j.repository.sail.SailRepository;
2834
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
2935
import org.eclipse.rdf4j.repository.util.RDFInserter;
3036
import org.eclipse.rdf4j.sail.lmdb.LmdbStore;
37+
import org.eclipse.rdf4j.sail.lmdb.config.LmdbStoreConfig;
3138
import org.junit.jupiter.api.Disabled;
3239
import org.junit.jupiter.api.Test;
3340
import org.openjdk.jmh.annotations.Benchmark;
@@ -56,6 +63,8 @@
5663
@OutputTimeUnit(TimeUnit.MILLISECONDS)
5764
public class ThemeQueryBenchmark {
5865

66+
private static final String STORE_NAME = "lmdb";
67+
5968
@Param({ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" })
6069
public int z_queryIndex;
6170

@@ -73,6 +82,8 @@ public class ThemeQueryBenchmark {
7382

7483
private File dataDir;
7584
private SailRepository repository;
85+
private LmdbStore store;
86+
private LmdbStoreConfig storeConfig;
7687
private Theme theme;
7788
private String query;
7889
private long expected;
@@ -91,8 +102,13 @@ public void setup() throws IOException {
91102
query = ThemeQueryCatalog.queryFor(theme, z_queryIndex);
92103
expected = ThemeQueryCatalog.expectedCountFor(theme, z_queryIndex);
93104
dataDir = Files.newTemporaryFolder();
94-
repository = new SailRepository(new LmdbStore(dataDir, ConfigUtil.createConfig()));
105+
storeConfig = ConfigUtil.createConfig();
106+
store = new LmdbStore(dataDir, storeConfig);
107+
repository = new SailRepository(store);
95108
loadData();
109+
if (QueryPlanCapture.isCaptureEnabled()) {
110+
captureQueryPlanSnapshot();
111+
}
96112
}
97113

98114
private void loadData() throws IOException {
@@ -104,6 +120,47 @@ private void loadData() throws IOException {
104120
}
105121
}
106122

123+
private void captureQueryPlanSnapshot() throws IOException {
124+
BenchmarkQuery benchmarkQuery = ThemeQueryCatalog.benchmarkQueryFor(theme, z_queryIndex);
125+
FeatureFlagCollector featureFlags = new FeatureFlagCollector()
126+
.addValue("themeBenchmark.themeName", () -> themeName)
127+
.addValue("themeBenchmark.queryIndex", () -> z_queryIndex)
128+
.addReflectiveGetter("lmdbStore.writable", store, "isWritable")
129+
.addReflectiveGetter("lmdbConfig.tripleIndexes", storeConfig, "getTripleIndexes")
130+
.addReflectiveGetter("lmdbConfig.forceSync", storeConfig, "getForceSync")
131+
.addReflectiveField("lmdbConfig.autoGrow", storeConfig, "autoGrow")
132+
.addReflectiveGetter("lmdbConfig.valueDbSize", storeConfig, "getValueDBSize")
133+
.addReflectiveGetter("lmdbConfig.tripleDbSize", storeConfig, "getTripleDBSize");
134+
QueryPlanCapture.registerConfiguredFeatureFlags(featureFlags);
135+
136+
QueryPlanCaptureContext context = QueryPlanCaptureContext.builder()
137+
.outputDirectory(QueryPlanCapture.resolveOutputDirectory().resolve(STORE_NAME))
138+
.queryId(STORE_NAME + "-" + themeName + "-q" + z_queryIndex)
139+
.queryString(query)
140+
.benchmark("ThemeQueryBenchmark")
141+
.addMetadata("store", STORE_NAME)
142+
.addMetadata("theme", themeName)
143+
.addMetadata("queryIndex", Integer.toString(z_queryIndex))
144+
.addMetadata("queryName", benchmarkQuery.getName())
145+
.addMetadata("expectedCount", Long.toString(expected))
146+
.addMetadata(QueryPlanCapture.metadataFromSystemProperties())
147+
.featureFlagCollector(featureFlags)
148+
.tupleExprRenderer(this::renderTupleExprWithIr)
149+
.build();
150+
151+
try (SailRepositoryConnection connection = repository.getConnection()) {
152+
Path snapshotPath = new QueryPlanCapture()
153+
.captureAndWrite(context, () -> connection.prepareTupleQuery(query));
154+
System.out.println("Query plan snapshot written to: " + snapshotPath);
155+
}
156+
}
157+
158+
private String renderTupleExprWithIr(org.eclipse.rdf4j.query.algebra.TupleExpr tupleExpr) {
159+
TupleExprIRRenderer.Config config = new TupleExprIRRenderer.Config();
160+
config.verifyRoundTrip = false;
161+
return new TupleExprIRRenderer(config).render(tupleExpr);
162+
}
163+
107164
@TearDown(Level.Trial)
108165
public void tearDown() throws IOException {
109166
repository.shutDown();

core/sail/memory/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@
9393
<version>${project.version}</version>
9494
<scope>test</scope>
9595
</dependency>
96+
<dependency>
97+
<groupId>${project.groupId}</groupId>
98+
<artifactId>rdf4j-queryrender</artifactId>
99+
<version>${project.version}</version>
100+
<scope>test</scope>
101+
</dependency>
96102
</dependencies>
97103
<build>
98104
<plugins>

core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/ThemeQueryBenchmark.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@
1414
import static org.junit.jupiter.api.Assertions.assertEquals;
1515

1616
import java.io.IOException;
17+
import java.nio.file.Path;
1718
import java.util.concurrent.TimeUnit;
1819

20+
import org.eclipse.rdf4j.benchmark.common.BenchmarkQuery;
1921
import org.eclipse.rdf4j.benchmark.common.ThemeQueryCatalog;
22+
import org.eclipse.rdf4j.benchmark.common.plan.FeatureFlagCollector;
23+
import org.eclipse.rdf4j.benchmark.common.plan.QueryPlanCapture;
24+
import org.eclipse.rdf4j.benchmark.common.plan.QueryPlanCaptureContext;
2025
import org.eclipse.rdf4j.benchmark.rio.util.ThemeDataSetGenerator;
2126
import org.eclipse.rdf4j.benchmark.rio.util.ThemeDataSetGenerator.Theme;
2227
import org.eclipse.rdf4j.common.transaction.IsolationLevels;
2328
import org.eclipse.rdf4j.query.explanation.Explanation;
29+
import org.eclipse.rdf4j.queryrender.sparql.TupleExprIRRenderer;
2430
import org.eclipse.rdf4j.repository.sail.SailRepository;
2531
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
2632
import org.eclipse.rdf4j.repository.util.RDFInserter;
@@ -53,6 +59,8 @@
5359
@OutputTimeUnit(TimeUnit.MILLISECONDS)
5460
public class ThemeQueryBenchmark {
5561

62+
private static final String STORE_NAME = "memory";
63+
5664
@Param({ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" })
5765
public int z_queryIndex;
5866

@@ -69,6 +77,7 @@ public class ThemeQueryBenchmark {
6977
public String themeName;
7078

7179
private SailRepository repository;
80+
private MemoryStore store;
7281
private Theme theme;
7382
private String query;
7483
private long expected;
@@ -86,8 +95,12 @@ public void setup() throws IOException {
8695
theme = Theme.valueOf(themeName);
8796
query = ThemeQueryCatalog.queryFor(theme, z_queryIndex);
8897
expected = ThemeQueryCatalog.expectedCountFor(theme, z_queryIndex);
89-
repository = new SailRepository(new MemoryStore());
98+
store = new MemoryStore();
99+
repository = new SailRepository(store);
90100
loadData();
101+
if (QueryPlanCapture.isCaptureEnabled()) {
102+
captureQueryPlanSnapshot();
103+
}
91104
}
92105

93106
private void loadData() throws IOException {
@@ -99,6 +112,45 @@ private void loadData() throws IOException {
99112
}
100113
}
101114

115+
private void captureQueryPlanSnapshot() throws IOException {
116+
BenchmarkQuery benchmarkQuery = ThemeQueryCatalog.benchmarkQueryFor(theme, z_queryIndex);
117+
FeatureFlagCollector featureFlags = new FeatureFlagCollector()
118+
.addValue("themeBenchmark.themeName", () -> themeName)
119+
.addValue("themeBenchmark.queryIndex", () -> z_queryIndex)
120+
.addReflectiveGetter("memoryStore.persist", store, "getPersist")
121+
.addReflectiveGetter("memoryStore.syncDelay", store, "getSyncDelay")
122+
.addReflectiveGetter("memoryStore.iterationCacheSyncThreshold", store,
123+
"getIterationCacheSyncThreshold");
124+
QueryPlanCapture.registerConfiguredFeatureFlags(featureFlags);
125+
126+
QueryPlanCaptureContext context = QueryPlanCaptureContext.builder()
127+
.outputDirectory(QueryPlanCapture.resolveOutputDirectory().resolve(STORE_NAME))
128+
.queryId(STORE_NAME + "-" + themeName + "-q" + z_queryIndex)
129+
.queryString(query)
130+
.benchmark("ThemeQueryBenchmark")
131+
.addMetadata("store", STORE_NAME)
132+
.addMetadata("theme", themeName)
133+
.addMetadata("queryIndex", Integer.toString(z_queryIndex))
134+
.addMetadata("queryName", benchmarkQuery.getName())
135+
.addMetadata("expectedCount", Long.toString(expected))
136+
.addMetadata(QueryPlanCapture.metadataFromSystemProperties())
137+
.featureFlagCollector(featureFlags)
138+
.tupleExprRenderer(this::renderTupleExprWithIr)
139+
.build();
140+
141+
try (SailRepositoryConnection connection = repository.getConnection()) {
142+
Path snapshotPath = new QueryPlanCapture()
143+
.captureAndWrite(context, () -> connection.prepareTupleQuery(query));
144+
System.out.println("Query plan snapshot written to: " + snapshotPath);
145+
}
146+
}
147+
148+
private String renderTupleExprWithIr(org.eclipse.rdf4j.query.algebra.TupleExpr tupleExpr) {
149+
TupleExprIRRenderer.Config config = new TupleExprIRRenderer.Config();
150+
config.verifyRoundTrip = false;
151+
return new TupleExprIRRenderer(config).render(tupleExpr);
152+
}
153+
102154
@TearDown(Level.Trial)
103155
public void tearDown() throws IOException {
104156
repository.shutDown();

testsuites/benchmark-common/pom.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,32 @@
3939
<artifactId>rdf4j-rio-api</artifactId>
4040
<version>${project.version}</version>
4141
</dependency>
42+
<dependency>
43+
<groupId>org.eclipse.rdf4j</groupId>
44+
<artifactId>rdf4j-query</artifactId>
45+
<version>${project.version}</version>
46+
</dependency>
47+
<dependency>
48+
<groupId>org.eclipse.rdf4j</groupId>
49+
<artifactId>rdf4j-queryalgebra-model</artifactId>
50+
<version>${project.version}</version>
51+
</dependency>
52+
<dependency>
53+
<groupId>com.fasterxml.jackson.core</groupId>
54+
<artifactId>jackson-databind</artifactId>
55+
</dependency>
4256
<dependency>
4357
<groupId>org.eclipse.rdf4j</groupId>
4458
<artifactId>rdf4j-rio-nquads</artifactId>
4559
<version>${project.version}</version>
4660
<scope>test</scope>
4761
</dependency>
62+
<dependency>
63+
<groupId>org.eclipse.rdf4j</groupId>
64+
<artifactId>rdf4j-queryparser-sparql</artifactId>
65+
<version>${project.version}</version>
66+
<scope>test</scope>
67+
</dependency>
4868
<dependency>
4969
<groupId>commons-io</groupId>
5070
<artifactId>commons-io</artifactId>

0 commit comments

Comments
 (0)