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
|
||||
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinLogger
|
||||
|
||||
@@ -31,4 +32,17 @@ internal inline fun KotlinLogger.kotlinDebug(fn: () -> String) {
|
||||
val msg = fn()
|
||||
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.tasks.TaskWithLocalState
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinWarn
|
||||
import org.jetbrains.kotlin.gradle.logging.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||
import org.jetbrains.kotlin.utils.LibraryUtils
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
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 =
|
||||
GradleCompilerRunner(this)
|
||||
|
||||
@@ -266,18 +265,12 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
// 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)
|
||||
// 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 outputFiles = HashSet<File>()
|
||||
allOutputFiles().forEach {
|
||||
if (it.isDirectory) {
|
||||
it.walk().filterTo(outputFiles, File::isFile)
|
||||
} else if (it.isFile) {
|
||||
outputFiles.add(it)
|
||||
val outputsBackup: TaskOutputsBackup? =
|
||||
if (incremental && inputs.isIncremental)
|
||||
kotlinLogger.logTime("Backing up outputs for incremental build") {
|
||||
TaskOutputsBackup(allOutputFiles())
|
||||
}
|
||||
}
|
||||
|
||||
outputFiles.keysToMap { it.readBytes() }
|
||||
} else null
|
||||
else null
|
||||
|
||||
if (!incremental) {
|
||||
clearLocalState("IC is disabled")
|
||||
@@ -286,26 +279,11 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
try {
|
||||
executeImpl(inputs)
|
||||
} catch (t: Throwable) {
|
||||
allOutputFiles().forEach {
|
||||
if (it.isDirectory) {
|
||||
it.deleteRecursively()
|
||||
} else if (it.isFile) {
|
||||
it.delete()
|
||||
if (outputsBackup != null) {
|
||||
kotlinLogger.logTime("Restoring previous outputs on error") {
|
||||
outputsBackup.restoreOutputs()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+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