From 9a4ff6e2010a3ff0637794689e595d904fd630b4 Mon Sep 17 00:00:00 2001 From: Alexander Likhachev Date: Sat, 5 Jun 2021 00:50:07 +0300 Subject: [PATCH] [Gradle, JS] Add libraries filter caching in compile task Previously any compile task was honestly reading dependency metadata from filesystem to check whether it's K/JS module even if another compile task already tested this dependency. Now the result of check is cached in build service that is cleared after build finish. It can save many rebuild time on incremental compilation of complex projects. #KT-47154 Fixed --- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index d46ec991bce..4a199d24deb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -16,6 +16,8 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters import org.gradle.api.tasks.* import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile @@ -57,6 +59,7 @@ import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.library.impl.isKotlinLibrary import org.jetbrains.kotlin.utils.JsLibraryUtils import java.io.File +import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject const val KOTLIN_BUILD_DIR_NAME = "kotlin" @@ -616,6 +619,21 @@ abstract class Kotlin2JsCompile @Inject constructor( } } ).disallowChanges() + val libraryCacheService = task.project.rootProject.gradle.sharedServices.registerIfAbsent( + "${LibraryFilterCachingService::class.java.canonicalName}_${LibraryFilterCachingService::class.java.classLoader.hashCode()}", + LibraryFilterCachingService::class.java + ) {} + task.libraryCache.set(libraryCacheService).also { task.libraryCache.disallowChanges() } + } + } + + internal abstract class LibraryFilterCachingService : BuildService, AutoCloseable { + private val cache = ConcurrentHashMap() + + fun getOrCompute(key: File, compute: (File) -> Boolean) = cache.computeIfAbsent(key, compute) + + override fun close() { + cache.clear() } } @@ -711,8 +729,7 @@ abstract class Kotlin2JsCompile @Inject constructor( // 1) purely pre-IR backend // 2) purely IR backend // 3) hybrid pre-IR and IR backend. Can only accept libraries with both JS and IR parts. - @get:Internal - protected val libraryFilter: (File) -> Boolean + private val libraryFilterBody: (File) -> Boolean get() = if (kotlinOptions.isIrBackendEnabled()) { if (kotlinOptions.isPreIrBackendDisabled()) { ::isKotlinLibrary @@ -723,6 +740,15 @@ abstract class Kotlin2JsCompile @Inject constructor( JsLibraryUtils::isKotlinJavascriptLibrary } + @get:Internal + internal abstract val libraryCache: Property + + @get:Internal + protected val libraryFilter: (File) -> Boolean + get() = { file -> + libraryCache.get().getOrCompute(file, libraryFilterBody) + } + @get:Internal internal val absolutePathProvider = project.projectDir.absolutePath