Call System.gc only when when log level is debug, fixes KT-11022
This commit is contained in:
committed by
Ilya Chernikov
parent
bc5110550a
commit
d0efd4083f
+31
-13
@@ -21,12 +21,7 @@ import org.gradle.BuildAdapter
|
||||
import org.gradle.BuildResult
|
||||
import org.gradle.api.logging.Logging
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
|
||||
internal fun getUsedMemoryKb(): Long {
|
||||
System.gc()
|
||||
val rt = Runtime.getRuntime()
|
||||
return (rt.totalMemory() - rt.freeMemory()) / 1024
|
||||
}
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
||||
private fun comparableVersionStr(version: String) =
|
||||
@@ -39,13 +34,23 @@ private fun comparableVersionStr(version: String) =
|
||||
?.let { if (it.all { (it?.value?.length ?: 0).let { it > 0 && it < 4 }}) it else null }
|
||||
?.joinToString(".", transform = { it!!.value.padStart(3, '0') })
|
||||
|
||||
class CleanUpBuildListener(pluginClassLoader: ClassLoader) : BuildAdapter() {
|
||||
companion object {
|
||||
const val FORCE_SYSTEM_GC_MESSAGE = "Forcing System.gc()"
|
||||
}
|
||||
|
||||
class FinishBuildListener(pluginClassLoader: ClassLoader, val startMemory: Long) : BuildAdapter() {
|
||||
val log = Logging.getLogger(this.javaClass)
|
||||
|
||||
private val log = Logging.getLogger(this.javaClass)
|
||||
private var threadTracker: ThreadTracker? = ThreadTracker()
|
||||
|
||||
private val cleanup = CompilerServicesCleanup(pluginClassLoader)
|
||||
private var startMemory: Long? = null
|
||||
|
||||
// There is function with the same name in BuildAdapter,
|
||||
// but it is called before any plugin can attach build listener
|
||||
fun buildStarted() {
|
||||
if (log.isDebugEnabled) {
|
||||
startMemory = getUsedMemoryKb()!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildFinished(result: BuildResult?) {
|
||||
log.kotlinDebug("Build finished listener")
|
||||
@@ -60,9 +65,22 @@ class FinishBuildListener(pluginClassLoader: ClassLoader, val startMemory: Long)
|
||||
gradle.removeListener(this)
|
||||
}
|
||||
|
||||
// the value reported here is not necessarily a leak, since it is calculated before collecting the plugin classes
|
||||
// but on subsequent runs in the daemon it should be rather small, then the classes are actually reused by the daemon (see above)
|
||||
getUsedMemoryKb().let { log.kotlinDebug("[PERF] Used memory after build: $it kb (${"%+d".format(it - startMemory)} kb)") }
|
||||
startMemory?.let { startMemoryCopy ->
|
||||
getUsedMemoryKb()?.let { endMemory ->
|
||||
// the value reported here is not necessarily a leak, since it is calculated before collecting the plugin classes
|
||||
// but on subsequent runs in the daemon it should be rather small, then the classes are actually reused by the daemon (see above)
|
||||
log.kotlinDebug("[PERF] Used memory after build: $endMemory kb (difference since build start: ${"%+d".format(endMemory - startMemoryCopy)} kb)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUsedMemoryKb(): Long? {
|
||||
if (!log.isDebugEnabled) return null
|
||||
|
||||
log.lifecycle(FORCE_SYSTEM_GC_MESSAGE)
|
||||
System.gc()
|
||||
val rt = Runtime.getRuntime()
|
||||
return (rt.totalMemory() - rt.freeMemory()) / 1024
|
||||
}
|
||||
}
|
||||
|
||||
+5
-13
@@ -2,18 +2,10 @@ package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import java.net.URL
|
||||
import org.gradle.api.logging.Logging
|
||||
import java.util.Properties
|
||||
import java.io.FileNotFoundException
|
||||
import org.gradle.api.initialization.dsl.ScriptHandler
|
||||
import org.gradle.api.invocation.Gradle
|
||||
import org.gradle.api.logging.Logger
|
||||
import java.lang.reflect.Method
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||
import java.net.URLClassLoader
|
||||
|
||||
// TODO: simplify: the complicated structure is a leftover from dynamic loading of plugin core, could be significantly simplified now
|
||||
|
||||
@@ -21,9 +13,10 @@ abstract class KotlinBasePluginWrapper: Plugin<Project> {
|
||||
|
||||
val log = Logging.getLogger(this.javaClass)
|
||||
|
||||
public override fun apply(project: Project) {
|
||||
|
||||
val startMemory = getUsedMemoryKb()
|
||||
override fun apply(project: Project) {
|
||||
val cleanUpBuildListener = CleanUpBuildListener(this.javaClass.classLoader)
|
||||
cleanUpBuildListener.buildStarted()
|
||||
project.gradle.addBuildListener(cleanUpBuildListener)
|
||||
|
||||
val sourceBuildScript = findSourceBuildScript(project)
|
||||
if (sourceBuildScript == null) {
|
||||
@@ -38,7 +31,6 @@ abstract class KotlinBasePluginWrapper: Plugin<Project> {
|
||||
val plugin = getPlugin(this.javaClass.classLoader, sourceBuildScript)
|
||||
plugin.apply(project)
|
||||
|
||||
project.gradle.addBuildListener(FinishBuildListener(this.javaClass.classLoader, startMemory))
|
||||
}
|
||||
|
||||
protected abstract fun getPlugin(pluginClassLoader: ClassLoader, scriptHandler: ScriptHandler): Plugin<Project>
|
||||
|
||||
+1
-3
@@ -1,9 +1,7 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.junit.Test
|
||||
import org.jetbrains.kotlin.gradle.BaseGradleIT.Project
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
class SimpleKotlinGradleIT : BaseGradleIT() {
|
||||
|
||||
|
||||
+15
-1
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.jetbrains.kotlin.gradle.BaseGradleIT.Project
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.jetbrains.kotlin.gradle.plugin.CleanUpBuildListener
|
||||
import org.junit.Test
|
||||
|
||||
class KotlinGradleIT: BaseGradleIT() {
|
||||
@@ -81,6 +82,19 @@ class KotlinGradleIT: BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLogLevelForceGC() {
|
||||
val debugProject = Project("simpleProject", "1.12", minLogLevel = LogLevel.DEBUG)
|
||||
debugProject.build("build") {
|
||||
assertContains(CleanUpBuildListener.FORCE_SYSTEM_GC_MESSAGE)
|
||||
}
|
||||
|
||||
val infoProject = Project("simpleProject", "1.12", minLogLevel = LogLevel.INFO)
|
||||
infoProject.build("clean", "build") {
|
||||
assertNotContains(CleanUpBuildListener.FORCE_SYSTEM_GC_MESSAGE)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKotlinClasspath() {
|
||||
Project("classpathTest", "1.6").build("build") {
|
||||
|
||||
Reference in New Issue
Block a user