Skip to content

Commit 15a00b7

Browse files
committed
Setup Cassandra benchmark env and add CQLMultiQueryBenchmark
Signed-off-by: Boxuan Li <[email protected]>
1 parent 543632f commit 15a00b7

File tree

4 files changed

+196
-22
lines changed

4 files changed

+196
-22
lines changed

.github/workflows/ci-benchmark.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,18 @@ jobs:
4444
with:
4545
java-version: 1.8
4646
- run: mvn clean install --projects janusgraph-all -Pjanusgraph-cache -Dmaven.javadoc.skip=true ${{ env.BUILD_MAVEN_OPTS }}
47-
47+
- run: mvn verify --projects janusgraph-all -Pjanusgraph-cache ${{ env.VERIFY_MAVEN_OPTS }}
4848
benchmark:
4949
name: Performance regression check
5050
runs-on: ubuntu-latest
51+
needs: build-all
5152
steps:
53+
# install CCM for CQL benchmarks
54+
- uses: actions/setup-python@v2
55+
with:
56+
python-version: '3.x'
57+
- run: pip install git+https://github.com/li-boxuan/ccm.git
58+
5259
- uses: actions/checkout@v2
5360
- uses: actions/cache@v2
5461
with:
@@ -61,6 +68,9 @@ jobs:
6168
java-version: 1.8
6269
- run: mvn clean install -Pjanusgraph-benchmark ${{ env.BUILD_MAVEN_OPTS }} -Dgpg.skip=true
6370
- run: mvn verify --projects janusgraph-benchmark
71+
env:
72+
CCM_CLUSTER_START_DEFAULT_TIMEOUT: 300
73+
CCM_UPDATE_PID_DEFAULT_TIMEOUT: 300
6474

6575
# Download previous benchmark result from cache (if exists)
6676
- name: Download previous benchmark data

janusgraph-benchmark/pom.xml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
</properties>
2020

2121
<dependencies>
22+
<dependency>
23+
<groupId>org.janusgraph</groupId>
24+
<artifactId>janusgraph-cql</artifactId>
25+
<version>${project.version}</version>
26+
</dependency>
27+
2228
<!-- Logging backends. -->
2329
<dependency>
2430
<groupId>org.apache.logging.log4j</groupId>
@@ -52,6 +58,25 @@
5258
<artifactId>janusgraph-inmemory</artifactId>
5359
<version>${project.version}</version>
5460
</dependency>
61+
62+
<!-- needed by Cassandra ccm -->
63+
<dependency>
64+
<groupId>com.datastax.oss</groupId>
65+
<artifactId>java-driver-test-infra</artifactId>
66+
<version>${cassandra-driver.version}</version>
67+
<exclusions>
68+
<exclusion>
69+
<groupId>com.datastax.oss</groupId>
70+
<artifactId>java-driver-core</artifactId>
71+
</exclusion>
72+
</exclusions>
73+
</dependency>
74+
<dependency>
75+
<groupId>org.apache.commons</groupId>
76+
<artifactId>commons-exec</artifactId>
77+
<version>1.3</version>
78+
</dependency>
79+
5580
</dependencies>
5681

5782
<profiles>
@@ -80,7 +105,6 @@
80105
<argument>-classpath</argument>
81106
<classpath/>
82107
<argument>org.janusgraph.BenchmarkRunner</argument>
83-
<argument>.*Benchmark</argument>
84108
</arguments>
85109
</configuration>
86110
</execution>

janusgraph-benchmark/src/main/java/org/janusgraph/BenchmarkRunner.java

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package org.janusgraph;
1616

17+
import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge;
1718
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
1819
import org.openjdk.jmh.results.Result;
1920
import org.openjdk.jmh.results.RunResult;
@@ -34,22 +35,7 @@
3435
import java.util.Map;
3536

