Skip to content

Commit 18f1bef

Browse files
committed
GH-5438 Use thread-local pool in LmdbStore to minimize synchronization
1 parent ce04587 commit 18f1bef

File tree

5 files changed

+66
-57
lines changed

5 files changed

+66
-57
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ class LmdbContextIdIterator implements Closeable {
6565

6666
private final Thread ownerThread = Thread.currentThread();
6767

68-
LmdbContextIdIterator(Pool pool, int dbi, Txn txnRef) throws IOException {
69-
this.pool = pool;
68+
LmdbContextIdIterator(int dbi, Txn txnRef) throws IOException {
69+
this.pool = Pool.get();
7070
this.keyData = pool.getVal();
7171
this.valueData = pool.getVal();
7272

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ class LmdbRecordIterator implements RecordIterator {
7979

8080
private final Thread ownerThread = Thread.currentThread();
8181

82-
LmdbRecordIterator(Pool pool, TripleIndex index, boolean rangeSearch, long subj, long pred, long obj,
82+
LmdbRecordIterator(TripleIndex index, boolean rangeSearch, long subj, long pred, long obj,
8383
long context, boolean explicit, Txn txnRef) throws IOException {
84-
this.pool = pool;
84+
this.pool = Pool.get();
8585
this.keyData = pool.getVal();
8686
this.valueData = pool.getVal();
8787
this.index = index;

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,10 @@ public void clearInferred(Resource... contexts) throws SailException {
200200
sailChangedEvent.setStatementsRemoved(true);
201201
}
202202

203+
@Override
204+
protected void closeInternal() throws SailException {
205+
super.closeInternal();
206+
// release thread-local pool
207+
Pool.release();
208+
}
203209
}

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

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,81 +19,85 @@
1919
* A simple pool for {@link MDBVal}, {@link ByteBuffer} and {@link Statistics} instances.
2020
*/
2121
class Pool {
22+
// thread-local pool instance
23+
private static final ThreadLocal<Pool> threadlocal = ThreadLocal.withInitial(Pool::new);
2224

2325
private final MDBVal[] valPool = new MDBVal[1024];
2426
private final ByteBuffer[] keyPool = new ByteBuffer[1024];
2527
private final Statistics[] statisticsPool = new Statistics[512];
26-
private volatile int valPoolIndex = -1;
27-
private volatile int keyPoolIndex = -1;
28-
private volatile int statisticsPoolIndex = -1;
28+
private int valPoolIndex = -1;
29+
private int keyPoolIndex = -1;
30+
private int statisticsPoolIndex = -1;
2931

30-
MDBVal getVal() {
31-
synchronized (valPool) {
32-
if (valPoolIndex >= 0) {
33-
return valPool[valPoolIndex--];
34-
}
32+
final MDBVal getVal() {
33+
if (valPoolIndex >= 0) {
34+
return valPool[valPoolIndex--];
3535
}
3636
return MDBVal.malloc();
3737
}
3838

39-
ByteBuffer getKeyBuffer() {
40-
synchronized (keyPool) {
41-
if (keyPoolIndex >= 0) {
42-
ByteBuffer bb = keyPool[keyPoolIndex--];
43-
bb.clear();
44-
return bb;
45-
}
39+
final ByteBuffer getKeyBuffer() {
40+
if (keyPoolIndex >= 0) {
41+
ByteBuffer bb = keyPool[keyPoolIndex--];
42+
bb.clear();
43+
return bb;
4644
}
4745
return MemoryUtil.memAlloc(TripleStore.MAX_KEY_LENGTH);
4846
}
4947

50-
Statistics getStatistics() {
51-
synchronized (statisticsPool) {
52-
if (statisticsPoolIndex >= 0) {
53-
return statisticsPool[statisticsPoolIndex--];
54-
}
48+
final Statistics getStatistics() {
49+
if (statisticsPoolIndex >= 0) {
50+
return statisticsPool[statisticsPoolIndex--];
5551
}
5652
return new Statistics();
5753
}
5854

59-
void free(MDBVal val) {
60-
synchronized (valPool) {
61-
if (valPoolIndex < valPool.length - 1) {
62-
valPool[++valPoolIndex] = val;
63-
} else {
64-
val.close();
65-
}
55+
final void free(MDBVal val) {
56+
if (valPoolIndex < valPool.length - 1) {
57+
valPool[++valPoolIndex] = val;
58+
} else {
59+
val.close();
6660
}
6761
}
6862

69-
void free(ByteBuffer bb) {
70-
synchronized (keyPool) {
71-
if (keyPoolIndex < keyPool.length - 1) {
72-
keyPool[++keyPoolIndex] = bb;
73-
} else {
74-
MemoryUtil.memFree(bb);
75-
}
63+
final void free(ByteBuffer bb) {
64+
if (keyPoolIndex < keyPool.length - 1) {
65+
keyPool[++keyPoolIndex] = bb;
66+
} else {
67+
MemoryUtil.memFree(bb);
7668
}
7769
}
7870

79-
void free(Statistics statistics) {
80-
synchronized (statisticsPool) {
81-
if (statisticsPoolIndex < statisticsPool.length - 1) {
82-
statisticsPool[++statisticsPoolIndex] = statistics;
83-
}
71+
final void free(Statistics statistics) {
72+
if (statisticsPoolIndex < statisticsPool.length - 1) {
73+
statisticsPool[++statisticsPoolIndex] = statistics;
8474
}
8575
}
8676

87-
void close() {
88-
synchronized (valPool) {
89-
while (valPoolIndex >= 0) {
90-
valPool[valPoolIndex--].close();
91-
}
77+
final void close() {
78+
while (valPoolIndex >= 0) {
79+
valPool[valPoolIndex--].close();
9280
}
93-
synchronized (keyPool) {
94-
while (keyPoolIndex >= 0) {
95-
MemoryUtil.memFree(keyPool[keyPoolIndex--]);
96-
}
81+
while (keyPoolIndex >= 0) {
82+
MemoryUtil.memFree(keyPool[keyPoolIndex--]);
9783
}
9884
}
85+
86+
/**
87+
* Get a pool instance for the current thread.
88+
*
89+
* @return a Pool instance
90+
*/
91+
public static Pool get() {
92+
return threadlocal.get();
93+
}
94+
95+
/**
96+
* Release the pool instance for the current thread.
97+
*/
98+
public static void release() {
99+
Pool pool = threadlocal.get();
100+
pool.close();
101+
threadlocal.remove();
102+
}
99103
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ class TripleStore implements Closeable {
163163
private long mapSize;
164164
private long writeTxn;
165165
private final TxnManager txnManager;
166-
private final Pool pool = new Pool();
167166

168167
private TxnRecordCache recordCache = null;
169168

@@ -391,7 +390,7 @@ private void reindex(Set<String> currentIndexSpecs, Set<String> newIndexSpecs) t
391390
TripleIndex addedIndex = new TripleIndex(fieldSeq);
392391
RecordIterator[] sourceIter = { null };
393392
try {
394-
sourceIter[0] = new LmdbRecordIterator(pool, sourceIndex, false, -1, -1, -1, -1,
393+
sourceIter[0] = new LmdbRecordIterator(sourceIndex, false, -1, -1, -1, -1,
395394
explicit, txnManager.createTxn(txn));
396395

397396
RecordIterator it = sourceIter[0];
@@ -482,7 +481,7 @@ public void close() throws IOException {
482481
* @throws IOException
483482
*/
484483
public LmdbContextIdIterator getContexts(Txn txn) throws IOException {
485-
return new LmdbContextIdIterator(this.pool, this.contextsDbi, txn);
484+
return new LmdbContextIdIterator(this.contextsDbi, txn);
486485
}
487486

488487
/**
@@ -511,7 +510,7 @@ public RecordIterator getTriples(Txn txn, long subj, long pred, long obj, long c
511510

512511
private RecordIterator getTriplesUsingIndex(Txn txn, long subj, long pred, long obj, long context,
513512
boolean explicit, TripleIndex index, boolean rangeSearch) throws IOException {
514-
return new LmdbRecordIterator(pool, index, rangeSearch, subj, pred, obj, context, explicit, txn);
513+
return new LmdbRecordIterator(index, rangeSearch, subj, pred, obj, context, explicit, txn);
515514
}
516515

517516
/**
@@ -676,6 +675,7 @@ protected double cardinality(long subj, long pred, long obj, long context) throw
676675
}
677676

678677
return txnManager.doWith((stack, txn) -> {
678+
Pool pool = Pool.get();
679679
final Statistics s = pool.getStatistics();
680680
try {
681681
MDBVal maxKey = MDBVal.malloc(stack);
@@ -1329,7 +1329,6 @@ public String toString() {
13291329
void close() {
13301330
mdb_dbi_close(env, dbiExplicit);
13311331
mdb_dbi_close(env, dbiInferred);
1332-
pool.close();
13331332
}
13341333

13351334
void clear(long txn) {

0 commit comments

Comments
 (0)