From 5dec87eba8c50c34424ee4c746bc2acde5d15213 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 27 Feb 2024 17:45:14 +0100 Subject: [PATCH] [LL] Use soft references in `FileStructureCache` - We can also soft-reference the `KtFile` key. Chances are, if the `KtFile` can be garbage-collected, we do not need a `FileStructure` instance for it either. ^KT-65978 fixed --- .../api/fir/file/structure/FileStructureCache.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureCache.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureCache.kt index f82c20fd689..be0fe7fc6de 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureCache.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureCache.kt @@ -5,19 +5,26 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure +import com.intellij.util.containers.ContainerUtil import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents import org.jetbrains.kotlin.psi.KtFile -import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap /** - * Belongs to a [org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession] + * Caches [FileStructure] instances for an [LLFirResolveSession][org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession]. */ internal class FileStructureCache(private val moduleResolveComponents: LLFirModuleResolveComponents) { - private val cache = ConcurrentHashMap() + /** + * File structure elements can be rebuilt at any time and do not need to be unique (like FIR symbols), so they can be soft-referenced + * from this cache to reduce memory consumption. Any `analyze` call in a file causes file structure elements to be built, so during + * operations which cause a lot of files to be analyzed (such as Find Usages), a session might accumulate a lot of file structure + * elements. + */ + private val cache: ConcurrentMap = ContainerUtil.createConcurrentSoftKeySoftValueMap() fun getFileStructure(ktFile: KtFile): FileStructure = cache.computeIfAbsent(ktFile) { FileStructure.build(ktFile, moduleResolveComponents) } fun getCachedFileStructure(ktFile: KtFile): FileStructure? = cache[ktFile] -} \ No newline at end of file +}