CavalliumDBEngine/src/example/java/it.cavallium.dbengine.client/Example.java

297 lines
12 KiB
Java
Raw Normal View History

package it.cavallium.dbengine.client;
import com.google.common.primitives.Ints;
import io.netty.buffer.ByteBuf;
2021-01-31 15:47:48 +01:00
import io.netty.buffer.Unpooled;
import it.cavallium.dbengine.database.Column;
2021-01-31 19:52:47 +01:00
import it.cavallium.dbengine.database.LLKeyValueDatabase;
2021-01-31 21:23:43 +01:00
import it.cavallium.dbengine.database.collections.DatabaseMapDictionaryDeep;
2021-01-31 15:47:48 +01:00
import it.cavallium.dbengine.database.collections.DatabaseMapDictionary;
import it.cavallium.dbengine.database.collections.FixedLengthSerializer;
2021-01-31 21:23:43 +01:00
import it.cavallium.dbengine.database.collections.Serializer;
2021-01-31 19:52:47 +01:00
import it.cavallium.dbengine.database.collections.SubStageGetterSingleBytes;
import it.cavallium.dbengine.database.disk.LLLocalDatabaseConnection;
import java.nio.file.Path;
2021-01-31 19:52:47 +01:00
import java.text.DecimalFormat;
2021-01-31 15:47:48 +01:00
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
2021-01-31 19:52:47 +01:00
import java.util.Locale;
import java.util.function.Function;
import reactor.core.publisher.Flux;
2021-01-31 15:47:48 +01:00
import reactor.core.publisher.Mono;
import reactor.core.publisher.Sinks;
import reactor.core.publisher.Sinks.One;
2021-01-31 19:52:47 +01:00
import reactor.core.scheduler.Schedulers;
import reactor.util.function.Tuples;
public class Example {
2021-01-31 19:52:47 +01:00
private static final boolean printPreviousValue = false;
private static final int numRepeats = 500;
private static final int batchSize = 1000;
2021-01-31 19:52:47 +01:00
public static void main(String[] args) throws InterruptedException {
2021-01-31 19:52:47 +01:00
testAtPut();
testPutValueAndGetPrevious();
2021-01-31 21:23:43 +01:00
testPutValue();
testAtPut()
.then(rangeTestAtPut())
.then(testPutValue())
.then(rangeTestPutValue())
.then(testPutMulti())
.then(rangeTestPutMulti())
2021-01-31 19:52:47 +01:00
.subscribeOn(Schedulers.parallel())
.blockOptional();
}
private static Mono<Void> testAtPut() {
var ssg = new SubStageGetterSingleBytes();
2021-01-31 15:47:48 +01:00
var ser = FixedLengthSerializer.noop(4);
2021-01-31 19:52:47 +01:00
var itemKey = new byte[]{0, 1, 2, 3};
var newValue = new byte[]{4, 5, 6, 7};
2021-01-31 15:47:48 +01:00
var itemKeyBuffer = Unpooled.wrappedBuffer(itemKey);
return test("MapDictionaryDeep::at::put (same key, same value, " + batchSize + " times)",
2021-01-31 19:52:47 +01:00
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
2021-01-31 21:23:43 +01:00
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionaryDeep.simple(dict, ssg, ser))),
tuple -> Flux.range(0, batchSize).flatMap(n -> Mono
2021-01-31 15:59:21 +01:00
.defer(() -> Mono
2021-01-31 19:52:47 +01:00
.fromRunnable(() -> {
if (printPreviousValue)
System.out.println("Setting new value at key " + Arrays.toString(itemKey) + ": " + Arrays.toString(newValue));
})
.then(tuple.getT2().at(null, itemKeyBuffer))
2021-01-31 15:59:21 +01:00
.flatMap(handle -> handle.setAndGetPrevious(newValue))
2021-01-31 19:52:47 +01:00
.doOnSuccess(oldValue -> {
if (printPreviousValue)
System.out.println("Old value: " + (oldValue == null ? "None" : Arrays.toString(oldValue)));
2021-01-31 15:59:21 +01:00
})
))
.then(),
2021-01-31 21:23:43 +01:00
numRepeats,
2021-01-31 19:52:47 +01:00
tuple -> tuple.getT1().close());
}
private static Mono<Void> testPutValueAndGetPrevious() {
var ssg = new SubStageGetterSingleBytes();
var ser = FixedLengthSerializer.noop(4);
var itemKey = new byte[]{0, 1, 2, 3};
var newValue = new byte[]{4, 5, 6, 7};
var itemKeyBuffer = Unpooled.wrappedBuffer(itemKey);
return test("MapDictionaryDeep::putValueAndGetPrevious (same key, same value, " + batchSize + " times)",
2021-01-31 19:52:47 +01:00
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
2021-01-31 21:23:43 +01:00
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionaryDeep.simple(dict, ssg, ser))),
tuple -> Flux.range(0, batchSize).flatMap(n -> Mono
2021-01-31 19:52:47 +01:00
.defer(() -> Mono
.fromRunnable(() -> {
if (printPreviousValue)
System.out.println("Setting new value at key " + Arrays.toString(itemKey) + ": " + Arrays.toString(newValue));
})
.then(tuple.getT2().putValueAndGetPrevious(itemKeyBuffer, newValue))
.doOnSuccess(oldValue -> {
if (printPreviousValue)
System.out.println("Old value: " + (oldValue == null ? "None" : Arrays.toString(oldValue)));
})
))
.then(),
2021-01-31 21:23:43 +01:00
numRepeats,
2021-01-31 19:52:47 +01:00
tuple -> tuple.getT1().close());
}
private static Mono<Void> testPutValue() {
var ssg = new SubStageGetterSingleBytes();
var ser = FixedLengthSerializer.noop(4);
var itemKey = new byte[]{0, 1, 2, 3};
var newValue = new byte[]{4, 5, 6, 7};
var itemKeyBuffer = Unpooled.wrappedBuffer(itemKey);
return test("MapDictionaryDeep::putValue (same key, same value, " + batchSize + " times)",
2021-01-31 19:52:47 +01:00
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
2021-01-31 21:23:43 +01:00
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionaryDeep.simple(dict, ssg, ser))),
tuple -> Flux.range(0, batchSize).flatMap(n -> Mono
2021-01-31 19:52:47 +01:00
.defer(() -> Mono
.fromRunnable(() -> {
if (printPreviousValue)
System.out.println("Setting new value at key " + Arrays.toString(itemKey) + ": " + Arrays.toString(newValue));
})
.then(tuple.getT2().putValue(itemKeyBuffer, newValue))
))
.then(),
numRepeats,
tuple -> tuple.getT1().close());
}
private static Mono<Void> testPutMulti() {
var ssg = new SubStageGetterSingleBytes();
var ser = FixedLengthSerializer.noop(4);
int batchSize = 1000;
HashMap<ByteBuf, byte[]> keysToPut = new HashMap<>();
for (int i = 0; i < 1000; i++) {
keysToPut.put(Unpooled.wrappedBuffer(Ints.toByteArray(i * 3)), Ints.toByteArray(i * 11));
}
var putMultiFlux = Flux.fromIterable(keysToPut.entrySet());
return test("MapDictionaryDeep::putMulti (batch of " + batchSize + " entries)",
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionaryDeep.simple(dict, ssg, ser))),
tuple -> Mono
.defer(() -> tuple.getT2().putMulti(putMultiFlux)
2021-01-31 19:52:47 +01:00
),
2021-01-31 21:23:43 +01:00
numRepeats,
tuple -> tuple.getT1().close());
}
private static Mono<Void> rangeTestAtPut() {
var ser = FixedLengthSerializer.noop(4);
var vser = Serializer.noopBytes();
var itemKey = new byte[]{0, 1, 2, 3};
var newValue = new byte[]{4, 5, 6, 7};
var itemKeyBuffer = Unpooled.wrappedBuffer(itemKey);
return test("MapDictionary::at::put (same key, same value, " + batchSize + " times)",
2021-01-31 21:23:43 +01:00
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionary.simple(dict, ser, vser))),
tuple -> Flux.range(0, batchSize).flatMap(n -> Mono
2021-01-31 21:23:43 +01:00
.defer(() -> Mono
.fromRunnable(() -> {
if (printPreviousValue)
System.out.println("Setting new value at key " + Arrays.toString(itemKey) + ": " + Arrays.toString(newValue));
})
.then(tuple.getT2().at(null, itemKeyBuffer))
.flatMap(handle -> handle.setAndGetPrevious(newValue))
.doOnSuccess(oldValue -> {
if (printPreviousValue)
System.out.println("Old value: " + (oldValue == null ? "None" : Arrays.toString(oldValue)));
})
))
.then(),
2021-01-31 21:23:43 +01:00
numRepeats,
tuple -> tuple.getT1().close());
}
private static Mono<Void> rangeTestPutValueAndGetPrevious() {
var ser = FixedLengthSerializer.noop(4);
var vser = Serializer.noopBytes();
var itemKey = new byte[]{0, 1, 2, 3};
var newValue = new byte[]{4, 5, 6, 7};
var itemKeyBuffer = Unpooled.wrappedBuffer(itemKey);
return test("MapDictionary::putValueAndGetPrevious (same key, same value, " + batchSize + " times)",
2021-01-31 21:23:43 +01:00
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionary.simple(dict, ser, vser))),
tuple -> Flux.range(0, batchSize).flatMap(n -> Mono
2021-01-31 21:23:43 +01:00
.defer(() -> Mono
.fromRunnable(() -> {
if (printPreviousValue)
System.out.println("Setting new value at key " + Arrays.toString(itemKey) + ": " + Arrays.toString(newValue));
})
.then(tuple.getT2().putValueAndGetPrevious(itemKeyBuffer, newValue))
.doOnSuccess(oldValue -> {
if (printPreviousValue)
System.out.println("Old value: " + (oldValue == null ? "None" : Arrays.toString(oldValue)));
})
))
.then(),
2021-01-31 21:23:43 +01:00
numRepeats,
tuple -> tuple.getT1().close());
}
private static Mono<Void> rangeTestPutValue() {
var ser = FixedLengthSerializer.noop(4);
var vser = Serializer.noopBytes();
var itemKey = new byte[]{0, 1, 2, 3};
var newValue = new byte[]{4, 5, 6, 7};
var itemKeyBuffer = Unpooled.wrappedBuffer(itemKey);
return test("MapDictionary::putValue (same key, same value, " + batchSize + " times)",
2021-01-31 21:23:43 +01:00
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionary.simple(dict, ser, vser))),
tuple -> Flux.range(0, batchSize).flatMap(n -> Mono
2021-01-31 21:23:43 +01:00
.defer(() -> Mono
.fromRunnable(() -> {
if (printPreviousValue)
System.out.println("Setting new value at key " + Arrays.toString(itemKey) + ": " + Arrays.toString(newValue));
})
.then(tuple.getT2().putValue(itemKeyBuffer, newValue))
))
.then(),
numRepeats,
tuple -> tuple.getT1().close());
}
private static Mono<Void> rangeTestPutMulti() {
var ser = FixedLengthSerializer.noop(4);
var vser = Serializer.noopBytes();
HashMap<ByteBuf, byte[]> keysToPut = new HashMap<>();
for (int i = 0; i < batchSize; i++) {
keysToPut.put(Unpooled.wrappedBuffer(Ints.toByteArray(i * 3)), Ints.toByteArray(i * 11));
}
var putMultiFlux = Flux.fromIterable(keysToPut.entrySet());
return test("MapDictionary::putMulti (batch of " + batchSize + " entries)",
tempDb()
.flatMap(db -> db.getDictionary("testmap").map(dict -> Tuples.of(db, dict)))
.map(tuple -> tuple.mapT2(dict -> DatabaseMapDictionary.simple(dict, ser, vser))),
tuple -> Mono
.defer(() -> tuple.getT2().putMulti(putMultiFlux)
2021-01-31 21:23:43 +01:00
),
numRepeats,
2021-01-31 19:52:47 +01:00
tuple -> tuple.getT1().close());
}
private static <U> Mono<? extends LLKeyValueDatabase> tempDb() {
return new LLLocalDatabaseConnection(Path.of("/tmp/"), true)
.connect()
.flatMap(conn -> conn.getDatabase("testdb", List.of(Column.dictionary("testmap")), false));
}
public static <A, B, C> Mono<Void> test(String name, Mono<A> setup, Function<A, Mono<B>> test, long numRepeats, Function<A, Mono<C>> close) {
One<Instant> instantInit = Sinks.one();
One<Instant> instantInitTest = Sinks.one();
One<Instant> instantEndTest = Sinks.one();
One<Instant> instantEnd = Sinks.one();
Duration WAIT_TIME = Duration.ofSeconds(5);
Duration WAIT_TIME_END = Duration.ofSeconds(5);
2021-01-31 19:52:47 +01:00
return Mono
.fromRunnable(() -> instantInit.tryEmitValue(now()))
.then(setup)
.delayElement(WAIT_TIME)
2021-01-31 19:52:47 +01:00
.doOnSuccess(s -> instantInitTest.tryEmitValue(now()))
.flatMap(a ->Mono.defer(() -> test.apply(a)).repeat(numRepeats)
2021-01-31 19:52:47 +01:00
.then()
.doOnSuccess(s -> instantEndTest.tryEmitValue(now()))
.delayElement(WAIT_TIME_END)
2021-01-31 19:52:47 +01:00
.then(close.apply(a)))
.doOnSuccess(s -> instantEnd.tryEmitValue(now()))
.then(Mono.zip(instantInit.asMono(), instantInitTest.asMono(), instantEndTest.asMono(), instantEnd.asMono()))
.doOnSuccess(tuple -> {
System.out.println("----------------------------------------------------------------------");
System.out.println(name);
System.out.println(
"\t - Executed " + DecimalFormat.getInstance(Locale.ITALY).format(numRepeats) + " times:");
System.out.println("\t - Test time: " + DecimalFormat
.getInstance(Locale.ITALY)
.format(Duration.between(tuple.getT2(), tuple.getT3()).toNanos() / (double) numRepeats / (double) 1000000)
+ "ms");
System.out.println("\t - Test speed: " + DecimalFormat
.getInstance(Locale.ITALY)
.format(numRepeats / (Duration.between(tuple.getT2(), tuple.getT3()).toNanos() / (double) 1000000 / (double) 1000))
+ " tests/s");
System.out.println("\t - Total time: " + DecimalFormat
.getInstance(Locale.ITALY)
.format(Duration.between(tuple.getT2(), tuple.getT3()).toNanos() / (double) 1000000) + "ms");
System.out.println("\t - Total time (setup+test+end): " + DecimalFormat
.getInstance(Locale.ITALY)
.format(Duration.between(tuple.getT1(), tuple.getT4().minus(WAIT_TIME)).toNanos() / (double) 1000000) + "ms");
2021-01-31 19:52:47 +01:00
System.out.println("----------------------------------------------------------------------");
})
.then();
}
public static Instant now() {
return Instant.ofEpochSecond(0, System.nanoTime());
}
}