|
2 | 2 |
|
3 | 3 | import stroom.bytebuffer.ByteBufferPool;
|
4 | 4 | import stroom.bytebuffer.ByteBufferPoolFactory;
|
| 5 | +import stroom.bytebuffer.PooledByteBuffer; |
5 | 6 | import stroom.lmdb.serde.IntegerSerde;
|
6 | 7 | import stroom.lmdb.serde.Serde;
|
7 | 8 | import stroom.lmdb.serde.StringSerde;
|
| 9 | +import stroom.test.common.TestUtil; |
| 10 | +import stroom.test.common.TestUtil.TimedCase; |
8 | 11 | import stroom.util.io.ByteSize;
|
9 | 12 | import stroom.util.logging.DurationTimer;
|
10 | 13 | import stroom.util.logging.LambdaLogger;
|
|
15 | 18 | import org.junit.jupiter.api.Test;
|
16 | 19 | import org.lmdbjava.DbiFlags;
|
17 | 20 |
|
| 21 | +import java.nio.ByteBuffer; |
18 | 22 | import java.util.ArrayList;
|
19 | 23 | import java.util.Collections;
|
| 24 | +import java.util.HashMap; |
20 | 25 | import java.util.List;
|
21 | 26 | import java.util.Map;
|
22 | 27 | import java.util.Map.Entry;
|
| 28 | +import java.util.Optional; |
| 29 | +import java.util.concurrent.ConcurrentHashMap; |
23 | 30 |
|
24 | 31 | public class TestLmdbPerformance extends AbstractDualEnvLmdbTest {
|
25 | 32 |
|
@@ -55,6 +62,17 @@ private BasicLmdbDb<Integer, String> createIntegerKeyDb(final LmdbEnv lmdbEnv,
|
55 | 62 | DbiFlags.MDB_INTEGERKEY);
|
56 | 63 | }
|
57 | 64 |
|
| 65 | + private BasicLmdbDb<String, String> createStringStringDb(final LmdbEnv lmdbEnv, |
| 66 | + final String name) { |
| 67 | + return new BasicLmdbDb<>( |
| 68 | + lmdbEnv, |
| 69 | + byteBufferPool, |
| 70 | + new StringSerde(), |
| 71 | + new StringSerde(), |
| 72 | + name, |
| 73 | + DbiFlags.MDB_CREATE); |
| 74 | + } |
| 75 | + |
58 | 76 | /**
|
59 | 77 | * Compare using MDB_APPEND vs not, when repeatedly putting a batch of entries.
|
60 | 78 | */
|
@@ -137,6 +155,75 @@ void testAppendVsAppendWithIntegerKey_withDeletes() {
|
137 | 155 | putData(db2, iterations, rounds, true, deleteBetweenRounds);
|
138 | 156 | }
|
139 | 157 |
|
| 158 | + @Disabled // manual perf test only |
| 159 | + @Test |
| 160 | + void testGetVsHeapMap() { |
| 161 | + final int iterations = 10_000_000; |
| 162 | + final int rounds = 4; |
| 163 | + final BasicLmdbDb<String, String> db3 = createStringStringDb(lmdbEnv1, "db3"); |
| 164 | + final Map<String, String> hashMap = new HashMap<>(); |
| 165 | + final Map<String, String> concurrentHashMap = new ConcurrentHashMap<>(); |
| 166 | + lmdbEnv1.doWithWriteTxn(writeTxn -> { |
| 167 | + db3.put(writeTxn, "foo", "bar", true); |
| 168 | + }); |
| 169 | + hashMap.put("foo", "bar"); |
| 170 | + concurrentHashMap.put("foo", "bar"); |
| 171 | + |
| 172 | + lmdbEnv1.doWithReadTxn(txn -> { |
| 173 | + try (PooledByteBuffer pooledByteBuffer = byteBufferPool.getPooledByteBuffer(10)) { |
| 174 | + final ByteBuffer keyBuffer = pooledByteBuffer.getByteBuffer(); |
| 175 | + db3.serializeKey(keyBuffer, "foo"); |
| 176 | + |
| 177 | + final TimedCase lmdbGetCaseWithSer = TimedCase.of("lmdb-get-with-ser", (round, iterations2) -> { |
| 178 | + for (long i = 0; i < iterations2; i++) { |
| 179 | + final Optional<String> foo = db3.get(txn, "foo"); |
| 180 | + if (foo.isEmpty()) { |
| 181 | + throw new RuntimeException("Empty"); |
| 182 | + } |
| 183 | + } |
| 184 | + }); |
| 185 | + |
| 186 | + final TimedCase lmdbGetCaseWithoutSer = TimedCase.of( |
| 187 | + "lmdb-get-without-ser", |
| 188 | + (round, iterations2) -> { |
| 189 | + for (long i = 0; i < iterations2; i++) { |
| 190 | + final Optional<ByteBuffer> foo = db3.getAsBytes(txn, keyBuffer); |
| 191 | + if (foo.isEmpty()) { |
| 192 | + throw new RuntimeException("Empty"); |
| 193 | + } |
| 194 | + } |
| 195 | + }); |
| 196 | + |
| 197 | + final TimedCase hashMapGet = TimedCase.of("hashMap", (round, iterations2) -> { |
| 198 | + for (long i = 0; i < iterations2; i++) { |
| 199 | + final String val = hashMap.get("foo"); |
| 200 | + if (val == null) { |
| 201 | + throw new RuntimeException("Empty"); |
| 202 | + } |
| 203 | + } |
| 204 | + }); |
| 205 | + |
| 206 | + final TimedCase concurrentMapGet = TimedCase.of("concurrentMap", (round, iterations2) -> { |
| 207 | + for (long i = 0; i < iterations2; i++) { |
| 208 | + final String val = concurrentHashMap.get("foo"); |
| 209 | + if (val == null) { |
| 210 | + throw new RuntimeException("Empty"); |
| 211 | + } |
| 212 | + } |
| 213 | + }); |
| 214 | + |
| 215 | + TestUtil.comparePerformance( |
| 216 | + rounds, |
| 217 | + iterations, |
| 218 | + LOGGER::info, |
| 219 | + lmdbGetCaseWithSer, |
| 220 | + lmdbGetCaseWithoutSer, |
| 221 | + hashMapGet, |
| 222 | + concurrentMapGet); |
| 223 | + } |
| 224 | + }); |
| 225 | + } |
| 226 | + |
140 | 227 | private void putData(final AbstractLmdbDb<Integer, String> db,
|
141 | 228 | final int iterations,
|
142 | 229 | final int rounds,
|
|
0 commit comments