Skip to content

Commit dcbceaa

Browse files
committed
GH-3572 benchmark and test
1 parent 4f3cee4 commit dcbceaa

File tree

3 files changed

+293
-0
lines changed

3 files changed

+293
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2021 Eclipse RDF4J contributors.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Distribution License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/org/documents/edl-v10.php.
7+
******************************************************************************/
8+
9+
package org.eclipse.rdf4j.sail.memory.benchmark;
10+
11+
import java.io.IOException;
12+
import java.io.InputStream;
13+
import java.util.concurrent.CountDownLatch;
14+
import java.util.concurrent.ExecutorService;
15+
import java.util.concurrent.Executors;
16+
17+
import org.openjdk.jmh.annotations.Level;
18+
import org.openjdk.jmh.annotations.Scope;
19+
import org.openjdk.jmh.annotations.Setup;
20+
import org.openjdk.jmh.annotations.State;
21+
import org.openjdk.jmh.annotations.TearDown;
22+
23+
@State(Scope.Benchmark)
24+
public class BaseConcurrentBenchmark {
25+
26+
ExecutorService executorService;
27+
28+
@Setup(Level.Trial)
29+
public void setup() throws Exception {
30+
// Logger root = (Logger) LoggerFactory.getLogger("");
31+
// root.setLevel(ch.qos.logback.classic.Level.INFO);
32+
33+
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
34+
}
35+
36+
@TearDown(Level.Trial)
37+
public void tearDown() throws Exception {
38+
executorService.shutdownNow();
39+
}
40+
41+
void threads(int threadCount, Runnable runnable) throws InterruptedException {
42+
43+
CountDownLatch latch = new CountDownLatch(1);
44+
CountDownLatch latchDone = new CountDownLatch(threadCount);
45+
46+
for (int i = 0; i < threadCount; i++) {
47+
executorService.submit(() -> {
48+
try {
49+
latch.await();
50+
runnable.run();
51+
} catch (InterruptedException e) {
52+
e.printStackTrace();
53+
} finally {
54+
latchDone.countDown();
55+
}
56+
});
57+
}
58+
59+
latch.countDown();
60+
latchDone.await();
61+
62+
}
63+
64+
static InputStream getResourceAsStream(String filename) {
65+
return BaseConcurrentBenchmark.class.getClassLoader().getResourceAsStream(filename);
66+
}
67+
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2021 Eclipse RDF4J contributors.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Distribution License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/org/documents/edl-v10.php.
7+
******************************************************************************/
8+
9+
package org.eclipse.rdf4j.sail.memory.benchmark;
10+
11+
import java.io.InputStream;
12+
import java.util.Collections;
13+
import java.util.List;
14+
import java.util.Random;
15+
import java.util.concurrent.TimeUnit;
16+
import java.util.concurrent.atomic.AtomicInteger;
17+
import java.util.stream.Collectors;
18+
import java.util.stream.Stream;
19+
20+
import org.eclipse.rdf4j.common.transaction.IsolationLevels;
21+
import org.eclipse.rdf4j.model.IRI;
22+
import org.eclipse.rdf4j.model.Literal;
23+
import org.eclipse.rdf4j.model.Value;
24+
import org.eclipse.rdf4j.model.util.Values;
25+
import org.eclipse.rdf4j.repository.sail.SailRepository;
26+
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
27+
import org.eclipse.rdf4j.rio.RDFFormat;
28+
import org.eclipse.rdf4j.sail.memory.MemoryStore;
29+
import org.eclipse.rdf4j.sail.memory.model.MemIRI;
30+
import org.eclipse.rdf4j.sail.memory.model.MemValue;
31+
import org.eclipse.rdf4j.sail.memory.model.MemValueFactory;
32+
import org.openjdk.jmh.annotations.Benchmark;
33+
import org.openjdk.jmh.annotations.BenchmarkMode;
34+
import org.openjdk.jmh.annotations.Fork;
35+
import org.openjdk.jmh.annotations.Level;
36+
import org.openjdk.jmh.annotations.Measurement;
37+
import org.openjdk.jmh.annotations.Mode;
38+
import org.openjdk.jmh.annotations.OutputTimeUnit;
39+
import org.openjdk.jmh.annotations.Scope;
40+
import org.openjdk.jmh.annotations.Setup;
41+
import org.openjdk.jmh.annotations.State;
42+
import org.openjdk.jmh.annotations.TearDown;
43+
import org.openjdk.jmh.annotations.Warmup;
44+
import org.openjdk.jmh.infra.Blackhole;
45+
46+
import com.google.common.base.Stopwatch;
47+
import com.google.common.collect.Lists;
48+
49+
/**
50+
* @author Håvard M. Ottestad
51+
*/
52+
@State(Scope.Benchmark)
53+
@Warmup(iterations = 20)
54+
@BenchmarkMode({ Mode.AverageTime })
55+
@Fork(value = 1, jvmArgs = { "-Xms1G", "-Xmx1G", })
56+
@Measurement(iterations = 10)
57+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
58+
public class MemValueFactoryConcurrentBenchmark extends BaseConcurrentBenchmark {
59+
60+
public static final int BUCKET_SIZE = 10000;
61+
private SailRepository repository;
62+
private List<List<Value>> values;
63+
64+
@Setup(Level.Trial)
65+
public void setup() throws Exception {
66+
super.setup();
67+
repository = new SailRepository(new MemoryStore());
68+
69+
try (SailRepositoryConnection connection = repository.getConnection()) {
70+
connection.begin(IsolationLevels.NONE);
71+
try (InputStream resourceAsStream = getResourceAsStream("benchmarkFiles/datagovbe-valid.ttl")) {
72+
connection.add(resourceAsStream, RDFFormat.TURTLE);
73+
}
74+
connection.commit();
75+
76+
List<Value> collect = connection.getStatements(null, null, null)
77+
.stream()
78+
.flatMap(s -> Stream.of(s.getSubject(), s.getPredicate(), s.getObject()))
79+
.distinct()
80+
.map(v -> {
81+
if (v.isIRI()) {
82+
return Values.iri(v.stringValue());
83+
} else if (v.isBNode()) {
84+
return Values.bnode(v.stringValue());
85+
} else if (v.isLiteral()) {
86+
Literal literal = (Literal) v;
87+
if (literal.getLanguage().isPresent()) {
88+
return Values.literal(literal.stringValue(), literal.getLanguage().get());
89+
} else {
90+
return Values.literal(literal.stringValue(), literal.getDatatype());
91+
}
92+
}
93+
throw new IllegalStateException("Could not map '" + v + "'");
94+
})
95+
.collect(Collectors.toList());
96+
97+
Collections.shuffle(collect, new Random(4583295));
98+
99+
values = Lists.partition(collect, BUCKET_SIZE);
100+
101+
}
102+
103+
}
104+
105+
public static void main(String[] args) throws Exception {
106+
MemValueFactoryConcurrentBenchmark memValueFactoryConcurrentBenchmark = new MemValueFactoryConcurrentBenchmark();
107+
memValueFactoryConcurrentBenchmark.setup();
108+
109+
System.out.println("Setup complete");
110+
111+
Stopwatch stopwatch = Stopwatch.createStarted();
112+
while (stopwatch.elapsed(TimeUnit.MINUTES) < 5) {
113+
memValueFactoryConcurrentBenchmark.onlyReads(new Blackhole(
114+
"Today's password is swordfish. I understand instantiating Blackholes directly is dangerous."));
115+
}
116+
117+
}
118+
119+
@TearDown(Level.Trial)
120+
public void tearDown() throws Exception {
121+
super.tearDown();
122+
repository.shutDown();
123+
}
124+
125+
@Benchmark
126+
public void onlyReads(Blackhole blackhole) throws Exception {
127+
128+
MemValueFactory valueFactory = (MemValueFactory) repository.getValueFactory();
129+
130+
Random random = new Random(48593);
131+
132+
threads(100, () -> {
133+
134+
List<Value> values = this.values.get(random.nextInt(this.values.size()));
135+
136+
for (Value value : values) {
137+
MemValue memValue = valueFactory.getMemValue(value);
138+
blackhole.consume(memValue);
139+
}
140+
141+
});
142+
143+
}
144+
145+
@Benchmark
146+
public void readHeavy(Blackhole blackhole) throws Exception {
147+
148+
MemoryStore memoryStore = new MemoryStore();
149+
memoryStore.init();
150+
MemValueFactory valueFactory = (MemValueFactory) memoryStore.getValueFactory();
151+
152+
Random random = new Random(48593);
153+
154+
threads(100, () -> {
155+
Random r = new Random(random.nextInt());
156+
for (int i = 0; i < BUCKET_SIZE; i++) {
157+
MemIRI orCreateMemURI = valueFactory
158+
.getOrCreateMemURI(Values.iri("http://example.com", "" + r.nextInt(BUCKET_SIZE / 10)));
159+
blackhole.consume(orCreateMemURI);
160+
}
161+
});
162+
163+
}
164+
165+
@Benchmark
166+
public void onlyWrites(Blackhole blackhole) throws Exception {
167+
168+
MemoryStore memoryStore = new MemoryStore();
169+
memoryStore.init();
170+
MemValueFactory valueFactory = (MemValueFactory) memoryStore.getValueFactory();
171+
172+
AtomicInteger atomicInteger = new AtomicInteger();
173+
174+
threads(100, () -> {
175+
int base = atomicInteger.incrementAndGet();
176+
for (int i = 0; i < BUCKET_SIZE; i++) {
177+
IRI iri = valueFactory.createIRI("http://example.com", base + "-" + i);
178+
blackhole.consume(iri);
179+
}
180+
});
181+
182+
}
183+
184+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022 Eclipse RDF4J contributors.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Distribution License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/org/documents/edl-v10.php.
7+
******************************************************************************/
8+
9+
package org.eclipse.rdf4j.sail.memory.model;
10+
11+
import static org.junit.jupiter.api.Assertions.assertTrue;
12+
13+
import org.eclipse.rdf4j.model.IRI;
14+
import org.eclipse.rdf4j.model.util.Values;
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.Timeout;
17+
18+
public class WeakObjectRegistryTest {
19+
20+
@Test
21+
@Timeout(5)
22+
public void testGC() throws InterruptedException {
23+
24+
WeakObjectRegistry<IRI> objects = new WeakObjectRegistry<>();
25+
26+
IRI iri = Values.iri("http://example.com/1");
27+
28+
objects.add(iri);
29+
30+
assertTrue(objects.contains(iri));
31+
32+
iri = null;
33+
34+
while (objects.contains(Values.iri("http://example.com/1"))) {
35+
System.gc();
36+
Thread.sleep(10);
37+
}
38+
39+
}
40+
41+
}

0 commit comments

Comments
 (0)