3637
public class BenchmarkRunner {
37-
public static void main(String[] args) throws RunnerException, IOException {
38-
final ChainedOptionsBuilder builder = new OptionsBuilder()
39-
.forks(1)
40-
.measurementTime(TimeValue.seconds(5))
41-
.shouldFailOnError(true)
42-
.warmupIterations(2)
43-
.warmupTime(TimeValue.seconds(1));
44-
if (args.length > 0) {
45-
for (String arg : args) {
46-
builder.include(arg);
47-
}
48-
} else {
49-
builder.include(".*Benchmark");
50-
}
51-
builder.exclude(".*StaticArrayEntryListBenchmark");
52-
Collection<RunResult> results = new Runner(builder.build()).run();
38+
private static void transformResults(Collection<RunResult> results, List<Map<String, Object>> outputs) {
5339
Map<String, Double> metrics = new HashMap<>();
5440
for (RunResult result : results) {
5541
Result primaryResult = result.getPrimaryResult();
@@ -62,17 +48,68 @@ public static void main(String[] args) throws RunnerException, IOException {
6248
// we sum up results with different params against same benchmark
6349
metrics.put(benchmark, metrics.getOrDefault(benchmark, 0d) + score);
6450
}
65-
List<Map<String, Object>> outputs = new ArrayList<>();
6651
for (Map.Entry<String, Double> entry : metrics.entrySet()) {
6752
outputs.add(new HashMap() {{
6853
put("name", entry.getKey());
6954
put("value", entry.getValue());
7055
put("unit", "ms/op");
7156
}});
7257
}
73-
String workspace = System.getenv("${GITHUB_WORKSPACE}");
74-
File file = new File(workspace, "benchmark.json");
75-
System.out.println("writing to " + file.getAbsolutePath());
58+
}
59+
60+
private static void runCqlBenchmarks(ChainedOptionsBuilder cqlBuilder, List<Map<String, Object>> outputs) throws RunnerException, InterruptedException, IOException {
61+
CcmBridge.Builder builder =
62+
CcmBridge.builder()
63+
.withNodes(1);
64+
CcmBridge bridge = builder.build();
65+
Runtime.getRuntime().addShutdownHook(
66+
new Thread(
67+
() -> {
68+
bridge.stop();
69+
bridge.remove();
70+
}
71+
)
72+
);
73+
bridge.create();
74+
bridge.start();
75+
System.out.println("Cassandra version = " + bridge.getCassandraVersion());
76+
77+
cqlBuilder.include("CQL.*Benchmark");
78+
transformResults(new Runner(cqlBuilder.build()).run(), outputs);
79+
}
80+
81+
private static ChainedOptionsBuilder getJmhBuilder() {
82+
return new OptionsBuilder()
83+
.forks(1)
84+
.measurementTime(TimeValue.seconds(5))
85+
.shouldFailOnError(true)
86+
.warmupIterations(2)
87+
.warmupTime(TimeValue.seconds(1));
88+
}
89+
90+
public static void main(String[] args) throws RunnerException, IOException, InterruptedException {
91+
final boolean runSpecifiedTests = args.length > 0;
92+
final List<Map<String, Object>> outputs = new ArrayList<>();
93+
94+
final ChainedOptionsBuilder builder = getJmhBuilder();
95+
if (runSpecifiedTests) {
96+
for (String arg : args) {
97+
builder.include(arg);
98+
}
99+
} else {
100+
builder.include(".*Benchmark");
101+
builder.exclude("StaticArrayEntryListBenchmark");
102+
builder.exclude("CQL.*Benchmark");
103+
}
104+
Collection<RunResult> results = new Runner(builder.build()).run();
105+
transformResults(results, outputs);
106+
107+
// run benchmarks using Cassandra (if ccm is available)
108+
if (!runSpecifiedTests) {
109+
runCqlBenchmarks(getJmhBuilder(), outputs);
110+
}
111+
112+
File file = new File("benchmark.json");
76113
ObjectMapper objectMapper = new ObjectMapper();
77114
String json = objectMapper.writeValueAsString(outputs);
78115
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2022 JanusGraph Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package org.janusgraph;
16+
17+
import org.apache.tinkerpop.gremlin.structure.Vertex;
18+
import org.janusgraph.core.JanusGraph;
19+
import org.janusgraph.core.JanusGraphFactory;
20+
import org.janusgraph.core.JanusGraphTransaction;
21+
import org.janusgraph.core.PropertyKey;
22+
import org.janusgraph.core.schema.JanusGraphManagement;
23+
import org.janusgraph.diskstorage.BackendException;
24+
import org.janusgraph.diskstorage.configuration.ModifiableConfiguration;
25+
import org.janusgraph.diskstorage.configuration.WriteConfiguration;
26+
import org.janusgraph.diskstorage.cql.CQLConfigOptions;
27+
import org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration;
28+
import org.openjdk.jmh.annotations.Benchmark;
29+
import org.openjdk.jmh.annotations.BenchmarkMode;
30+
import org.openjdk.jmh.annotations.Fork;
31+
import org.openjdk.jmh.annotations.Mode;
32+
import org.openjdk.jmh.annotations.OutputTimeUnit;
33+
import org.openjdk.jmh.annotations.Param;
34+
import org.openjdk.jmh.annotations.Scope;
35+
import org.openjdk.jmh.annotations.Setup;
36+
import org.openjdk.jmh.annotations.State;
37+
import org.openjdk.jmh.annotations.TearDown;
38+
39+
import java.util.List;
40+
import java.util.concurrent.TimeUnit;
41+
42+
@BenchmarkMode(Mode.AverageTime)
43+
@Fork(1)
44+
@State(Scope.Benchmark)
45+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
46+
public class CQLMultiQueryBenchmark {
47+
@Param({"100", "500"})
48+
int fanoutFactor;
49+
50+
JanusGraph graph;
51+
52+
public WriteConfiguration getConfiguration() {
53+
ModifiableConfiguration config = GraphDatabaseConfiguration.buildGraphConfiguration();
54+
config.set(GraphDatabaseConfiguration.STORAGE_BACKEND,"cql");
55+
config.set(CQLConfigOptions.LOCAL_DATACENTER, "dc1");
56+
config.set(GraphDatabaseConfiguration.USE_MULTIQUERY, true);
57+
return config.getConfiguration();
58+
}
59+
60+
@Setup
61+
public void setUp() throws Exception {
62+
graph = JanusGraphFactory.open(getConfiguration());
63+
64+
JanusGraphManagement mgmt = graph.openManagement();
65+
PropertyKey name = mgmt.makePropertyKey("name").dataType(String.class).make();
66+
mgmt.buildIndex("nameIndex", Vertex.class).addKey(name).buildCompositeIndex();
67+
mgmt.commit();
68+
69+
Vertex v = graph.addVertex("name", "outer");
70+
for (int i = 0; i < fanoutFactor; i++) {
71+
Vertex otherV = graph.addVertex("name", "middle");
72+
v.addEdge("connects", otherV);
73+
for (int j = 0; j < fanoutFactor; j++) {
74+
Vertex innerV = graph.addVertex("name", "inner");
75+
otherV.addEdge("connects", innerV);
76+
}
77+
graph.tx().commit();
78+
}
79+
}
80+
81+
@TearDown
82+
public void tearDown() throws BackendException {
83+
JanusGraphFactory.drop(graph);
84+
}
85+
86+
@Benchmark
87+
public List<Object> getNeighborNames() {
88+
JanusGraphTransaction tx = graph.buildTransaction()
89+
.start();
90+
List<Object> names = tx.traversal().V().has("name", "outer").out().out().values("name").toList();
91+
tx.rollback();
92+
return names;
93+
}
94+
95+
@Benchmark
96+
public List<Object> getNames() {
97+
JanusGraphTransaction tx = graph.buildTransaction()
98+
.start();
99+
List<Object> names = tx.traversal().V().has("name", "inner").values("name").toList();
100+
tx.rollback();
101+
return names;
102+
}
103+
}

0 commit comments

Comments
 (0)