|
12 | 12 | package org.eclipse.rdf4j.sail.lmdb; |
13 | 13 |
|
14 | 14 | import java.io.IOException; |
15 | | -import java.util.HashMap; |
16 | 15 | import java.util.Map; |
| 16 | +import java.util.concurrent.ConcurrentHashMap; |
17 | 17 |
|
18 | 18 | import org.eclipse.rdf4j.model.IRI; |
19 | 19 | import org.eclipse.rdf4j.model.Resource; |
|
31 | 31 | class LmdbEvaluationStatistics extends EvaluationStatistics { |
32 | 32 |
|
33 | 33 | private static final Logger log = LoggerFactory.getLogger(LmdbEvaluationStatistics.class); |
| 34 | + private static final int SHARED_CACHE_MAX_ENTRIES = 262_144; |
| 35 | + private static final Map<SharedCardinalityKey, Double> sharedCardinalityCache = new ConcurrentHashMap<>(); |
34 | 36 |
|
35 | 37 | private final ValueStore valueStore; |
36 | 38 |
|
37 | 39 | private final TripleStore tripleStore; |
38 | | - private final Map<CardinalityKey, Double> cardinalityCache = new HashMap<>(); |
| 40 | + private final int tripleStoreIdentity; |
| 41 | + private final Map<CardinalityKey, Double> cardinalityCache = new ConcurrentHashMap<>(); |
39 | 42 |
|
40 | 43 | public LmdbEvaluationStatistics(ValueStore valueStore, TripleStore tripleStore) { |
41 | 44 | this.valueStore = valueStore; |
42 | 45 | this.tripleStore = tripleStore; |
| 46 | + this.tripleStoreIdentity = System.identityHashCode(tripleStore); |
43 | 47 | } |
44 | 48 |
|
45 | 49 | @Override |
@@ -116,17 +120,31 @@ private double cardinality(Resource subj, IRI pred, Value obj, Resource context) |
116 | 120 | } |
117 | 121 | } |
118 | 122 |
|
119 | | - return tripleStore.cardinality(subjID, predID, objID, contextID); |
120 | | - |
121 | | -// CardinalityKey key = new CardinalityKey(subjID, predID, objID, contextID); |
122 | | -// Double cached = cardinalityCache.get(key); |
123 | | -// if (cached != null) { |
124 | | -// return cached; |
125 | | -// } |
126 | | -// |
127 | | -// double cardinality = tripleStore.cardinality(subjID, predID, objID, contextID); |
128 | | -// cardinalityCache.put(key, cardinality); |
129 | | -// return cardinality; |
| 123 | + CardinalityKey key = new CardinalityKey(subjID, predID, objID, contextID); |
| 124 | + Double cached = cardinalityCache.get(key); |
| 125 | + if (cached != null) { |
| 126 | + return cached; |
| 127 | + } |
| 128 | + |
| 129 | + long revisionId = valueStore.getRevision().getRevisionId(); |
| 130 | + SharedCardinalityKey sharedKey = new SharedCardinalityKey(tripleStoreIdentity, revisionId, key); |
| 131 | + Double sharedCached = sharedCardinalityCache.get(sharedKey); |
| 132 | + if (sharedCached != null) { |
| 133 | + cardinalityCache.put(key, sharedCached); |
| 134 | + return sharedCached; |
| 135 | + } |
| 136 | + |
| 137 | + double cardinality = tripleStore.cardinality(subjID, predID, objID, contextID); |
| 138 | + cardinalityCache.put(key, cardinality); |
| 139 | + cacheSharedCardinality(sharedKey, cardinality); |
| 140 | + return cardinality; |
| 141 | + } |
| 142 | + |
| 143 | + private static void cacheSharedCardinality(SharedCardinalityKey key, double cardinality) { |
| 144 | + if (sharedCardinalityCache.size() >= SHARED_CACHE_MAX_ENTRIES) { |
| 145 | + sharedCardinalityCache.clear(); |
| 146 | + } |
| 147 | + sharedCardinalityCache.put(key, cardinality); |
130 | 148 | } |
131 | 149 |
|
132 | 150 | private static final class CardinalityKey { |
@@ -166,4 +184,52 @@ public int hashCode() { |
166 | 184 | return result; |
167 | 185 | } |
168 | 186 | } |
| 187 | + |
| 188 | + private static final class SharedCardinalityKey { |
| 189 | + private final int tripleStoreIdentity; |
| 190 | + private final long revisionId; |
| 191 | + private final long subjID; |
| 192 | + private final long predID; |
| 193 | + private final long objID; |
| 194 | + private final long contextID; |
| 195 | + private final int hashCode; |
| 196 | + |
| 197 | + private SharedCardinalityKey(int tripleStoreIdentity, long revisionId, CardinalityKey cardinalityKey) { |
| 198 | + this.tripleStoreIdentity = tripleStoreIdentity; |
| 199 | + this.revisionId = revisionId; |
| 200 | + this.subjID = cardinalityKey.subjID; |
| 201 | + this.predID = cardinalityKey.predID; |
| 202 | + this.objID = cardinalityKey.objID; |
| 203 | + this.contextID = cardinalityKey.contextID; |
| 204 | + int hash = Integer.hashCode(tripleStoreIdentity); |
| 205 | + hash = 31 * hash + Long.hashCode(revisionId); |
| 206 | + hash = 31 * hash + Long.hashCode(subjID); |
| 207 | + hash = 31 * hash + Long.hashCode(predID); |
| 208 | + hash = 31 * hash + Long.hashCode(objID); |
| 209 | + hash = 31 * hash + Long.hashCode(contextID); |
| 210 | + this.hashCode = hash; |
| 211 | + } |
| 212 | + |
| 213 | + @Override |
| 214 | + public boolean equals(Object obj) { |
| 215 | + if (this == obj) { |
| 216 | + return true; |
| 217 | + } |
| 218 | + if (!(obj instanceof SharedCardinalityKey)) { |
| 219 | + return false; |
| 220 | + } |
| 221 | + SharedCardinalityKey other = (SharedCardinalityKey) obj; |
| 222 | + return tripleStoreIdentity == other.tripleStoreIdentity |
| 223 | + && revisionId == other.revisionId |
| 224 | + && subjID == other.subjID |
| 225 | + && predID == other.predID |
| 226 | + && objID == other.objID |
| 227 | + && contextID == other.contextID; |
| 228 | + } |
| 229 | + |
| 230 | + @Override |
| 231 | + public int hashCode() { |
| 232 | + return hashCode; |
| 233 | + } |
| 234 | + } |
169 | 235 | } |
0 commit comments