Improve performance

This commit is contained in:
Andrea Cavalli 2022-03-12 02:55:18 +01:00
parent 9b5071c45e
commit a4df72fe46
5 changed files with 68 additions and 13 deletions

View File

@ -6,6 +6,7 @@ import io.net5.buffer.api.Drop;
import io.net5.buffer.api.Owned; import io.net5.buffer.api.Owned;
import io.net5.buffer.api.Resource; import io.net5.buffer.api.Resource;
import io.net5.buffer.api.Send; import io.net5.buffer.api.Send;
import io.net5.buffer.api.internal.ResourceSupport;
import it.cavallium.dbengine.client.BadBlock; import it.cavallium.dbengine.client.BadBlock;
import it.cavallium.dbengine.client.CompositeSnapshot; import it.cavallium.dbengine.client.CompositeSnapshot;
import it.cavallium.dbengine.database.LLDictionary; import it.cavallium.dbengine.database.LLDictionary;
@ -13,13 +14,14 @@ import it.cavallium.dbengine.database.LLDictionaryResultType;
import it.cavallium.dbengine.database.LLRange; import it.cavallium.dbengine.database.LLRange;
import it.cavallium.dbengine.database.LLSnapshot; import it.cavallium.dbengine.database.LLSnapshot;
import it.cavallium.dbengine.database.LLUtils; import it.cavallium.dbengine.database.LLUtils;
import io.net5.buffer.api.internal.ResourceSupport;
import it.cavallium.dbengine.database.UpdateMode; import it.cavallium.dbengine.database.UpdateMode;
import it.cavallium.dbengine.database.serialization.SerializationException; import it.cavallium.dbengine.database.serialization.SerializationException;
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength; import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap; import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.lang3.function.TriFunction;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -73,6 +75,7 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
protected final LLDictionary dictionary; protected final LLDictionary dictionary;
private final BufferAllocator alloc; private final BufferAllocator alloc;
private final AtomicLong totalZeroBytesErrors = new AtomicLong();
protected final SubStageGetter<U, US> subStageGetter; protected final SubStageGetter<U, US> subStageGetter;
protected final SerializerFixedBinaryLength<T> keySuffixSerializer; protected final SerializerFixedBinaryLength<T> keySuffixSerializer;
protected final int keyPrefixLength; protected final int keyPrefixLength;
@ -437,4 +440,50 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
this.range = null; this.range = null;
this.onClose = null; this.onClose = null;
} }
public static <K1, K2, V, R> Flux<R> getAllLeaves2(DatabaseMapDictionaryDeep<K1, Object2ObjectSortedMap<K2, V>, DatabaseMapDictionary<K2, V>> deepMap,
CompositeSnapshot snapshot,
TriFunction<K1, K2, V, R> merger) {
if (deepMap.subStageGetter instanceof SubStageGetterMap<K2, V> subStageGetterMap) {
var keySuffix1Serializer = deepMap.keySuffixSerializer;
var keySuffix2Serializer = subStageGetterMap.keySerializer;
var valueSerializer = subStageGetterMap.valueSerializer;
return deepMap
.dictionary
.getRange(deepMap.resolveSnapshot(snapshot), deepMap.rangeMono)
.handle((entrySend, sink) -> {
try (var entry = entrySend.receive()) {
var keyBuf = entry.getKeyUnsafe();
var valueBuf = entry.getValueUnsafe();
assert keyBuf != null;
keyBuf.skipReadable(deepMap.keyPrefixLength);
K1 key1;
K2 key2;
try (var key1Buf = keyBuf.split(deepMap.keySuffixLength)) {
key1 = keySuffix1Serializer.deserialize(key1Buf);
}
key2 = keySuffix2Serializer.deserialize(keyBuf);
assert valueBuf != null;
var value = valueSerializer.deserialize(valueBuf);
sink.next(merger.apply(key1, key2, value));
} catch (IndexOutOfBoundsException ex) {
var exMessage = ex.getMessage();
if (exMessage != null && exMessage.contains("read 0 to 0, write 0 to ")) {
var totalZeroBytesErrors = deepMap.totalZeroBytesErrors.incrementAndGet();
if (totalZeroBytesErrors < 512 || totalZeroBytesErrors % 10000 == 0) {
LOG.error("Unexpected zero-bytes value in column " + deepMap.dictionary.getDatabaseName() + ":"
+ deepMap.dictionary.getColumnName() + " total=" + totalZeroBytesErrors);
}
sink.complete();
} else {
sink.error(ex);
}
} catch (SerializationException ex) {
sink.error(ex);
}
});
} else {
throw new IllegalArgumentException();
}
}
} }

