@@ -2,14 +2,12 @@ package ch.uzh.ifi.seal.bencher.analysis.coverage.dyn
2
2
3
3
import arrow.core.Either
4
4
import arrow.core.getOrElse
5
- import ch.uzh.ifi.seal.bencher.Benchmark
6
- import ch.uzh.ifi.seal.bencher.Method
5
+ import ch.uzh.ifi.seal.bencher.*
7
6
import ch.uzh.ifi.seal.bencher.analysis.JarHelper
8
7
import ch.uzh.ifi.seal.bencher.analysis.coverage.CoverageExecutor
9
8
import ch.uzh.ifi.seal.bencher.analysis.coverage.Coverages
10
9
import ch.uzh.ifi.seal.bencher.analysis.coverage.computation.*
11
10
import ch.uzh.ifi.seal.bencher.analysis.finder.MethodFinder
12
- import ch.uzh.ifi.seal.bencher.runCommand
13
11
import org.apache.logging.log4j.LogManager
14
12
import org.apache.logging.log4j.Logger
15
13
import java.io.File
@@ -22,10 +20,13 @@ import java.time.LocalDateTime
22
20
23
21
abstract class AbstractDynamicCoverage (
24
22
private val benchmarkFinder : MethodFinder <Benchmark >,
23
+ private val javaSettings : JavaSettings ,
25
24
private val oneCoverageForParameterizedBenchmarks : Boolean = true ,
26
- private val timeOut : Duration = Duration .ofMinutes(10)
25
+ private val timeOut : Duration = Duration .ofMinutes(10),
27
26
) : CoverageExecutor {
28
27
28
+ private val env: Map <String , String > = mapOfNotNull(javaSettings.homePair())
29
+
29
30
override fun get (jar : Path ): Either <String , Coverages > {
30
31
val ebs = benchmarkFinder.all()
31
32
val bs: List <Benchmark > = ebs.getOrElse {
@@ -54,7 +55,7 @@ abstract class AbstractDynamicCoverage(
54
55
private fun coverages (jar : Path , b : Benchmark ): Either <String , List <Pair <Benchmark , Coverage >>> {
55
56
val bs = b.parameterizedBenchmarks()
56
57
57
- val p = Files .createTempDirectory(tmpDirPrefix )
58
+ val p = Files .createTempDirectory(TMP_DIR_PREFIX )
58
59
val tmpDir = File (p.toUri())
59
60
60
61
val total = bs.size
@@ -80,35 +81,37 @@ abstract class AbstractDynamicCoverage(
80
81
}
81
82
82
83
private fun replaceFrom (b : Benchmark , rs : Coverage ): Coverage =
83
- b.toPlainMethod().let { pb ->
84
- Coverage (
85
- of = b,
86
- unitResults = rs.all().mapNotNull {
87
- when (it) {
88
- is NotCovered -> null
89
- is PossiblyCovered -> CUF .possiblyCovered(
90
- of = pb,
91
- unit = it.unit,
92
- level = it.level,
93
- probability = it.probability
94
- )
95
- is Covered -> CUF .covered(
96
- of = pb,
97
- unit = it.unit,
98
- level = it.level
99
- )
100
- }
101
- }.toSet()
102
- )
103
- }
84
+ b.toPlainMethod().let { pb ->
85
+ Coverage (
86
+ of = b,
87
+ unitResults = rs.all().mapNotNull {
88
+ when (it) {
89
+ is NotCovered -> null
90
+ is PossiblyCovered -> CUF .possiblyCovered(
91
+ of = pb,
92
+ unit = it.unit,
93
+ level = it.level,
94
+ probability = it.probability,
95
+ )
96
+ is Covered -> CUF .covered(
97
+ of = pb,
98
+ unit = it.unit,
99
+ level = it.level,
100
+ )
101
+ }
102
+ }.toSet(),
103
+ )
104
+ }
104
105
105
106
private fun coverageBench (jar : Path , i : Int , total : Int , tmpDir : File , b : Benchmark ): Pair <Benchmark , Coverage >? {
106
107
val cs = cmdStr(jar, b)
107
108
109
+ log.info(cs)
110
+
108
111
log.debug(" Param bench $b : ${i + 1 } /$total ; '$cs '" )
109
112
110
113
val l = logTimesParam(b, i, total, " coverage for parameterized benchmark" )
111
- val ers = exec(cs, jar, tmpDir, b)
114
+ val ers = exec(cs, env, jar, tmpDir, b)
112
115
return try {
113
116
ers
114
117
.mapLeft {
@@ -125,14 +128,14 @@ abstract class AbstractDynamicCoverage(
125
128
}
126
129
127
130
private fun coverageParam (jar : Path , total : Int , tmpDir : File , bs : List <Benchmark >): List <Pair <Benchmark , Coverage >> =
128
- bs.mapIndexedNotNull { i, pb -> coverageBench(jar, i, total, tmpDir, pb) }
131
+ bs.mapIndexedNotNull { i, pb -> coverageBench(jar, i, total, tmpDir, pb) }
129
132
130
133
private fun logTimesParam (b : Benchmark , i : Int , total : Int , text : String ): () -> Unit =
131
- if (total <= 1 ) {
132
- {}
133
- } else {
134
- logTimes(b, i, total, text)
135
- }
134
+ if (total <= 1 ) {
135
+ {}
136
+ } else {
137
+ logTimes(b, i, total, text)
138
+ }
136
139
137
140
private fun logTimes (b : Benchmark , i : Int , total : Int , text : String ): () -> Unit {
138
141
log.info(" start $text $b (${i + 1 } /$total )" )
@@ -143,17 +146,17 @@ abstract class AbstractDynamicCoverage(
143
146
}
144
147
}
145
148
146
- private fun exec (cmd : String , jar : Path , dir : File , b : Benchmark ): Either <String , Coverage > {
147
- val (ok, out , err) = cmd.runCommand(dir, timeOut)
149
+ private fun exec (cmd : String , env : Map < String , String >, jar : Path , dir : File , b : Benchmark ): Either <String , Coverage > {
150
+ val (ok, out , err) = cmd.runCommand(dir, timeOut, env )
148
151
if (! ok) {
149
152
return Either .Left (" Execution of '$cmd ' did not finish within $timeOut " )
150
153
}
151
154
152
- if (out != null && out .isNotBlank ()) {
155
+ if (! out .isNullOrBlank ()) {
153
156
log.debug(" Process out: $out " )
154
157
}
155
158
156
- if (err != null && err.isNotBlank ()) {
159
+ if (! err.isNullOrBlank ()) {
157
160
log.debug(" Process err: $err " )
158
161
}
159
162
@@ -215,15 +218,45 @@ abstract class AbstractDynamicCoverage(
215
218
}
216
219
}
217
220
218
- private fun cmdStr (jar : Path , b : Benchmark ): String =
219
- if (b.jmhParams.isEmpty()) {
220
- String .format(cmd, jar, jvmArgs(b), benchName(b))
221
- } else {
222
- String .format(cmdParam, jar, jvmArgs(b), jmhParams(b), benchName(b))
223
- }
221
+ // For use in shell (e.g., bash) the constructed command string needs escaping of
222
+ // (1) dollar-signs ($) and
223
+ // (2) double-quotes (")
224
+ // around the -jvmArgs argument and the JMH benchmark regex
225
+ private fun cmdStr (jar : Path , b : Benchmark ): String {
226
+ val cmdList = mutableListOf<String >()
227
+ // java
228
+ cmdList.add(JAVA_CMD )
229
+
230
+ // JVM arguments to java command
231
+ javaSettings.jvmArgs?.let { cmdList.add(it) }
232
+
233
+ // -jar jar
234
+ cmdList.add(JAR_ARG )
235
+ cmdList.add(jar.toString())
236
+
237
+ // -jvmArgs=jvmArgs(b)
238
+ val jmhJvmArgs = jvmArgs(b)
239
+ javaSettings.jvmArgs?.let { cmdList.add(String .format(JMH_JVM_ARGS , it)) } // add JVM arguments also to JMH fork JVMs
240
+ if (jmhJvmArgs.isNotEmpty()) {
241
+ cmdList.add(String .format(JMH_JVM_ARGS , jmhJvmArgs))
242
+ }
243
+
244
+ // benchmark parameters
245
+ if (b.jmhParams.isNotEmpty()) {
246
+ cmdList.add(jmhParams(b))
247
+ }
248
+
249
+ // benchmark
250
+ cmdList.add(String .format(JMH_BENCH , benchName(b)))
251
+
252
+ // JMH arguments
253
+ cmdList.add(JMH_ARGS )
254
+
255
+ return cmdList.joinToString(" " )
256
+ }
224
257
225
258
private fun jmhParams (b : Benchmark ): String =
226
- b.jmhParams.joinToString(separator = " " ) { " -p ${it.first} =${it.second} " }
259
+ b.jmhParams.joinToString(separator = " " ) { " -p ${it.first} =${it.second} " }
227
260
228
261
private fun benchName (b : Benchmark ): String = " ${b.clazz.replace(" $" , " ." )} .${b.name} "
229
262
@@ -237,21 +270,14 @@ abstract class AbstractDynamicCoverage(
237
270
238
271
239
272
companion object {
240
- val log: Logger = LogManager .getLogger(AbstractDynamicCoverage ::class .java.canonicalName)
241
-
242
- // arguments:
243
- // For use in shell (e.g., bash) the constructed command string needs escaping of
244
- // (1) dollar-signs ($) and
245
- // (2) double-quotes (")
246
- // around the -jvmArgs argument and the JMH benchmark regex
247
- // 1. benchmark jar path
248
- // 2. JVM args string
249
- // 3. JMH parameter string (required for cmdParam and optional for cmd)
250
- // 4. JMH benchmark
251
- private const val baseCmd = " java -jar %s -jvmArgs=%s -bm ss -wi 0 -i 1 -f 1 -r 1 -w 1"
252
- private const val cmd = " $baseCmd ^%s\$ "
253
- private const val cmdParam = " $baseCmd %s ^%s\$ "
254
-
255
- private const val tmpDirPrefix = " bencher-dyn-cov-"
273
+ private val log: Logger = LogManager .getLogger(AbstractDynamicCoverage ::class .java.canonicalName)
274
+
275
+ private const val JAVA_CMD = " java"
276
+ private const val JAR_ARG = " -jar"
277
+ private const val JMH_JVM_ARGS = " -jvmArgs=%s"
278
+ private const val JMH_ARGS = " -bm ss -wi 0 -i 1 -f 1 -r 1 -w 1"
279
+ private const val JMH_BENCH = " ^%s\$ "
280
+
281
+ private const val TMP_DIR_PREFIX = " bencher-dyn-cov-"
256
282
}
257
283
}
0 commit comments