From 25c8f1df780fcdf9b60c1f75c9a7e091eb1f56ee Mon Sep 17 00:00:00 2001 From: Sergei Galiamichev Date: Tue, 26 Mar 2024 13:53:50 +0100 Subject: [PATCH] Replace TreeMap with EntityIdMap to reduce comparisons count --- .../repository/test/inmemory/EntityIdMap.java | 70 +++++++++++++++++++ .../test/inmemory/InMemoryDataShard.java | 15 ++-- 2 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/EntityIdMap.java diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/EntityIdMap.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/EntityIdMap.java new file mode 100644 index 00000000..58e58def --- /dev/null +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/EntityIdMap.java @@ -0,0 +1,70 @@ +package tech.ydb.yoj.repository.test.inmemory; + +import tech.ydb.yoj.repository.db.Entity; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * TreeMap - is very expensive due to very complicated comparison login + */ +class EntityIdMap, E> extends AbstractMap, E> { + private final Comparator> comparator; + private Map, E> entries = new LinkedHashMap<>(); // probably not the best here but very simple + + public EntityIdMap(Comparator> comparator) { + this.comparator = comparator; + } + + public EntityIdMap(EntityIdMap entityLines) { + this(entityLines.comparator); + entries = new LinkedHashMap<>(entityLines); + } + + @Override + public Set, E>> entrySet() { + return entries.entrySet(); + } + + @Override + public E get(Object key) { + return entries.get(key); + } + + @Override + public E put(Entity.Id key, E value) { + List> temp = new ArrayList<>(entries.keySet()); + int index = Collections.binarySearch(temp, key, comparator); + Map, E> result = new LinkedHashMap<>(); + E oldValue = null; + int i = 0; + for (Entry, E> entry : entries.entrySet()) { + if (index < 0 && -index - 1 == i) { + result.put(key, value); + result.put(entry.getKey(), entry.getValue()); + } else if (index == i) { + oldValue = entry.getValue(); + result.put(key, value); + } else { + result.put(entry.getKey(), entry.getValue()); + } + i++; + } + if (-index - 1 == result.size()) { + result.put(key, value); // add last (item i.e first item or item with max value to existing list) + } + entries = result; + return oldValue; + } + + @Override + public E remove(Object key) { + return entries.remove(key); + } +} diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java index 2b394160..f693a2da 100644 --- a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java @@ -16,16 +16,15 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TreeMap; final class InMemoryDataShard> { private final Class type; private final EntitySchema schema; - private final TreeMap, InMemoryEntityLine> entityLines; + private final Map, InMemoryEntityLine> entityLines; private final Map>> uncommited = new HashMap<>(); private InMemoryDataShard( - Class type, EntitySchema schema, TreeMap, InMemoryEntityLine> entityLines + Class type, EntitySchema schema, Map, InMemoryEntityLine> entityLines ) { this.type = type; this.schema = schema; @@ -36,15 +35,13 @@ public InMemoryDataShard(Class type) { this(type, EntitySchema.of(type), createEmptyLines(type)); } - private static > TreeMap, InMemoryEntityLine> createEmptyLines(Class type) { - return new TreeMap<>(EntityIdSchema.getIdComparator(type)); + private static > Map, InMemoryEntityLine> createEmptyLines(Class type) { + return new EntityIdMap<>(EntityIdSchema.getIdComparator(type)); } public synchronized InMemoryDataShard createSnapshot() { - TreeMap, InMemoryEntityLine> snapshotLines = createEmptyLines(type); - for (Map.Entry, InMemoryEntityLine> entry : entityLines.entrySet()) { - snapshotLines.put(entry.getKey(), entry.getValue().createSnapshot()); - } + Map, InMemoryEntityLine> snapshotLines = new EntityIdMap<>((EntityIdMap)entityLines); + snapshotLines.replaceAll((k, v) -> v.createSnapshot()); return new InMemoryDataShard<>(type, schema, snapshotLines); }