View File

@ -16,8 +16,8 @@ import reactor.core.publisher.Mono;
public class SubStageGetterMap<T, U> implements public class SubStageGetterMap<T, U> implements
SubStageGetter<Object2ObjectSortedMap<T, U>, DatabaseMapDictionary<T, U>> { SubStageGetter<Object2ObjectSortedMap<T, U>, DatabaseMapDictionary<T, U>> {
private final SerializerFixedBinaryLength<T> keySerializer; final SerializerFixedBinaryLength<T> keySerializer;
private final Serializer<U> valueSerializer; final Serializer<U> valueSerializer;
public SubStageGetterMap(SerializerFixedBinaryLength<T> keySerializer, public SubStageGetterMap(SerializerFixedBinaryLength<T> keySerializer,
Serializer<U> valueSerializer) { Serializer<U> valueSerializer) {

View File

@ -137,7 +137,7 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
} }
} }
var optionsWithCache = openRocksDb(path, databaseOptions); OptionsWithCache optionsWithCache = openRocksDb(path, databaseOptions);
var rocksdbOptions = optionsWithCache.options(); var rocksdbOptions = optionsWithCache.options();
try { try {
List<ColumnFamilyDescriptor> descriptors = new LinkedList<>(); List<ColumnFamilyDescriptor> descriptors = new LinkedList<>();
@ -175,7 +175,6 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
tableOptions tableOptions
.setIndexType(IndexType.kTwoLevelIndexSearch) .setIndexType(IndexType.kTwoLevelIndexSearch)
.setPartitionFilters(true) .setPartitionFilters(true)
.setBlockCache(optionsWithCache.cache())
.setCacheIndexAndFilterBlocks(databaseOptions.setCacheIndexAndFilterBlocks().orElse(true)) .setCacheIndexAndFilterBlocks(databaseOptions.setCacheIndexAndFilterBlocks().orElse(true))
.setCacheIndexAndFilterBlocksWithHighPriority(true) .setCacheIndexAndFilterBlocksWithHighPriority(true)
.setPinTopLevelIndexAndFilter(true) .setPinTopLevelIndexAndFilter(true)
@ -185,7 +184,6 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
tableOptions tableOptions
.setIndexType(IndexType.kTwoLevelIndexSearch) .setIndexType(IndexType.kTwoLevelIndexSearch)
.setPartitionFilters(true) .setPartitionFilters(true)
.setBlockCache(optionsWithCache.cache())
.setCacheIndexAndFilterBlocks(databaseOptions.setCacheIndexAndFilterBlocks().orElse( true)) .setCacheIndexAndFilterBlocks(databaseOptions.setCacheIndexAndFilterBlocks().orElse( true))
.setCacheIndexAndFilterBlocksWithHighPriority(true) .setCacheIndexAndFilterBlocksWithHighPriority(true)
.setPinTopLevelIndexAndFilter(true) .setPinTopLevelIndexAndFilter(true)
@ -195,7 +193,10 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
tableOptions.setFilterPolicy(bloomFilter); tableOptions.setFilterPolicy(bloomFilter);
tableOptions.setOptimizeFiltersForMemory(true); tableOptions.setOptimizeFiltersForMemory(true);
} }
tableOptions.setBlockSize(16 * 1024); // 16KiB tableOptions
.setBlockCacheCompressed(optionsWithCache.compressedCache())
.setBlockCache(optionsWithCache.standardCache())
.setBlockSize(16 * 1024); // 16KiB
columnOptions.setTableFormatConfig(tableOptions); columnOptions.setTableFormatConfig(tableOptions);
columnOptions.setCompactionPriority(CompactionPriority.MinOverlappingRatio); columnOptions.setCompactionPriority(CompactionPriority.MinOverlappingRatio);
@ -391,7 +392,7 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
// end force compact // end force compact
} }
record OptionsWithCache(DBOptions options, Cache cache) {} record OptionsWithCache(DBOptions options, Cache standardCache, Cache compressedCache) {}
private static OptionsWithCache openRocksDb(@Nullable Path path, DatabaseOptions databaseOptions) throws IOException { private static OptionsWithCache openRocksDb(@Nullable Path path, DatabaseOptions databaseOptions) throws IOException {
// Get databases directory path // Get databases directory path
@ -409,6 +410,7 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
// the Options class contains a set of configurable DB options // the Options class contains a set of configurable DB options
// that determines the behaviour of the database. // that determines the behaviour of the database.
var options = new DBOptions(); var options = new DBOptions();
options.setParanoidChecks(false);
options.setCreateIfMissing(true); options.setCreateIfMissing(true);
options.setCreateMissingColumnFamilies(true); options.setCreateMissingColumnFamilies(true);
options.setInfoLogLevel(InfoLogLevel.ERROR_LEVEL); options.setInfoLogLevel(InfoLogLevel.ERROR_LEVEL);
@ -427,6 +429,7 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
options.setMaxOpenFiles(databaseOptions.maxOpenFiles().orElse(-1)); options.setMaxOpenFiles(databaseOptions.maxOpenFiles().orElse(-1));
Cache blockCache; Cache blockCache;
Cache compressedCache;
if (databaseOptions.lowMemory()) { if (databaseOptions.lowMemory()) {
// LOW MEMORY // LOW MEMORY
options options
@ -438,7 +441,8 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
.setWalSizeLimitMB(0) // 16MB .setWalSizeLimitMB(0) // 16MB
.setMaxTotalWalSize(0) // automatic .setMaxTotalWalSize(0) // automatic
; ;
blockCache = new ClockCache(databaseOptions.blockCache().orElse( 8L * SizeUnit.MB), -1, true); blockCache = new ClockCache(databaseOptions.blockCache().orElse( 8L * SizeUnit.MB) / 2, -1, true);
compressedCache = new ClockCache(databaseOptions.blockCache().orElse( 8L * SizeUnit.MB) / 2, -1, true);
if (databaseOptions.useDirectIO()) { if (databaseOptions.useDirectIO()) {
options options
@ -460,7 +464,8 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
.setWalSizeLimitMB(1024) // 1024MB .setWalSizeLimitMB(1024) // 1024MB
.setMaxTotalWalSize(2L * SizeUnit.GB) // 2GiB max wal directory size .setMaxTotalWalSize(2L * SizeUnit.GB) // 2GiB max wal directory size
; ;
blockCache = new ClockCache(databaseOptions.blockCache().orElse( 512 * SizeUnit.MB), -1, true); blockCache = new ClockCache(databaseOptions.blockCache().orElse( 512 * SizeUnit.MB) / 2);
compressedCache = new ClockCache(databaseOptions.blockCache().orElse( 512 * SizeUnit.MB) / 2);
if (databaseOptions.useDirectIO()) { if (databaseOptions.useDirectIO()) {
options options
@ -491,7 +496,7 @@ public class LLLocalKeyValueDatabase implements LLKeyValueDatabase {
options.setUseDirectIoForFlushAndCompaction(true); options.setUseDirectIoForFlushAndCompaction(true);
} }
return new OptionsWithCache(options, blockCache); return new OptionsWithCache(options, blockCache, compressedCache);
} }
private static List<DbPath> convertPaths(Path databasesDirPath, Path path, List<DatabaseVolume> volumes) { private static List<DbPath> convertPaths(Path databasesDirPath, Path path, List<DatabaseVolume> volumes) {

View File

@ -79,8 +79,8 @@ public abstract class LLLocalReactiveRocksIterator<T> extends
return Flux.generate(() -> { return Flux.generate(() -> {
var readOptions = new ReadOptions(this.readOptions); var readOptions = new ReadOptions(this.readOptions);
if (!rangeShared.hasMin() || !rangeShared.hasMax()) { if (!rangeShared.hasMin() || !rangeShared.hasMax()) {
readOptions.setReadaheadSize(32 * 1024); // 32KiB //readOptions.setReadaheadSize(32 * 1024); // 32KiB
readOptions.setFillCache(false); //readOptions.setFillCache(false);
readOptions.setVerifyChecksums(false); readOptions.setVerifyChecksums(false);
} }
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {

View File

@ -130,6 +130,7 @@ public class RocksdbFileStore {
private static DBOptions getDBOptions() { private static DBOptions getDBOptions() {
var options = new DBOptions(); var options = new DBOptions();
options.setParanoidChecks(false);
options.setWalSizeLimitMB(256); options.setWalSizeLimitMB(256);
options.setMaxWriteBatchGroupSizeBytes(2 * SizeUnit.MB); options.setMaxWriteBatchGroupSizeBytes(2 * SizeUnit.MB);
//options.setAtomicFlush(false); //options.setAtomicFlush(false);