From 7c360c0068e48fc5f0e1d8466e0503df0b7607e9 Mon Sep 17 00:00:00 2001 From: Ivan Gavrilovic Date: Thu, 13 Aug 2020 20:44:25 +0100 Subject: [PATCH] Kotlin Gradle plugin - use build service to share incremental compilation info For large projects, incremental comilation mapping information may be quite large. With configuration caching enabled, each task gets its own copy of that state, and for a project with 1400 subprojects, this resulted in 3.6GB of additional state stored (once task graph is cached). This change introduces IncrementalModuleInfoProvider which allows build service to be used if configuration caching is enabled, and it falls back to static constant otherwise. --- .../GradleKotlinCompilerRunner.kt | 2 +- .../incremental/incrementalModuleInfo.kt | 38 +++++++++++++++++++ .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 23 ++++++++--- 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/incremental/incrementalModuleInfo.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index 5128c566317..04e8f18e33c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -141,7 +141,7 @@ internal open class GradleCompilerRunner(protected val taskProvider: GradleCompi } val incrementalCompilationEnvironment = environment.incrementalCompilationEnvironment - val modulesInfo = incrementalCompilationEnvironment?.let { incrementalModuleInfoProvider } + val modulesInfo = incrementalCompilationEnvironment?.let { incrementalModuleInfoProvider.get().info } val workArgs = GradleKotlinCompilerWorkArguments( projectFiles = ProjectFilesForCompilation( loggerProvider, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/incremental/incrementalModuleInfo.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/incremental/incrementalModuleInfo.kt new file mode 100644 index 00000000000..fb8fdc47f10 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/incremental/incrementalModuleInfo.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.incremental + +import org.gradle.api.provider.Property +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters +import org.jetbrains.kotlin.incremental.IncrementalModuleInfo + +/** + * Provider of [IncrementalModuleInfo] that allows concrete implementation to e.g use Gradle build services + * or rely on some static stats. + */ +interface IncrementalModuleInfoProvider { + val info: IncrementalModuleInfo +} + +/** A build service used to provide [IncrementalModuleInfo] instance for all tasks. */ +abstract class IncrementalModuleInfoBuildService : BuildService, + IncrementalModuleInfoProvider { + abstract class Parameters : BuildServiceParameters { + abstract val info: Property + } + + override val info: IncrementalModuleInfo + get() = parameters.info.get() + + companion object { + // Use class name + class loader in case there are multiple class loaders in the same build + fun getServiceName(): String { + val clazz = IncrementalModuleInfoBuildService::class.java + return clazz.canonicalName + "_" + clazz.classLoader.hashCode() + } + } +} 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 97d2ea95f4d..f02aa148e4f 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 @@ -25,6 +25,8 @@ import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.Companion.normal import org.jetbrains.kotlin.daemon.common.MultiModuleICSettings import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.incremental.ChangedFiles +import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoBuildService +import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoProvider import org.jetbrains.kotlin.gradle.internal.* import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles @@ -37,12 +39,11 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName import org.jetbrains.kotlin.gradle.report.BuildReportMode -import org.jetbrains.kotlin.gradle.utils.getValue +import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.isParentOf import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray import org.jetbrains.kotlin.incremental.ChangedFiles -import org.jetbrains.kotlin.incremental.IncrementalModuleInfo import org.jetbrains.kotlin.library.impl.isKotlinLibrary import org.jetbrains.kotlin.utils.JsLibraryUtils import java.io.File @@ -127,10 +128,22 @@ public class GradleCompileTaskProvider { rootDir = task.project.rootProject.rootDir sessionsDir = GradleCompilerRunner.sessionsDir(task.project) projectName = task.project.rootProject.name.normalizeForFlagFile() - buildModulesInfo = GradleCompilerRunner.buildModulesInfo(task.project.gradle) + val modulesInfo = GradleCompilerRunner.buildModulesInfo(task.project.gradle) + buildModulesInfo = if (!isConfigurationCacheAvailable(task.project.gradle)) { + task.project.provider { + object : IncrementalModuleInfoProvider { + override val info = modulesInfo + } + } + } else { + task.project.gradle.sharedServices.registerIfAbsent( + IncrementalModuleInfoBuildService.getServiceName(), IncrementalModuleInfoBuildService::class.java + ) { + it.parameters.info.set(modulesInfo) + } + } path = task.path logger = task.logger - } val path: String @@ -140,7 +153,7 @@ public class GradleCompileTaskProvider { val rootDir: File /*= project.rootProject.rootDir*/ val sessionsDir: File/* = GradleCompilerRunner.sessionsDir(project)*/ val projectName: String /*= project.rootProject.name.normalizeForFlagFile()*/ - val buildModulesInfo: IncrementalModuleInfo /*= GradleCompilerRunner.buildModulesInfo(project.gradle)*/ + val buildModulesInfo: Provider /*= GradleCompilerRunner.buildModulesInfo(project.gradle)*/ } abstract class AbstractKotlinCompile() : AbstractKotlinCompileTool() {