use less memory along indexing path

This commit is contained in:
Maxim.Mossienko
2012-04-26 18:18:06 +04:00
parent c3b7aa4728
commit 43797e8722
3 changed files with 39 additions and 12 deletions
@@ -42,7 +42,7 @@ class ChangeTrackingValueContainer<Value> extends UpdatableValueContainer<Value>
myInitializer = initializer;
myAdded = new ValueContainerImpl<Value>();
myRemoved = new ValueContainerImpl<Value>();
myInvalidated = new TIntHashSet();
myInvalidated = new TIntHashSet(1);
}
//public void log(String op, int id, final Value value) {
@@ -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<Key, Value, Input> implements UpdatableIndex<Key,Val
throw new StorageException(e);
}
// add new values
for (Map.Entry<Key, Value> 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<StorageException> exceptionRef = new Ref<StorageException>();
final boolean b = ((THashMap<Key, Value>)newData).forEachEntry(new TObjectObjectProcedure<Key, Value>() {
@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<Key, Value> entry : newData.entrySet()) {
myStorage.addValue(entry.getKey(), inputId, entry.getValue());
}
}
if (myInputsIndex != null) {
try {
@@ -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<Value> extends UpdatableValueContainer<Value> implements Cloneable{
private static final Logger LOG = Logger.getInstance("#com.intellij.util.indexing.ValueContainerImpl");
private final static Object myNullValue = new Object();
private THashMap<Value, Object> myInputIdMapping;
public ValueContainerImpl() {
myInputIdMapping = new THashMap<Value, Object>();
// per statistic most maps (80%) has one value
myInputIdMapping = new THashMap<Value, Object>(1);
}
@Override
@@ -66,16 +69,20 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
@Override
public void removeAssociatedValue(int inputId) {
final List<Value> toRemove = new ArrayList<Value>(1);
if (myInputIdMapping.isEmpty()) return;
List<Value> toRemove = null;
for (final Iterator<Value> 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>(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<Value> extends UpdatableValueContainer<Value> 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<Value> extends UpdatableValueContainer<Value> implement
return EmptyIterator.getInstance();
}
final Set<Value> values = Collections.unmodifiableSet(myInputIdMapping.keySet());
return new Iterator<Value>() {
final Iterator<Value> iterator = values.iterator();
final Iterator<Value> iterator = myInputIdMapping.keySet().iterator();
@Override
public boolean hasNext() {
@@ -140,7 +145,7 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
@Override
public void remove() {
iterator.remove();
throw new UnsupportedOperationException();
}
};
}