[psi] packageCache: avoid pair as a key

supposedly, when search for package is performed,
it's performed multiple times with different names
but for the same scope.
In this situation, extracting scope from key brings a lot of memory.
For IJ, it reduces load from 7Mb -> 4Mb
This commit is contained in:
Anna Kozlova
2023-06-22 10:53:20 +02:00
committed by Space Team
parent abdc44c18a
commit 92bcf3b2d5
@@ -22,7 +22,6 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.PackageIndex; import com.intellij.openapi.roots.PackageIndex;
import com.intellij.openapi.util.LowMemoryWatcher; import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileManager;
@@ -62,10 +61,10 @@ public class KotlinJavaPsiFacade implements Disposable {
private static class PackageCache { private static class PackageCache {
// long term cache // long term cache
final ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage> packageInLibScopeCache = new ConcurrentHashMap<>(); final ConcurrentMap<GlobalSearchScope, ConcurrentMap<String, PsiPackage>> packageInLibScopeCache = new ConcurrentHashMap<>();
// short term caches // short term caches
final ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage> packageInScopeCache = new ConcurrentHashMap<>(); final ConcurrentMap<GlobalSearchScope, ConcurrentMap<String, PsiPackage>> packageInScopeCache = new ConcurrentHashMap<>();
final ConcurrentMap<String, Boolean> hasPackageInAllScopeCache = new ConcurrentHashMap<>(); final ConcurrentMap<String, Boolean> hasPackageInAllScopeCache = new ConcurrentHashMap<>();
void clear() { void clear() {
@@ -340,12 +339,13 @@ public class KotlinJavaPsiFacade implements Disposable {
Boolean packageFoundInAllScope = cache.hasPackageInAllScopeCache.get(qualifiedName); Boolean packageFoundInAllScope = cache.hasPackageInAllScopeCache.get(qualifiedName);
if (packageFoundInAllScope != null && !packageFoundInAllScope.booleanValue()) return null; if (packageFoundInAllScope != null && !packageFoundInAllScope.booleanValue()) return null;
Pair<String, GlobalSearchScope> key = new Pair<>(qualifiedName, searchScope); ConcurrentMap<String, PsiPackage> packageInLibScope = cache.packageInLibScopeCache.get(searchScope);
PsiPackage pkg = cache.packageInLibScopeCache.get(key); PsiPackage pkg = packageInLibScope != null ? packageInLibScope.get(qualifiedName) : null;
if (pkg != null) { if (pkg != null) {
return unwrap(pkg); return unwrap(pkg);
} }
pkg = cache.packageInScopeCache.get(key); ConcurrentMap<String, PsiPackage> packageInScope = cache.packageInScopeCache.get(searchScope);
pkg = packageInScope != null ? packageInScope.get(qualifiedName) : null;
if (pkg != null) { if (pkg != null) {
return unwrap(pkg); return unwrap(pkg);
} }
@@ -356,7 +356,7 @@ public class KotlinJavaPsiFacade implements Disposable {
{ {
// store found package in a long term cache if package is found in library search scope // store found package in a long term cache if package is found in library search scope
ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage> existedPackageInScopeCache = ConcurrentMap<GlobalSearchScope, ConcurrentMap<String, PsiPackage>> existedPackageInScopeCache =
isALibrarySearchScope ? cache.packageInLibScopeCache : cache.packageInScopeCache; isALibrarySearchScope ? cache.packageInLibScopeCache : cache.packageInScopeCache;
KotlinPsiElementFinderWrapper[] finders = filteredFinders(); KotlinPsiElementFinderWrapper[] finders = filteredFinders();
@@ -367,7 +367,9 @@ public class KotlinJavaPsiFacade implements Disposable {
if (!finder.isSameResultForAnyScope()) { if (!finder.isSameResultForAnyScope()) {
PsiPackage aPackage = finder.findPackage(qualifiedName, searchScope); PsiPackage aPackage = finder.findPackage(qualifiedName, searchScope);
if (aPackage != null) { if (aPackage != null) {
return unwrap(ConcurrencyUtil.cacheOrGet(existedPackageInScopeCache, key, aPackage)); ConcurrentMap<String, PsiPackage> concurrentMap =
ConcurrencyUtil.cacheOrGet(existedPackageInScopeCache, searchScope, new ConcurrentHashMap<>());
return unwrap(ConcurrencyUtil.cacheOrGet(concurrentMap, qualifiedName, aPackage));
} }
} }
} }
@@ -377,7 +379,9 @@ public class KotlinJavaPsiFacade implements Disposable {
PsiPackage aPackage = finder.findPackage(qualifiedName, searchScope); PsiPackage aPackage = finder.findPackage(qualifiedName, searchScope);
if (aPackage != null) { if (aPackage != null) {
return unwrap(ConcurrencyUtil.cacheOrGet(existedPackageInScopeCache, key, aPackage)); ConcurrentMap<String, PsiPackage> concurrentMap =
ConcurrencyUtil.cacheOrGet(existedPackageInScopeCache, searchScope, new ConcurrentHashMap<>());
return unwrap(ConcurrencyUtil.cacheOrGet(concurrentMap, qualifiedName, aPackage));
} }
} }
@@ -397,7 +401,7 @@ public class KotlinJavaPsiFacade implements Disposable {
} }
} }
ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage> notFoundPackageInScopeCache; ConcurrentMap<GlobalSearchScope, ConcurrentMap<String, PsiPackage>> notFoundPackageInScopeCache;
switch (notFoundCacheType) { switch (notFoundCacheType) {
case LIB_SCOPE: case LIB_SCOPE:
notFoundPackageInScopeCache = cache.packageInLibScopeCache; notFoundPackageInScopeCache = cache.packageInLibScopeCache;
@@ -411,7 +415,9 @@ public class KotlinJavaPsiFacade implements Disposable {
throw new IllegalStateException("Impossible enum value: " + notFoundCacheType.toString()); throw new IllegalStateException("Impossible enum value: " + notFoundCacheType.toString());
} }
return unwrap(ConcurrencyUtil.cacheOrGet(notFoundPackageInScopeCache, key, NULL_PACKAGE)); ConcurrentMap<String, PsiPackage> concurrentMap =
ConcurrencyUtil.cacheOrGet(notFoundPackageInScopeCache, searchScope, new ConcurrentHashMap<>());
return unwrap(ConcurrencyUtil.cacheOrGet(concurrentMap, qualifiedName, NULL_PACKAGE));
} }
private PackageCache obtainPackageCache() { private PackageCache obtainPackageCache() {