From 2308f08ae30e8bcf83c4ed69bf7b830cfcc9cd5e Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Sun, 13 Apr 2025 03:23:40 +0200 Subject: [PATCH] make StringCanonizingOpenHashMap faster --- .../util/map/StringCanonizingOpenHashMap.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/map/StringCanonizingOpenHashMap.java b/leaf-server/src/main/java/org/dreeam/leaf/util/map/StringCanonizingOpenHashMap.java index e55c07c9..45f1336c 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/map/StringCanonizingOpenHashMap.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/map/StringCanonizingOpenHashMap.java @@ -11,21 +11,31 @@ import java.util.function.Function; public class StringCanonizingOpenHashMap extends Object2ObjectOpenHashMap { private static final Interner KEY_INTERNER = Interners.newWeakInterner(); + private final float loadFactor; private static String intern(String key) { - return key != null ? KEY_INTERNER.intern(key) : null; + if (key == null) return null; + String jvmInterned = key.intern(); + if (jvmInterned == key) { + return key; + } + + return KEY_INTERNER.intern(key); } public StringCanonizingOpenHashMap() { super(); + this.loadFactor = 0.8f; } public StringCanonizingOpenHashMap(int expectedSize) { super(expectedSize); + this.loadFactor = 0.8f; } public StringCanonizingOpenHashMap(int expectedSize, float loadFactor) { super(expectedSize, loadFactor); + this.loadFactor = loadFactor; } @Override @@ -36,9 +46,16 @@ public class StringCanonizingOpenHashMap extends Object2ObjectOpenHashMap m) { if (m.isEmpty()) return; - Map tmp = new Object2ObjectOpenHashMap<>(m.size()); - m.forEach((k, v) -> tmp.put(intern(k), v)); - super.putAll(tmp); + + // Fast path for maps that already have interned keys + if (m instanceof StringCanonizingOpenHashMap) { + super.putAll(m); + return; + } + // Process each entry directly rather than creating a temporary map + for (Map.Entry entry : m.entrySet()) { + put(entry.getKey(), entry.getValue()); + } } private void putWithoutInterning(String key, T value) { @@ -46,11 +63,17 @@ public class StringCanonizingOpenHashMap extends Object2ObjectOpenHashMap StringCanonizingOpenHashMap deepCopy(StringCanonizingOpenHashMap incomingMap, Function deepCopier) { - StringCanonizingOpenHashMap newMap = new StringCanonizingOpenHashMap<>(incomingMap.size(), 0.8f); + int size = incomingMap.size(); + if (size == 0) { + return new StringCanonizingOpenHashMap<>(0, incomingMap.loadFactor); + } + // Pre-allocate + StringCanonizingOpenHashMap newMap = new StringCanonizingOpenHashMap<>(size, incomingMap.loadFactor); ObjectIterator> iterator = incomingMap.object2ObjectEntrySet().fastIterator(); while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); + Entry entry = iterator.next(); + // Keys are already interned, so we can add them directly newMap.putWithoutInterning(entry.getKey(), deepCopier.apply(entry.getValue())); }