Perf: implemented many attempts computation
Mean and standard deviation are computed as result
This commit is contained in:
@@ -96,33 +96,47 @@ task bench(type:DefaultTask) {
|
|||||||
def average = "none"
|
def average = "none"
|
||||||
def absoluteAverage = "none"
|
def absoluteAverage = "none"
|
||||||
jvmReport.report
|
jvmReport.report
|
||||||
.sort { konanReport.report[it.key] / it.value }
|
.sort { konanReport.report[it.key].mean / it.value.mean }
|
||||||
.each { k, v ->
|
.each { k, v ->
|
||||||
def konanValue = konanReport.report[k]
|
def konanValue = konanReport.report[k]
|
||||||
def ratio = String.format('%.2f', konanValue / v)
|
def ratio = konanValue.mean / v.mean
|
||||||
def formattedKonanValue = String.format('%.2f', konanValue / 1000)
|
def minRatio = (konanValue.mean - konanValue.stdDev) / (v.mean + v.stdDev)
|
||||||
|
def maxRatio = (konanValue.mean + konanValue.stdDev) / (v.mean - v.stdDev)
|
||||||
|
def ratioStdDev = Math.min(Math.abs(minRatio - ratio), Math.abs(maxRatio - ratio))
|
||||||
|
def formattedKonanValue = String.format('%.4f us +- %.4f us', konanValue.mean / 1000, konanValue.stdDev / 1000)
|
||||||
|
def formattedRatio = String.format('%.2f +- %.2f', ratio, ratioStdDev)
|
||||||
if (k == 'RingAverage') {
|
if (k == 'RingAverage') {
|
||||||
average = ratio
|
average = formattedRatio
|
||||||
absoluteAverage = formattedKonanValue
|
absoluteAverage = formattedKonanValue
|
||||||
|
} else {
|
||||||
|
println("$k : absolute = $formattedKonanValue, ratio = $formattedRatio")
|
||||||
}
|
}
|
||||||
println("$k : absolute = $formattedKonanValue us, ratio = $ratio")
|
|
||||||
if (System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") != null)
|
if (System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") != null)
|
||||||
println("##teamcity[buildStatisticValue key='$k' value='$ratio']")
|
println("##teamcity[buildStatisticValue key='$k' value='$ratio']")
|
||||||
}
|
}
|
||||||
|
|
||||||
println()
|
println()
|
||||||
println("Average Ring score: absolute = $absoluteAverage us, ratio = $average")
|
println("Average Ring score: absolute = $absoluteAverage, ratio = $average")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Results {
|
||||||
|
def Double mean
|
||||||
|
def Double stdDev
|
||||||
|
|
||||||
|
Results(Double mean, Double stdDev) {
|
||||||
|
this.mean = mean
|
||||||
|
this.stdDev = stdDev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Report {
|
class Report {
|
||||||
def Map<String, Double> report = new TreeMap()
|
def Map<String, Results> report = new TreeMap()
|
||||||
|
|
||||||
Report(File path) {
|
Report(File path) {
|
||||||
path.readLines().drop(3).findAll { it.split(':').length == 2 }.each {
|
path.readLines().drop(3).findAll { it.split(':').length == 3 }.each {
|
||||||
def p = it.split(':')
|
def p = it.split(':')
|
||||||
report.put(p[0].trim(), Double.parseDouble(p[1].trim()))
|
report.put(p[0].trim(), new Results(Double.parseDouble(p[1].trim()), Double.parseDouble(p[2].trim())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ val BENCHMARK_SIZE = 100
|
|||||||
//-----------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------//
|
||||||
|
|
||||||
class Launcher(val numWarmIterations: Int) {
|
class Launcher(val numWarmIterations: Int) {
|
||||||
val results = mutableMapOf<String, Long>()
|
class Results(val mean: Double, val variance: Double)
|
||||||
|
|
||||||
fun launch(benchmark: () -> Any?): Long { // If benchmark runs too long - use coeff to speed it up.
|
val results = mutableMapOf<String, Results>()
|
||||||
|
|
||||||
|
fun launch(benchmark: () -> Any?): Results { // If benchmark runs too long - use coeff to speed it up.
|
||||||
var i = numWarmIterations
|
var i = numWarmIterations
|
||||||
|
|
||||||
while (i-- > 0) benchmark()
|
while (i-- > 0) benchmark()
|
||||||
@@ -41,20 +43,27 @@ class Launcher(val numWarmIterations: Int) {
|
|||||||
}
|
}
|
||||||
cleanup()
|
cleanup()
|
||||||
}
|
}
|
||||||
if (time >= 200L * 1_000_000) // 200ms
|
if (time >= 100L * 1_000_000) // 100ms
|
||||||
break
|
break
|
||||||
autoEvaluatedNumberOfMeasureIteration *= 2
|
autoEvaluatedNumberOfMeasureIteration *= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
i = autoEvaluatedNumberOfMeasureIteration
|
val attempts = 10
|
||||||
val time = measureNanoTime {
|
val samples = DoubleArray(attempts)
|
||||||
while (i-- > 0) {
|
for (k in samples.indices) {
|
||||||
benchmark()
|
i = autoEvaluatedNumberOfMeasureIteration
|
||||||
|
val time = measureNanoTime {
|
||||||
|
while (i-- > 0) {
|
||||||
|
benchmark()
|
||||||
|
}
|
||||||
|
cleanup()
|
||||||
}
|
}
|
||||||
cleanup()
|
samples[k] = time * 1.0 / autoEvaluatedNumberOfMeasureIteration
|
||||||
}
|
}
|
||||||
|
val mean = samples.sum() / attempts
|
||||||
|
val variance = samples.indices.sumByDouble { (samples[it] - mean) * (samples[it] - mean) } / attempts
|
||||||
|
|
||||||
return time / autoEvaluatedNumberOfMeasureIteration
|
return Results(mean, variance)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -101,17 +110,18 @@ class Launcher(val numWarmIterations: Int) {
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun printResultsNormalized() {
|
fun printResultsNormalized() {
|
||||||
var total = 0.0
|
var totalMean = 0.0
|
||||||
|
var totalVariance = 0.0
|
||||||
results.asSequence().sortedBy { it.key }.forEach {
|
results.asSequence().sortedBy { it.key }.forEach {
|
||||||
val norma = it.value.toDouble()
|
|
||||||
val niceName = it.key.padEnd(50, ' ')
|
val niceName = it.key.padEnd(50, ' ')
|
||||||
val niceNorma = norma.toString(9)
|
println("$niceName : ${it.value.mean.toString(9)} : ${kotlin.math.sqrt(it.value.variance).toString(9)}")
|
||||||
println("$niceName : $niceNorma")
|
|
||||||
|
|
||||||
total += norma
|
totalMean += it.value.mean
|
||||||
|
totalVariance += it.value.variance
|
||||||
}
|
}
|
||||||
val average = total / results.size
|
val averageMean = totalMean / results.size
|
||||||
println("\nRingAverage: ${average.toString(9)}")
|
val averageStdDev = kotlin.math.sqrt(totalVariance) / results.size
|
||||||
|
println("\nRingAverage: ${averageMean.toString(9)} : ${averageStdDev.toString(9)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|||||||
Reference in New Issue
Block a user