save some completion memory by replacing weak maps with user data

This commit is contained in:
peter
2017-03-28 20:44:12 +02:00
parent b5e28e3113
commit b795a3eb9d
4 changed files with 26 additions and 37 deletions
@@ -25,10 +25,7 @@ import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.patterns.StandardPatterns;
import com.intellij.util.ProcessingContext;
@@ -66,6 +63,7 @@ public class CompletionLookupArranger extends LookupArranger {
private final CompletionProgressIndicator myProcess;
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
private final Map<CompletionSorterImpl, Classifier<LookupElement>> myClassifiers = new LinkedHashMap<>();
private final Key<CompletionSorterImpl> mySorterKey = Key.create("SORTER_KEY");
private final CompletionFinalSorter myFinalSorter = CompletionFinalSorter.newSorter();
private int myPrefixChanges;
@@ -89,7 +87,8 @@ public class CompletionLookupArranger extends LookupArranger {
@NotNull
private CompletionSorterImpl obtainSorter(LookupElement element) {
return myProcess.getSorter(element);
//noinspection ConstantConditions
return element.getUserData(mySorterKey);
}
@NotNull
@@ -132,6 +131,10 @@ public class CompletionLookupArranger extends LookupArranger {
return result;
}
void associateSorter(LookupElement element, CompletionSorterImpl sorter) {
element.putUserData(mySorterKey, sorter);
}
private static boolean haveSameWeights(List<Pair<LookupElement, Object>> pairs) {
if (pairs.isEmpty()) return true;
@@ -82,7 +82,6 @@ import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/**
@@ -97,6 +96,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
private final Caret myCaret;
private final CompletionParameters myParameters;
private final CodeCompletionHandlerBase myHandler;
private final CompletionLookupArranger myArranger;
private OffsetsInFile myHostOffsets;
private final LookupImpl myLookup;
private final MergingUpdateQueue myQueue;
@@ -128,8 +128,6 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
private volatile int myCount;
private volatile boolean myHasPsiElements;
private boolean myLookupUpdated;
private final ConcurrentMap<LookupElement, CompletionSorterImpl> myItemSorters =
ContainerUtil.createConcurrentWeakMap(ContainerUtil.identityStrategy());
private final PropertyChangeListener myLookupManagerListener;
private final Queue<Runnable> myAdvertiserChanges = new ConcurrentLinkedQueue<>();
private final List<CompletionResult> myDelayedMiddleMatches = ContainerUtil.newArrayList();
@@ -155,7 +153,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
myAdvertiserChanges.offer(() -> myLookup.getAdvertiser().clearAdvertisements());
myLookup.setArranger(new CompletionLookupArranger(parameters, this));
myArranger = new CompletionLookupArranger(parameters, this);
myLookup.setArranger(myArranger);
myLookup.addLookupListener(myLookupListener);
myLookup.setCalculating(true);
@@ -291,11 +290,6 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
}
}
@NotNull
CompletionSorterImpl getSorter(LookupElement element) {
return myItemSorters.get(element);
}
@Override
public void dispose() {
}
@@ -451,7 +445,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
addDelayedMiddleMatches();
}
myItemSorters.put(lookupElement, (CompletionSorterImpl)item.getSorter());
myArranger.associateSorter(lookupElement, (CompletionSorterImpl)item.getSorter());
if (item.isStartMatch() || allowMiddleMatches) {
addItemToLookup(item);
} else {
@@ -19,10 +19,9 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.EqualityPolicy;
import com.intellij.util.containers.hash.LinkedHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,7 +35,7 @@ public abstract class LookupArranger implements WeighingContext {
private final List<LookupElement> myMatchingItems = new ArrayList<>();
private final List<LookupElement> myExactPrefixItems = new ArrayList<>();
private final List<LookupElement> myInexactPrefixItems = new ArrayList<>();
private final Map<LookupElement, PrefixMatcher> myMatchers = ContainerUtil.createConcurrentWeakMap(ContainerUtil.identityStrategy());
private final Key<PrefixMatcher> myMatcherKey = Key.create("LookupArrangerMatcher");
private String myAdditionalPrefix = "";
public void addElement(LookupElement item, LookupElementPresentation presentation) {
@@ -58,7 +57,7 @@ public abstract class LookupArranger implements WeighingContext {
}
public void registerMatcher(@NotNull LookupElement item, @NotNull PrefixMatcher matcher) {
myMatchers.put(item, matcher);
item.putUserData(myMatcherKey, matcher);
}
@NotNull
@@ -70,7 +69,7 @@ public abstract class LookupArranger implements WeighingContext {
@NotNull
public PrefixMatcher itemMatcher(@NotNull LookupElement item) {
PrefixMatcher matcher = myMatchers.get(item);
PrefixMatcher matcher = item.getUserData(myMatcherKey);
if (matcher == null) {
throw new AssertionError("Item not in lookup: item=" + item + "; lookup items=" + myItems);
}
@@ -89,20 +88,17 @@ public abstract class LookupArranger implements WeighingContext {
}
public final void prefixReplaced(Lookup lookup, String newPrefix) {
//noinspection unchecked
Map<LookupElement, PrefixMatcher> newMatchers = new LinkedHashMap(EqualityPolicy.IDENTITY);
for (LookupElement item : myItems) {
ArrayList<LookupElement> itemCopy = ContainerUtil.newArrayList(myItems);
myItems.clear();
for (LookupElement item : itemCopy) {
if (item.isValid()) {
PrefixMatcher matcher = itemMatcher(item).cloneWithPrefix(newPrefix);
if (matcher.prefixMatches(item)) {
newMatchers.put(item, matcher);
item.putUserData(myMatcherKey, matcher);
myItems.add(item);
}
}
}
myMatchers.clear();
myMatchers.putAll(newMatchers);
myItems.clear();
myItems.addAll(newMatchers.keySet());
prefixChanged(lookup);
}
@@ -42,10 +42,7 @@ import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.PsiDocumentManager;
@@ -79,6 +76,7 @@ import java.util.Map;
public class LookupImpl extends LightweightHint implements LookupEx, Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.lookup.impl.LookupImpl");
private static final Key<Font> CUSTOM_FONT_KEY = Key.create("CustomLookupElementFont");
private final LookupOffsets myOffsets;
private final Project myProject;
@@ -123,8 +121,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
private boolean myChangeGuard;
private volatile LookupArranger myArranger;
private LookupArranger myPresentableArranger;
private final Map<LookupElement, Font> myCustomFonts = ContainerUtil.createConcurrentWeakMap(10, 0.75f, Runtime.getRuntime().availableProcessors(),
ContainerUtil.identityStrategy());
private boolean myStartCompletionWhenNothingMatches;
boolean myResizePending;
private boolean myFinishing;
@@ -273,15 +269,15 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
private void updateLookupWidth(LookupElement item, LookupElementPresentation presentation) {
final Font customFont = myCellRenderer.getFontAbleToDisplay(presentation);
if (customFont != null) {
myCustomFonts.put(item, customFont);
item.putUserData(CUSTOM_FONT_KEY, customFont);
}
int maxWidth = myCellRenderer.updateMaximumWidth(presentation, item);
myLookupTextWidth = Math.max(maxWidth, myLookupTextWidth);
}
@Nullable
public Font getCustomFont(LookupElement item, boolean bold) {
Font font = myCustomFonts.get(item);
Font getCustomFont(LookupElement item, boolean bold) {
Font font = item.getUserData(CUSTOM_FONT_KEY);
return font == null ? null : bold ? font.deriveFont(Font.BOLD) : font;
}