From 28e33aaf56088472618c64f288381fc54865bba8 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 21 Apr 2016 10:52:29 +0300 Subject: [PATCH] Use weak-reference based SLRU cache for module resolvers Create new module resolver iff it's weak reference is collected, but at the same time keep hot modules in SLRU map not to give them be collected --- .../kotlin/analyzer/AnalyzerFacade.kt | 4 +- .../kotlin/analyzer/WeakReferenceSLRUCache.kt | 64 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/analyzer/WeakReferenceSLRUCache.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 65768611305..96855f599ac 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -206,11 +206,13 @@ abstract class AnalyzerFacade { addFriends() + val cache = WeakReferenceSLRUCache(storageManager) + fun initializeResolverForProject() { modules.forEach { module -> val descriptor = resolverForProject.descriptorForModule(module) - val computeResolverForModule = storageManager.createLazyValue { + val computeResolverForModule = cache.prepareValueComputation(module) { val content = modulesContent(module) createResolverForModule( module, descriptor, projectContext.withModule(descriptor), modulesContent(module), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/WeakReferenceSLRUCache.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/WeakReferenceSLRUCache.kt new file mode 100644 index 00000000000..27513774513 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/WeakReferenceSLRUCache.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.analyzer + +import com.intellij.util.containers.ContainerUtil +import com.intellij.util.containers.SLRUMap +import org.jetbrains.kotlin.storage.StorageManager + +class WeakReferenceSLRUCache(private val storageManager: StorageManager) { + private val weakValueMap = ContainerUtil.createConcurrentWeakValueMap() + // Store most recently used values in SLRU cache to make them available even if no other references to them exist + private val recentlyUsed = SLRUMap(20, 20) + + fun prepareValueComputation(module: K, computation: () -> V): () -> V = { + getOrCompute(module, computation) + } + + private fun getOrCompute(module: K, computation: () -> V): V { + getFromWeakValueMap(module)?.let { + return it + } + + return storageManager.compute { + getFromWeakValueMap(module)?.let { + return@compute it + } + + val result = computation() + weakValueMap[module] = result + + recentlyUsed.put(result, STUB_OBJECT) + + result + } + } + + private fun getFromWeakValueMap(module: K) = + weakValueMap[module]?.let { + recordAccess(it) + it + } + + private fun recordAccess(resolver: V) { + storageManager.compute { + recentlyUsed.get(resolver) + } + } +} + +private val STUB_OBJECT = Any()