Schema update (organising benchmarks within projects)

This commit is contained in:
2026-08-27 13:22:46 +02:00
parent 4fdeafb73b
commit 0d3f5ca8ad
5 changed files with 58 additions and 14 deletions
+2
View File
@@ -2,6 +2,8 @@
set -e set -e
export PHOEBENCH_BUILD_RELEASE='true'
./gradlew :clients:cli:shadowJar ./gradlew :clients:cli:shadowJar
./gradlew :clients:compose:createDistributable ./gradlew :clients:compose:createDistributable
./gradlew :clients:compose:wasmJsBrowserProductionWebpack ./gradlew :clients:compose:wasmJsBrowserProductionWebpack
+21
View File
@@ -157,4 +157,25 @@ fun envValue(key: String): String? {
} }
.firstOrNull { it.first == key }?.second .firstOrNull { it.first == key }?.second
} }
}
buildConfig {
generateAtSync = false
useKotlinOutput { internalVisibility = false }
println("Source sets: ${kotlin.sourceSets.toList().map { it.name }}")
sourceSets.named("desktopMain") {
println("Generating 'desktopMain'")
className("PersistenceConstants")
packageName("com.jaytux.phoebench.clients")
envValue("PHOEBENCH_BUILD_RELEASE")?.let {
println("Using release desktop service")
buildConfigField("SERVICE", "com.jaytux.phoebench")
} ?: run {
println("Using debug desktop service")
buildConfigField("SERVICE", "com.jaytux.phoebench.debug")
}
}
} }
@@ -19,6 +19,7 @@ import kotlinx.datetime.format.Padding
import kotlinx.datetime.format.char import kotlinx.datetime.format.char
import kotlinx.datetime.toLocalDateTime import kotlinx.datetime.toLocalDateTime
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.math.pow
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.nextInt import kotlin.random.nextInt
@@ -137,4 +138,10 @@ fun <T1, T2, T3, T4> List<Tuple4<T1, T2, T3, T4>>.unzip(): Tuple4<List<T1>, List
return l1 to l2 app l3 app l4 return l1 to l2 app l3 app l4
} }
fun <T> List<T>.removeAt(idx: Int): List<T> = subList(0, idx) + subList(idx + 1, size) fun <T> List<T>.removeAt(idx: Int): List<T> = subList(0, idx) + subList(idx + 1, size)
fun List<Float>.geomean(): Float {
var prod = 1.0f
for(value in this) prod *= value
return prod.pow(1.0f / size.toFloat())
}
@@ -509,6 +509,8 @@ fun ProjectPlotArea(vm: ProjectVM, benchmark: ProjectVM.Benchmark) {
val allInputs by vm.inputs val allInputs by vm.inputs
val allHardware by vm.hardware val allHardware by vm.hardware
val visibleInputs by remember(entries, allInputs) { mutableStateOf(allInputs intersect entries.map { it.input }.toSet()) }
var filteredEntries by remember { mutableStateOf(entries) } var filteredEntries by remember { mutableStateOf(entries) }
var timeMin by remember { mutableStateOf(Instant.DISTANT_PAST) } var timeMin by remember { mutableStateOf(Instant.DISTANT_PAST) }
var timeMax by remember { mutableStateOf(Instant.DISTANT_FUTURE) } var timeMax by remember { mutableStateOf(Instant.DISTANT_FUTURE) }
@@ -587,21 +589,33 @@ fun ProjectPlotArea(vm: ProjectVM, benchmark: ProjectVM.Benchmark) {
LaunchedEffect(filteredEntries, baseline, currentUnit) { LaunchedEffect(filteredEntries, baseline, currentUnit) {
var max = 0.0f var max = 0.0f
baselineComparison = baseline?.let { bl -> baselineComparison = baseline?.let { bl ->
val perVersion = mutableMapOf<ProjectVM.Version, Pair<Float, Float>>() class MeanAccumulator(var sum: Float = 0.0f, var count: Float = 0.0f) {
fun add(f: Float) { sum += f; count += 1.0f }
fun mean() = if(count == 0.0f) 0.0f else sum / count
}
val perVersion = mutableMapOf<ProjectVM.Version, MutableMap<String, MeanAccumulator>>()
filteredEntries.forEach { entry -> filteredEntries.forEach { entry ->
val corrected = entry.measurements.map { entry.nativeUnit.convertTo(currentUnit, it) }.sum() val corrected = entry.measurements.map { entry.nativeUnit.convertTo(currentUnit, it) }.sum()
perVersion[entry.label] = perVersion[entry.label]?.let { perVersion.getOrPut(entry.label) { mutableMapOf() }
(previous, prCount) -> (previous + corrected) to (prCount + entry.measurements.size) .getOrPut(entry.input) { MeanAccumulator() }
} ?: (corrected to entry.measurements.size.toFloat()) .add(corrected)
} }
val means = perVersion.mapValues { (_, v) -> v.first / v.second } val subMeans = perVersion.mapValues { (_, v) -> v.mapValues { (_, acc) -> acc.mean() } }
val baselineData = means[bl] ?: return@let null val baseline = subMeans[bl] ?: return@let null
means.mapNotNull { (ver, data) ->
val speedup = baselineData / data val versionSpeedups = subMeans.mapValues { (_, v) ->
max = maxOf(max, speedup) v.mapNotNull { (input, mean) ->
ver.name to speedup app ver.uiColor app data val base = baseline[input] ?: return@mapNotNull null
(base / mean) to mean
}
} }
versionSpeedups.mapNotNull { (version, inputMeans) ->
val speedup = inputMeans.map { it.first }.geomean()
max = maxOf(max, speedup)
version.name to speedup app version.uiColor app inputMeans.map { it.second }.geomean()
}.sortedBy { it.t1 }
} }
baselineMax = max baselineMax = max
} }
@@ -775,7 +789,7 @@ fun ProjectPlotArea(vm: ProjectVM, benchmark: ProjectVM.Benchmark) {
item { Spacer(Modifier.height(10.dp)) } item { Spacer(Modifier.height(10.dp)) }
items((allInputs intersect inputFilter.toSet()).toList()) { items((visibleInputs intersect inputFilter.toSet()).toList()) {
Row(Modifier.fillMaxWidth().clickable { Row(Modifier.fillMaxWidth().clickable {
if(inputFilter.size == allInputs.size) { if(inputFilter.size == allInputs.size) {
inputFilter.clear() inputFilter.clear()
@@ -795,7 +809,7 @@ fun ProjectPlotArea(vm: ProjectVM, benchmark: ProjectVM.Benchmark) {
} }
} }
items((allInputs - inputFilter.toSet()).toList()) { items((visibleInputs - inputFilter.toSet()).toList()) {
Row(Modifier.fillMaxWidth().clickable { Row(Modifier.fillMaxWidth().clickable {
if(inputFilter.size == allInputs.size) { if(inputFilter.size == allInputs.size) {
inputFilter.clear() inputFilter.clear()
@@ -21,7 +21,7 @@ import kotlin.uuid.Uuid
object JVMStore : IStore { object JVMStore : IStore {
private val json = Json private val json = Json
const val SERVICE = "com.jaytux.phoebench" const val SERVICE = PersistenceConstants.SERVICE
private class StoredProperty<T>( private class StoredProperty<T>(
val key: String, val key: String,