Skip to content

Commit 372b6a1

Browse files
committed
zgc support
1 parent 438ceb2 commit 372b6a1

File tree

8 files changed

+181
-44
lines changed

8 files changed

+181
-44
lines changed

build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group = "io.github.cdsap"
9-
version = "0.1.3"
9+
version = "0.1.4"
1010

1111
java {
1212
toolchain {

src/main/kotlin/io/github/cdsap/kotlinprocess/ConsolidateProcesses.kt

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class ConsolidateProcesses {
2626
capacity = jStatData[it.key]?.capacity?.toGigsFromKb()!!,
2727
gcTime = jStatData[it.key]?.gcTime?.toMinutes()!!,
2828
uptime = jStatData[it.key]?.uptime?.toMinutes()!!,
29+
type = jStatData[it.key]?.typeGC!!
2930
)
3031
)
3132
}

src/main/kotlin/io/github/cdsap/kotlinprocess/model/Process.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ data class Process(
77
val usage: Double,
88
val capacity: Double,
99
val gcTime: Double,
10-
val uptime: Double
10+
val uptime: Double,
11+
val type: String
1112
)

src/main/kotlin/io/github/cdsap/kotlinprocess/model/ProcessJstat.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ data class ProcessJstat(
44
val usage: Double,
55
val capacity: Double,
66
val gcTime: Double,
7-
val uptime: Double
7+
val uptime: Double,
8+
val typeGC: String
89
)

src/main/kotlin/io/github/cdsap/kotlinprocess/output/BuildScanOutput.kt

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class BuildScanOutput(
3030
"Kotlin-Process-${it.pid}-gcTime",
3131
"${it.gcTime} minutes"
3232
)
33+
buildScanExtension.value(
34+
"Kotlin-Process-${it.pid}-gcType",
35+
it.type
36+
)
3337
}
3438
}
3539
}

