Measure time spent on backing up and restoring outputs
This commit is contained in:
+14
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.logging
|
package org.jetbrains.kotlin.gradle.logging
|
||||||
|
|
||||||
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.jetbrains.kotlin.compilerRunner.KotlinLogger
|
import org.jetbrains.kotlin.compilerRunner.KotlinLogger
|
||||||
|
|
||||||
@@ -31,4 +32,17 @@ internal inline fun KotlinLogger.kotlinDebug(fn: () -> String) {
|
|||||||
val msg = fn()
|
val msg = fn()
|
||||||
debug("[KOTLIN] $msg")
|
debug("[KOTLIN] $msg")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun <T> KotlinLogger.logTime(action: String, fn: () -> T): T {
|
||||||
|
val startNs = System.nanoTime()
|
||||||
|
val result = fn()
|
||||||
|
val endNs = System.nanoTime()
|
||||||
|
|
||||||
|
val timeNs = endNs - startNs
|
||||||
|
val timeMs = timeNs.toDouble() / 1_000_000
|
||||||
|
|
||||||
|
debug(String.format("%s took %.2f ms", action, timeMs))
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
+11
-33
@@ -28,16 +28,13 @@ import org.jetbrains.kotlin.gradle.internal.CompilerArgumentAwareWithInput
|
|||||||
import org.jetbrains.kotlin.gradle.internal.prepareCompilerArguments
|
import org.jetbrains.kotlin.gradle.internal.prepareCompilerArguments
|
||||||
import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
|
import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
|
||||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
import org.jetbrains.kotlin.gradle.logging.*
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinWarn
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.*
|
||||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||||
import org.jetbrains.kotlin.utils.LibraryUtils
|
import org.jetbrains.kotlin.utils.LibraryUtils
|
||||||
import org.jetbrains.kotlin.utils.keysToMap
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -254,6 +251,8 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
||||||
|
|
||||||
internal open fun compilerRunner(): GradleCompilerRunner =
|
internal open fun compilerRunner(): GradleCompilerRunner =
|
||||||
GradleCompilerRunner(this)
|
GradleCompilerRunner(this)
|
||||||
|
|
||||||
@@ -266,18 +265,12 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
// If task throws exception, but its outputs are changed during execution,
|
// If task throws exception, but its outputs are changed during execution,
|
||||||
// then Gradle forces next build to be non-incremental (see Gradle's DefaultTaskArtifactStateRepository#persistNewOutputs)
|
// then Gradle forces next build to be non-incremental (see Gradle's DefaultTaskArtifactStateRepository#persistNewOutputs)
|
||||||
// To prevent this, we backup outputs before incremental build and restore when exception is thrown
|
// To prevent this, we backup outputs before incremental build and restore when exception is thrown
|
||||||
val prevOutputs: Map<File, ByteArray>? = if (incremental && inputs.isIncremental) {
|
val outputsBackup: TaskOutputsBackup? =
|
||||||
val outputFiles = HashSet<File>()
|
if (incremental && inputs.isIncremental)
|
||||||
allOutputFiles().forEach {
|
kotlinLogger.logTime("Backing up outputs for incremental build") {
|
||||||
if (it.isDirectory) {
|
TaskOutputsBackup(allOutputFiles())
|
||||||
it.walk().filterTo(outputFiles, File::isFile)
|
|
||||||
} else if (it.isFile) {
|
|
||||||
outputFiles.add(it)
|
|
||||||
}
|
}
|
||||||
}
|
else null
|
||||||
|
|
||||||
outputFiles.keysToMap { it.readBytes() }
|
|
||||||
} else null
|
|
||||||
|
|
||||||
if (!incremental) {
|
if (!incremental) {
|
||||||
clearLocalState("IC is disabled")
|
clearLocalState("IC is disabled")
|
||||||
@@ -286,26 +279,11 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
try {
|
try {
|
||||||
executeImpl(inputs)
|
executeImpl(inputs)
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
allOutputFiles().forEach {
|
if (outputsBackup != null) {
|
||||||
if (it.isDirectory) {
|
kotlinLogger.logTime("Restoring previous outputs on error") {
|
||||||
it.deleteRecursively()
|
outputsBackup.restoreOutputs()
|
||||||
} else if (it.isFile) {
|
|
||||||
it.delete()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevOutputs != null) {
|
|
||||||
val dirs = HashSet<File>()
|
|
||||||
|
|
||||||
for ((file, bytes) in prevOutputs) {
|
|
||||||
val dir = file.parentFile
|
|
||||||
if (dirs.add(dir)) {
|
|
||||||
dir.mkdirs()
|
|
||||||
}
|
|
||||||
file.writeBytes(bytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw t
|
throw t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. 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.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.jetbrains.kotlin.utils.keysToMap
|
||||||
|
import java.io.File
|
||||||
|
import java.util.HashSet
|
||||||
|
|
||||||
|
internal class TaskOutputsBackup(private val outputs: FileCollection) {
|
||||||
|
private val previousOutputs: Map<File, ByteArray>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val outputFiles = HashSet<File>()
|
||||||
|
outputs.forEach {
|
||||||
|
if (it.isDirectory) {
|
||||||
|
it.walk().filterTo(outputFiles, File::isFile)
|
||||||
|
} else if (it.isFile) {
|
||||||
|
outputFiles.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previousOutputs = outputFiles.keysToMap { it.readBytes() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restoreOutputs() {
|
||||||
|
outputs.forEach {
|
||||||
|
if (it.isDirectory) {
|
||||||
|
it.deleteRecursively()
|
||||||
|
} else if (it.isFile) {
|
||||||
|
it.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val dirs = HashSet<File>()
|
||||||
|
|
||||||
|
for ((file, bytes) in previousOutputs) {
|
||||||
|
val dir = file.parentFile
|
||||||
|
if (dirs.add(dir)) {
|
||||||
|
dir.mkdirs()
|
||||||
|
}
|
||||||
|
file.writeBytes(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user