From ea4a8a7f6de24c10b14b8d4bf01b371284f5db27 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Mon, 25 Nov 2024 15:54:41 +0100 Subject: [PATCH] IJPL-166213 use soft references for iconCache in IconDeferrerImpl If someone reads code for long enough, hard-referenced cache eventually gets too big. For some reason, `LowMemoryWatcher.register(::clearCache)` does not help with that. So, let's use soft references instead GitOrigin-RevId: d9be28c5150161a98cceea6a11bb3adab1d9d41e --- .../src/com/intellij/ui/IconDeferrerImpl.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/IconDeferrerImpl.kt b/platform/platform-impl/src/com/intellij/ui/IconDeferrerImpl.kt index ae6549f9a937..ccd5790f2d57 100644 --- a/platform/platform-impl/src/com/intellij/ui/IconDeferrerImpl.kt +++ b/platform/platform-impl/src/com/intellij/ui/IconDeferrerImpl.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. @file:Suppress("ReplaceGetOrSet", "ReplacePutWithAssignment") package com.intellij.ui @@ -12,11 +12,11 @@ import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.BulkFileListener import com.intellij.openapi.vfs.newvfs.events.VFileEvent import com.intellij.psi.util.PsiModificationTracker +import com.intellij.util.containers.CollectionFactory import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.asContextElement import kotlinx.coroutines.job import kotlinx.coroutines.withContext -import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.LongAdder import javax.swing.Icon @@ -39,9 +39,8 @@ internal class IconDeferrerImpl(coroutineScope: CoroutineScope) : IconDeferrer() // Due to a critical bug (https://youtrack.jetbrains.com/issue/IDEA-320644/Improve-Smart-PSI-pointer-equals-implementation), // we are not using "caffeine". - // Furthermore, a size-bounded cache is unnecessary for us because our application has frequent cache clearances, - // such as during PSI modifications. - private val iconCache = ConcurrentHashMap() + private val iconCache = CollectionFactory.createSoftKeySoftValueMap() + @Volatile private var mightBePopulated = false // used to avoid multiple calls PHM#clear() which might be expensive, no need to be atomic or something else private val lastClearTimestamp = LongAdder()