src/main/kotlin/io/github/cdsap/kotlinprocess/output/ConsoleOutput.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ConsoleOutput(private val processes: List<Process>) {
1818
body {
1919
row {
2020
cell("Kotlin processes") {
21-
columnSpan = 6
21+
columnSpan = 7
2222
}
2323
}
2424
row {
@@ -27,6 +27,7 @@ class ConsoleOutput(private val processes: List<Process>) {
2727
cell("Usage")
2828
cell("Capacity")
2929
cell("GC Time")
30+
cell("GC Type")
3031
cell("Uptime")
3132
}
3233

@@ -37,6 +38,7 @@ class ConsoleOutput(private val processes: List<Process>) {
3738
cell("${it.usage} Gb")
3839
cell("${it.capacity} Gb")
3940
cell("${it.gcTime} minutes")
41+
cell(it.type)
4042
cell("${it.uptime} minutes")
4143
}
4244
}

src/main/kotlin/io/github/cdsap/kotlinprocess/parser/JStatData.kt

+98-27
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ class JStatData {
2222
val rawHeaders = lines[currentIndex].split("\\s+".toRegex()).filter { it != "" }
2323
val rawValues = lines[++currentIndex].split("\\s+".toRegex()).filter { it != "" }
2424

25-
val (headers, value) = removeConcurrentGCTimes(rawHeaders, rawValues)
25+
val typeOfCollector = getCollector(rawHeaders, rawValues)
26+
27+
val (headers, value) = preparePairsByCollector(typeOfCollector, rawHeaders, rawValues)
2628

2729
if (headers.size == value.size && checkValuesAraValid(value)) {
2830
val process = lines[++currentIndex].split("\\s+".toRegex())
@@ -35,39 +37,94 @@ class JStatData {
3537
aux++
3638
}
3739
processes[process.first()] = ProcessJstat(
38-
capacity = totalCapacity(jspMapValues),
39-
usage = usage(jspMapValues),
40+
capacity = totalCapacity(typeOfCollector, jspMapValues),
41+
usage = usage(typeOfCollector, jspMapValues),
4042
gcTime = gcTime(jspMapValues),
41-
uptime = uptime(jspMapValues)
43+
uptime = uptime(jspMapValues),
44+
typeGC = typeOfCollector.name
4245
)
4346

4447
}
4548
}
4649
return processes
4750
}
4851

49-
// When using ParallelGC argument concurrent gc times are not informed, generating an output like
50-
//Timestamp S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT
51-
// 298.0 22.0 20.0 0.0 0.0 1.0 1.8 1.0 0.9 4.0 8.3 6.0 5.0 4 0.3 4 0.7 - - 1
52-
// We need to remove the entries CGC and CGCT from the headers and values
53-
private fun removeConcurrentGCTimes(
52+
private fun getCollector(rawHeaders: List<String>, rawValues: List<String>): TypeCollector {
53+
val socHeaderPosition = rawHeaders.indexOf("S0C")
54+
val soc = rawValues[socHeaderPosition]
55+
if (soc == "-") {
56+
return TypeCollector.Z
57+
} else {
58+
val socCGC = rawHeaders.indexOf("CGC")
59+
val cgc = rawValues[socCGC]
60+
if (cgc == "-") {
61+
return TypeCollector.PARALLEL
62+
} else {
63+
return TypeCollector.G1
64+
}
65+
}
66+
}
67+
68+
private fun preparePairsByCollector(
69+
typeOfCollector: TypeCollector,
5470
rawHeaders: List<String>,
5571
rawValues: List<String>
5672
): Pair<List<String>, List<String>> {
57-
return if (rawHeaders.contains("CGC") && rawHeaders.contains("CGCT")
58-
&& rawHeaders.size == rawValues.size ) {
59-
val concurrentGCTime = rawHeaders.indexOf("CGC")
60-
val concurrentGCTimeTotal = rawHeaders.indexOf("CGCT")
61-
62-
val headers = rawHeaders.toMutableList()
63-
headers.removeAt(concurrentGCTime)
64-
headers.removeAt(concurrentGCTimeTotal - 1)
65-
val value = rawValues.toMutableList()
66-
value.removeAt(concurrentGCTime)
67-
value.removeAt(concurrentGCTimeTotal - 1)
68-
Pair(headers.toList(), value.toList())
69-
} else {
70-
Pair(rawHeaders, rawValues)
73+
when (typeOfCollector) {
74+
TypeCollector.G1 -> {
75+
return Pair(rawHeaders, rawValues)
76+
}
77+
78+
TypeCollector.PARALLEL -> {
79+
val concurrentGCTime = rawHeaders.indexOf("CGC")
80+
val concurrentGCTimeTotal = rawHeaders.indexOf("CGCT")
81+
82+
val headers = rawHeaders.toMutableList()
83+
headers.removeAt(concurrentGCTime)
84+
headers.removeAt(concurrentGCTimeTotal - 1)
85+
val value = rawValues.toMutableList()
86+
value.removeAt(concurrentGCTime)
87+
value.removeAt(concurrentGCTimeTotal - 1)
88+
return Pair(headers.toList(), value.toList())
89+
}
90+
91+
TypeCollector.Z -> {
92+
val soc = rawHeaders.indexOf("S0C")
93+
val s1c = rawHeaders.indexOf("S1C")
94+
val sou = rawHeaders.indexOf("S0U")
95+
val s1u = rawHeaders.indexOf("S1U")
96+
val ec = rawHeaders.indexOf("EC")
97+
val eu = rawHeaders.indexOf("EU")
98+
val ygc = rawHeaders.indexOf("YGC")
99+
val ygct = rawHeaders.indexOf("YGCT")
100+
val fgc = rawHeaders.indexOf("FGC")
101+
val fgct = rawHeaders.indexOf("FGCT")
102+
103+
val headers = rawHeaders.toMutableList()
104+
headers.removeAt(soc)
105+
headers.removeAt(s1c - 1)
106+
headers.removeAt(sou - 2)
107+
headers.removeAt(s1u - 3)
108+
headers.removeAt(ec - 4)
109+
headers.removeAt(eu - 5)
110+
headers.removeAt(ygc - 6)
111+
headers.removeAt(ygct - 7)
112+
headers.removeAt(fgc - 8)
113+
headers.removeAt(fgct - 9)
114+
115+
val value = rawValues.toMutableList()
116+
value.removeAt(soc)
117+
value.removeAt(s1c - 1)
118+
value.removeAt(sou - 2)
119+
value.removeAt(s1u - 3)
120+
value.removeAt(ec - 4)
121+
value.removeAt(eu - 5)
122+
value.removeAt(ygc - 6)
123+
value.removeAt(ygct - 7)
124+
value.removeAt(fgc - 8)
125+
value.removeAt(fgct - 9)
126+
return Pair(headers.toList(), value.toList())
127+
}
71128
}
72129
}
73130

@@ -82,12 +139,20 @@ class JStatData {
82139
return true
83140
}
84141

85-
private fun totalCapacity(jspMapValues: Map<String, Double>): Double {
86-
return jspMapValues["EC"]!! + jspMapValues["OC"]!! + jspMapValues["S0C"]!! + jspMapValues["S1C"]!!
142+
private fun totalCapacity(typeOfCollector: TypeCollector, jspMapValues: Map<String, Double>): Double {
143+
if(typeOfCollector == TypeCollector.Z) {
144+
return jspMapValues["OC"]!! + jspMapValues["MC"]!!
145+
} else {
146+
return jspMapValues["EC"]!! + jspMapValues["OC"]!! + jspMapValues["S0C"]!! + jspMapValues["S1C"]!!
147+
}
87148
}
88149

89-
private fun usage(jspMapValues: Map<String, Double>): Double {
90-
return jspMapValues["S0U"]!! + jspMapValues["S1U"]!! + jspMapValues["EU"]!! + jspMapValues["OU"]!!
150+
private fun usage(typeOfCollector: TypeCollector, jspMapValues: Map<String, Double>): Double {
151+
if(typeOfCollector == TypeCollector.Z) {
152+
return jspMapValues["OU"]!! + jspMapValues["MU"]!!
153+
} else {
154+
return jspMapValues["S0U"]!! + jspMapValues["S1U"]!! + jspMapValues["EU"]!! + jspMapValues["OU"]!!
155+
}
91156
}
92157

93158
private fun gcTime(jspMapValues: Map<String, Double>): Double {
@@ -98,3 +163,9 @@ class JStatData {
98163
return jspMapValues["Timestamp"]!!
99164
}
100165
}
166+
167+
enum class TypeCollector {
168+
G1,
169+
PARALLEL,
170+
Z
171+
}

src/test/kotlin/io/github/cdsap/kotlinprocess/InfoKotlinProcessPluginTest.kt

+70-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.github.cdsap.kotlinprocess
33
import junit.framework.TestCase.assertTrue
44
import org.gradle.testkit.runner.BuildResult
55
import org.gradle.testkit.runner.GradleRunner
6+
import org.junit.Assume
67
import org.junit.Rule
78
import org.junit.Test
89
import org.junit.rules.TemporaryFolder
@@ -31,7 +32,7 @@ class InfoKotlinProcessPluginTest {
3132
fun testPluginIsCompatibleWithConfigurationCacheWithoutGradleEnterprise() {
3233
createBuildGradle()
3334

34-
gradleVersions.forEach {
35+
gradleVersions.forEach {
3536
val firstBuild = GradleRunner.create()
3637
.withProjectDir(testProjectDir.root)
3738
.withArguments("compileKotlin", "--configuration-cache")
@@ -52,9 +53,12 @@ class InfoKotlinProcessPluginTest {
5253

5354
@Test
5455
fun testOutputIsGeneratedWhenPluginIsAppliedWithJvmArgs() {
55-
testProjectDir.newFile("gradle.properties").appendText("""
56+
testProjectDir.newFile("gradle.properties").writeText(
57+
"""
5658
org.gradle.jvmargs=-Xmx256m -Dfile.encoding=UTF-8
57-
""".trimIndent())
59+
""".trimIndent()
60+
)
61+
5862
createBuildGradle()
5963
createKotlinClass()
6064

@@ -66,10 +70,12 @@ class InfoKotlinProcessPluginTest {
6670

6771
@Test
6872
fun testOutputIsGeneratedWhenPluginIsAppliedWithJvmArgsAndKotlinJvm() {
69-
testProjectDir.newFile("gradle.properties").appendText("""
73+
testProjectDir.newFile("gradle.properties").writeText(
74+
"""
7075
org.gradle.jvmargs=-Xmx256m -Dfile.encoding=UTF-8
7176
kotlin.daemon.jvmargs=-Xmx128m
72-
""".trimIndent())
77+
""".trimIndent()
78+
)
7379
createBuildGradle()
7480
createKotlinClass()
7581

@@ -81,10 +87,12 @@ class InfoKotlinProcessPluginTest {
8187

8288
@Test
8389
fun testOutputIsGeneratedWhenPluginIsAppliedWithJvmArgsAndKotlinGCJvm() {
84-
testProjectDir.newFile("gradle.properties").appendText("""
90+
testProjectDir.newFile("gradle.properties").writeText(
91+
"""
8592
org.gradle.jvmargs=-Xmx256m -Dfile.encoding=UTF-8
8693
kotlin.daemon.jvmargs=-Xmx128m -XX:+UseParallelGC
87-
""".trimIndent())
94+
""".trimIndent()
95+
)
8896
createBuildGradle()
8997
createKotlinClass()
9098

@@ -96,30 +104,58 @@ class InfoKotlinProcessPluginTest {
96104

97105
@Test
98106
fun testOutputIsGeneratedWhenPluginIsAppliedWithJvmGCArgsAndKotlinJvm() {
99-
testProjectDir.newFile("gradle.properties").appendText("""
107+
testProjectDir.newFile("gradle.properties").writeText(
108+
"""
100109
org.gradle.jvmargs=-Xmx256m -XX:+UseParallelGC -Dfile.encoding=UTF-8
101-
""".trimIndent())
110+
""".trimIndent()
111+
)
102112
createBuildGradle()
103113
createKotlinClass()
104114

105115
gradleVersions.forEach {
106116
val build = simpleKotlinCompileBuild(it)
107117
assertTerminalOutput(build)
118+
assertTrue(build.output.contains("G1"))
108119
}
109120
}
110121

111122
@Test
112123
fun testOutputIsGeneratedWhenPluginIsAppliedWithJvmGCArgsAndKotlinGCJvm() {
113-
testProjectDir.newFile("gradle.properties").appendText("""
114-
org.gradle.jvmargs=-Xmx256m -XX:+UseParallelGC -Dfile.encoding=UTF-8
115-
kotlin.daemon.jvmargs=-Xmx128m -XX:+UseParallelGC
116-
""".trimIndent())
124+
testProjectDir.newFile("gradle.properties").writeText(
125+
"""
126+
org.gradle.jvmargs=-Xmx258m -XX:+UseParallelGC -Dfile.encoding=UTF-8
127+
kotlin.daemon.jvmargs=-Xmx600m -XX:+UseParallelGC
128+
""".trimIndent()
129+
)
117130
createBuildGradle()
118131
createKotlinClass()
119132

120133
gradleVersions.forEach {
121134
val build = simpleKotlinCompileBuild(it)
122135
assertTerminalOutput(build)
136+
assertTrue(build.output.contains("PARALLEL"))
137+
}
138+
}
139+
140+
@Test
141+
fun testOutputIsGeneratedWhenPluginIsAppliedWithJvmGCArgsAndKotlinZ1Jvm() {
142+
Assume.assumeTrue(Runtime.version().feature() >= 15)
143+
144+
testProjectDir.newFile("gradle.properties").writeText(
145+
"""
146+
org.gradle.jvmargs=-Xmx256m -XX:+UseParallelGC -Dfile.encoding=UTF-8
147+
kotlin.daemon.jvmargs=-Xmx750m -XX:+UnlockExperimentalVMOptions -XX:+UseZGC
148+
""".trimIndent()
149+
)
150+
151+
createBuildGradle17()
152+
createKotlinClass()
153+
154+
gradleVersions.forEach {
155+
val build = simpleKotlinCompileBuild(it)
156+
assertTerminalOutput(build)
157+
assertTrue(build.output.contains("Z"))
158+
123159
}
124160
}
125161

@@ -152,6 +188,27 @@ class InfoKotlinProcessPluginTest {
152188
repositories {
153189
mavenCentral()
154190
}
191+
192+
""".trimIndent()
193+
)
194+
}
195+
196+
private fun createBuildGradle17() {
197+
testProjectDir.newFile("build.gradle").appendText(
198+
"""
199+
plugins {
200+
id 'org.jetbrains.kotlin.jvm' version '1.7.21'
201+
id 'application'
202+
id 'io.github.cdsap.kotlinprocess'
203+
}
204+
repositories {
205+
mavenCentral()
206+
}
207+
java {
208+
toolchain {
209+
languageVersion = JavaLanguageVersion.of(17)
210+
}
211+
}
155212
""".trimIndent()
156213
)
157214
}

0 commit comments

Comments
 (0)