diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/Stats.kt b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/Stats.kt index 3163ee20d2c..ec086346928 100644 --- a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/Stats.kt +++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/Stats.kt @@ -207,7 +207,7 @@ class Stats( if (k == TEST_KEY) continue TeamCity.statValue("$n $k", v) (v as? Number)?.let { - TeamCity.testMetadata(n, k, it) + TeamCity.metadata(n, k, it) } } } diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/util/heapDumper.kt b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/util/heapDumper.kt new file mode 100644 index 00000000000..25a166c9fa2 --- /dev/null +++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/util/heapDumper.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.idea.perf.util + +import com.intellij.openapi.util.io.FileUtilRt +import com.sun.management.HotSpotDiagnosticMXBean +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream +import java.lang.management.ManagementFactory +import java.text.SimpleDateFormat +import java.util.* +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream + +object HeapDumper { + private const val HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic" + + private val hotspotMBean = initHotspotMBean() + + private fun initHotspotMBean() = ManagementFactory.newPlatformMXBeanProxy( + ManagementFactory.getPlatformMBeanServer(), + HOTSPOT_BEAN_NAME, + HotSpotDiagnosticMXBean::class.java + ) + + fun dumpHeap(fileNamePrefix: String, live: Boolean = true) { + val format = SimpleDateFormat("yyyyMMdd-HHmmss") + val timestamp = format.format(Date()) + val tempFile = File.createTempFile(fileNamePrefix, ".hprof") + tempFile.delete() + val fileName = "build/$fileNamePrefix-$timestamp.hprof.zip" + logMessage { "Dumping a heap into $tempFile ..." } + try { + hotspotMBean.dumpHeap(tempFile.toString(), live) + logMessage { "Heap dump is $tempFile ready." } + + zipFile(tempFile, File(fileName)) + + val testName = "Heap dump $timestamp" + TeamCity.test(testName) { + TeamCity.artifact(testName, "heapDump", fileName) + } + } catch (e: Exception) { + logMessage { "Error on making a heap dump: ${e.message}" } + e.printStackTrace() + } + } + + private fun zipFile(srcFile: File, targetFile: File) { + FileInputStream(srcFile).use { fis -> + ZipOutputStream(FileOutputStream(targetFile)).use { os -> + os.putNextEntry(ZipEntry(srcFile.name)) + FileUtilRt.copy(fis, os) + os.closeEntry() + } + } + } +} \ No newline at end of file diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/util/logging.kt b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/util/logging.kt index c94eedd6dfd..1cbcf4ab0de 100644 --- a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/util/logging.kt +++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/util/logging.kt @@ -9,7 +9,7 @@ import java.io.PrintWriter import java.io.StringWriter inline fun gradleMessage(block: () -> String) { - print("#gradle ${block()}") + //print("#gradle ${block()}") } inline fun logMessage(message: () -> String) { @@ -64,12 +64,16 @@ object TeamCity { message { "testStarted name='$testName'" } } - inline fun testMetadata(testName: String, name: String, value: Number) { + inline fun metadata(testName: String, name: String, value: Number) { message { "testMetadata testName='$testName' name='$name' type='number' value='$value'" } } + inline fun artifact(testName: String, name: String, artifactPath: String) { + message { "testMetadata testName='$testName' name='$name' type='artifact' value='$artifactPath'" } + } + inline fun testFinished(testName: String, durationMs: Long? = null) { - message { "testFinished name='$testName'${durationMs?.let { " duration='$durationMs'" }}" } + message { "testFinished name='$testName'${durationMs?.let { " duration='$durationMs'" } ?: ""}" } } fun testFailed(testName: String, error: Throwable) = testFailed(testName, toDetails(listOf(error))!!)