Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add verbose tracing information about performance. #870

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package io.bazel.kotlin.builder.tasks

import com.sun.management.OperatingSystemMXBean
import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor
import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor
import io.bazel.kotlin.builder.toolchain.CompilationStatusException
Expand All @@ -31,10 +32,14 @@ import io.bazel.kotlin.model.JvmCompilationTask
import io.bazel.kotlin.model.Platform
import io.bazel.kotlin.model.RuleKind
import io.bazel.worker.WorkerContext
import java.lang.management.ManagementFactory
import java.lang.management.MemoryUsage
import java.nio.charset.StandardCharsets
import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.Path
import java.time.Duration
import java.time.Duration.*
import java.util.regex.Pattern
import javax.inject.Inject
import javax.inject.Singleton
Expand Down Expand Up @@ -197,16 +202,82 @@ class KotlinBuilder @Inject internal constructor(
build()
}

private data class JvmTrace(
val gcCount: Long,
val gcTime: Duration,
val loadedClasses: Long,
val unloadedClasses: Long,
val heap: MemoryUsage,
val nonHeap: MemoryUsage,
val cpu: Duration
)

private fun executeJvmTask(
context: CompilationTaskContext,
workingDir: Path,
argMap: ArgMap
) {
val task = buildJvmTask(context.info, workingDir, argMap)
context.whenTracing {
val task = context.execute("buildtask") { buildJvmTask(context.info, workingDir, argMap) }

val trace = context.whenTracing {
print("alive for ${ofMillis(ManagementFactory.getRuntimeMXBean().uptime)}")
printProto("jvm task message:", task)

val (totalGcCount, totalGcDuration) = getGcStats()
val (heapMemoryUsage, nonHeapMemoryUsage) = getMemoryStats()
val (loadedClasses, unloadedClasses) = getClassStats()
return@whenTracing JvmTrace(
gcCount = totalGcCount,
gcTime = totalGcDuration,
loadedClasses = loadedClasses.toLong(),
unloadedClasses = unloadedClasses,
heap = heapMemoryUsage,
nonHeap = nonHeapMemoryUsage,
cpu = getCpuTime()
)
}
jvmTaskExecutor.execute(context, task)

trace?.run {
val (postGcCount, postGcDuration) = getGcStats()
val (heapMemoryUsage, nonHeapMemoryUsage) = getMemoryStats()
val (postLoadedClasses, postUnloadedClasses) = getClassStats()
print("""
gc:
task: ${postGcCount - gcCount}, ${postGcDuration.minus(gcTime)}
total: $postGcCount, $postGcDuration
mem:
heap:
pre: $heap
post: $heapMemoryUsage
nonheap:
pre: $nonHeap
post: $nonHeapMemoryUsage
classes (loaded/unloaded):
pre: $loadedClasses / $unloadedClasses
post: $postLoadedClasses / $postUnloadedClasses
cpu time: ${getCpuTime().minus(cpu)}
""".trimIndent())
}
}

private fun getCpuTime() = Duration.ofNanos((ManagementFactory.getOperatingSystemMXBean() as OperatingSystemMXBean).processCpuTime)

private fun getMemoryStats() = ManagementFactory.getMemoryMXBean().run {
heapMemoryUsage to nonHeapMemoryUsage
}

private fun getGcStats() = ManagementFactory.getGarbageCollectorMXBeans()
.asSequence()
.map { bean ->
bean.collectionCount to ofMillis(bean.collectionTime)
}
.reduce { (totalCount, totalDuration), (currentCount, currentDuration) ->
totalCount + currentCount to totalDuration + currentDuration
}

private fun getClassStats() = ManagementFactory.getClassLoadingMXBean().run {
loadedClassCount to unloadedClassCount
}

private fun buildJvmTask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,11 @@ fun JvmCompilationTask.compileKotlin(
return emptyList()
} else {
return (
args + plugins(
args.also{ compileArgs ->
context.whenTracing {
compileArgs.flag("-verbose").flag("-Xreport-perf")
}
} + plugins(
options = inputs.compilerPluginOptionsList,
classpath = inputs.compilerPluginClasspathList
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ package io.bazel.kotlin.builder.toolchain

import com.google.protobuf.MessageOrBuilder
import com.google.protobuf.TextFormat
import com.sun.management.OperatingSystemMXBean
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these imports needed still?

import io.bazel.kotlin.model.CompilationTaskInfo
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.lang.management.ManagementFactory
import java.nio.file.FileSystems

class CompilationTaskContext(
Expand Down