From 43797e87222af6ddbf61f4db779af4a866eac3c2 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 26 Apr 2012 18:18:06 +0400 Subject: [PATCH] use less memory along indexing path --- .../ChangeTrackingValueContainer.java | 2 +- .../util/indexing/MapReduceIndex.java | 26 +++++++++++++++++-- .../util/indexing/ValueContainerImpl.java | 23 +++++++++------- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java index 9dee34b26342..f41bc79ec6e3 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java @@ -42,7 +42,7 @@ class ChangeTrackingValueContainer extends UpdatableValueContainer myInitializer = initializer; myAdded = new ValueContainerImpl(); myRemoved = new ValueContainerImpl(); - myInvalidated = new TIntHashSet(); + myInvalidated = new TIntHashSet(1); } //public void log(String op, int id, final Value value) { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java index 7a4acf603be5..09417152e757 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java @@ -18,10 +18,13 @@ package com.intellij.util.indexing; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.io.PersistentHashMap; +import gnu.trove.THashMap; +import gnu.trove.TObjectObjectProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -232,8 +235,27 @@ public class MapReduceIndex implements UpdatableIndex entry : newData.entrySet()) { - myStorage.addValue(entry.getKey(), inputId, entry.getValue()); + if (newData instanceof THashMap) { + // such map often (from IdIndex) contain 100x (avg ~240) of entries, also THashMap have no Entry inside so we optimize for gc too + final Ref exceptionRef = new Ref(); + final boolean b = ((THashMap)newData).forEachEntry(new TObjectObjectProcedure() { + @Override + public boolean execute(Key key, Value value) { + try { + myStorage.addValue(key, inputId, value); + } + catch (StorageException ex) { + exceptionRef.set(ex); + return false; + } + return true; + } + }); + if (!b) throw exceptionRef.get(); + } else { + for (Map.Entry entry : newData.entrySet()) { + myStorage.addValue(entry.getKey(), inputId, entry.getValue()); + } } if (myInputsIndex != null) { try { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java index 0f1c63ff9b01..de4ccb0b6cd1 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -17,6 +17,7 @@ package com.intellij.util.indexing; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.util.SmartList; import com.intellij.util.containers.EmptyIterator; import gnu.trove.THashMap; import gnu.trove.TIntHashSet; @@ -31,10 +32,12 @@ import java.util.*; */ class ValueContainerImpl extends UpdatableValueContainer implements Cloneable{ private static final Logger LOG = Logger.getInstance("#com.intellij.util.indexing.ValueContainerImpl"); + private final static Object myNullValue = new Object(); private THashMap myInputIdMapping; public ValueContainerImpl() { - myInputIdMapping = new THashMap(); + // per statistic most maps (80%) has one value + myInputIdMapping = new THashMap(1); } @Override @@ -66,16 +69,20 @@ class ValueContainerImpl extends UpdatableValueContainer implement @Override public void removeAssociatedValue(int inputId) { - final List toRemove = new ArrayList(1); + if (myInputIdMapping.isEmpty()) return; + List toRemove = null; for (final Iterator valueIterator = getValueIterator(); valueIterator.hasNext();) { final Value value = valueIterator.next(); if (isAssociated(value, inputId)) { - LOG.assertTrue(toRemove.isEmpty(), "Expected only one value per-inputId"); - toRemove.add(value); + if (toRemove == null) toRemove = new SmartList(value); + else { + LOG.error("Expected only one value per-inputId"); + toRemove.add(value); + } } } - if (!toRemove.isEmpty()) { + if (toRemove != null) { for (Value value : toRemove) { removeValue(inputId, value); } @@ -108,7 +115,6 @@ class ValueContainerImpl extends UpdatableValueContainer implement return true; } - private final static Object myNullValue = new Object(); private Value maskNull(Value value) { if (value == null) { return (Value)myNullValue; @@ -122,9 +128,8 @@ class ValueContainerImpl extends UpdatableValueContainer implement return EmptyIterator.getInstance(); } - final Set values = Collections.unmodifiableSet(myInputIdMapping.keySet()); return new Iterator() { - final Iterator iterator = values.iterator(); + final Iterator iterator = myInputIdMapping.keySet().iterator(); @Override public boolean hasNext() { @@ -140,7 +145,7 @@ class ValueContainerImpl extends UpdatableValueContainer implement @Override public void remove() { - iterator.remove(); + throw new UnsupportedOperationException(); } }; }