Optimize memory footprint for SlicedMapImpl in case it's empty

It might be useful in case of many delegating traces that
remain effectively empty themselves (up to 7M of empty maps in case of compilation of 'idea' module)
This commit is contained in:
Denis Zharkov
2018-08-06 16:08:24 +07:00
parent 8050869e45
commit 3a8335d47f
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Key;
import com.intellij.util.keyFMap.KeyFMap; import com.intellij.util.keyFMap.KeyFMap;
import kotlin.jvm.functions.Function3; import kotlin.jvm.functions.Function3;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -31,7 +32,8 @@ import java.util.Map;
public class SlicedMapImpl implements MutableSlicedMap { public class SlicedMapImpl implements MutableSlicedMap {
private final boolean alwaysAllowRewrite; private final boolean alwaysAllowRewrite;
private final Map<Object, KeyFMap> map = new OpenAddressLinearProbingHashTable<>(); @Nullable
private Map<Object, KeyFMap> map = null;
private Multimap<WritableSlice<?, ?>, Object> collectiveSliceKeys = null; private Multimap<WritableSlice<?, ?>, Object> collectiveSliceKeys = null;
public SlicedMapImpl(boolean alwaysAllowRewrite) { public SlicedMapImpl(boolean alwaysAllowRewrite) {
@@ -44,6 +46,10 @@ public class SlicedMapImpl implements MutableSlicedMap {
return; return;
} }
if (map == null) {
map = new OpenAddressLinearProbingHashTable<>();
}
KeyFMap holder = map.get(key); KeyFMap holder = map.get(key);
if (holder == null) { if (holder == null) {
holder = KeyFMap.EMPTY_MAP; holder = KeyFMap.EMPTY_MAP;
@@ -76,13 +82,13 @@ public class SlicedMapImpl implements MutableSlicedMap {
@Override @Override
public void clear() { public void clear() {
map.clear(); map = null;
collectiveSliceKeys = null; collectiveSliceKeys = null;
} }
@Override @Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) { public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
KeyFMap holder = map.get(key); KeyFMap holder = map != null ? map.get(key) : null;
V value = holder == null ? null : holder.get(slice.getKey()); V value = holder == null ? null : holder.get(slice.getKey());
@@ -100,6 +106,7 @@ public class SlicedMapImpl implements MutableSlicedMap {
@Override @Override
public void forEach(@NotNull Function3<WritableSlice, Object, Object, Void> f) { public void forEach(@NotNull Function3<WritableSlice, Object, Object, Void> f) {
if (map == null) return;
map.forEach((key, holder) -> { map.forEach((key, holder) -> {
if (holder == null) return; if (holder == null) return;
@@ -114,6 +121,8 @@ public class SlicedMapImpl implements MutableSlicedMap {
@NotNull @NotNull
@Override @Override
public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) { public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
if (map == null) return ImmutableMap.of();
ImmutableMap.Builder<K, V> builder = ImmutableMap.builder(); ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
map.forEach((key, holder) -> { map.forEach((key, holder) -> {