From 6c627fa5c1683eaeb44d9255dc91bcea00edfa6e Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 29 Nov 2018 16:14:11 -0800 Subject: [PATCH] Cache classloaders for tools.jar and kapt in Gradle workers #KT-28852 fixed The loaders and hence some classes were repeatedly loaded and jit-compiled everytime when KaptExecution were dispatched. Those classes, like JavaCompiler, can be very large and therefore created a significant overhead. In some projects, the overhead accounted for more than 40% of total CPU time of annotation processing. This change tries to cache the classloaders so that they won't be reloaded and re-jitted. --- .../gradle/internal/kapt/KaptWithoutKotlincTask.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt index ff6c5d689e2..617ba6fde91 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt @@ -100,19 +100,24 @@ private class KaptExecution @Inject constructor( private const val JAVAC_CONTEXT_CLASS = "com.sun.tools.javac.util.Context" private fun kaptClass(classLoader: ClassLoader) = Class.forName("org.jetbrains.kotlin.kapt3.base.Kapt", true, classLoader) + private var cachedClassLoaderWithToolsJar: ClassLoader? = null + private var cachedKaptClassLoader: ClassLoader? = null } override fun run(): Unit = with(optionsForWorker) { val kaptClasspathUrls = kaptClasspath.map { it.toURI().toURL() }.toTypedArray() val rootClassLoader = findRootClassLoader() - val classLoaderWithToolsJar = if (toolsJar != null && !javacIsAlreadyHere()) { + val classLoaderWithToolsJar = cachedClassLoaderWithToolsJar ?: if (toolsJar != null && !javacIsAlreadyHere()) { URLClassLoader(arrayOf(toolsJar.toURI().toURL()), rootClassLoader) } else { rootClassLoader } + cachedClassLoaderWithToolsJar = classLoaderWithToolsJar + + val kaptClassLoader = cachedKaptClassLoader ?: URLClassLoader(kaptClasspathUrls, classLoaderWithToolsJar) + cachedKaptClassLoader = kaptClassLoader - val kaptClassLoader = URLClassLoader(kaptClasspathUrls, classLoaderWithToolsJar) val kaptMethod = kaptClass(kaptClassLoader).declaredMethods.single { it.name == "kapt" } kaptMethod.invoke(null, createKaptOptions(kaptClassLoader)) }