diff --git a/build-all.sh b/build-all.sh index 118e979..a3c4772 100755 --- a/build-all.sh +++ b/build-all.sh @@ -2,6 +2,8 @@ set -e +export PHOEBENCH_BUILD_RELEASE='true' + ./gradlew :clients:cli:shadowJar ./gradlew :clients:compose:createDistributable ./gradlew :clients:compose:wasmJsBrowserProductionWebpack diff --git a/clients/compose/build.gradle.kts b/clients/compose/build.gradle.kts index b5ed720..3ace54c 100644 --- a/clients/compose/build.gradle.kts +++ b/clients/compose/build.gradle.kts @@ -157,4 +157,25 @@ fun envValue(key: String): String? { } .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") + } + } } \ No newline at end of file diff --git a/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/Util.kt b/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/Util.kt index 98783ee..2a1a5e1 100644 --- a/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/Util.kt +++ b/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/Util.kt @@ -19,6 +19,7 @@ import kotlinx.datetime.format.Padding import kotlinx.datetime.format.char import kotlinx.datetime.toLocalDateTime import kotlin.math.absoluteValue +import kotlin.math.pow import kotlin.math.roundToInt import kotlin.random.Random import kotlin.random.nextInt @@ -137,4 +138,10 @@ fun List>.unzip(): Tuple4, List return l1 to l2 app l3 app l4 } -fun List.removeAt(idx: Int): List = subList(0, idx) + subList(idx + 1, size) \ No newline at end of file +fun List.removeAt(idx: Int): List = subList(0, idx) + subList(idx + 1, size) + +fun List.geomean(): Float { + var prod = 1.0f + for(value in this) prod *= value + return prod.pow(1.0f / size.toFloat()) +} \ No newline at end of file diff --git a/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/ui/ProjectView.kt b/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/ui/ProjectView.kt index a7aa118..f2371d9 100644 --- a/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/ui/ProjectView.kt +++ b/clients/compose/src/commonMain/kotlin/com/jaytux/phoebench/clients/ui/ProjectView.kt @@ -509,6 +509,8 @@ fun ProjectPlotArea(vm: ProjectVM, benchmark: ProjectVM.Benchmark) { val allInputs by vm.inputs 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 timeMin by remember { mutableStateOf(Instant.DISTANT_PAST) } var timeMax by remember { mutableStateOf(Instant.DISTANT_FUTURE) } @@ -587,21 +589,33 @@ fun ProjectPlotArea(vm: ProjectVM, benchmark: ProjectVM.Benchmark) { LaunchedEffect(filteredEntries, baseline, currentUnit) { var max = 0.0f baselineComparison = baseline?.let { bl -> - val perVersion = mutableMapOf>() + 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>() filteredEntries.forEach { entry -> val corrected = entry.measurements.map { entry.nativeUnit.convertTo(currentUnit, it) }.sum() - perVersion[entry.label] = perVersion[entry.label]?.let { - (previous, prCount) -> (previous + corrected) to (prCount + entry.measurements.size) - } ?: (corrected to entry.measurements.size.toFloat()) + perVersion.getOrPut(entry.label) { mutableMapOf() } + .getOrPut(entry.input) { MeanAccumulator() } + .add(corrected) } - val means = perVersion.mapValues { (_, v) -> v.first / v.second } - val baselineData = means[bl] ?: return@let null - means.mapNotNull { (ver, data) -> - val speedup = baselineData / data - max = maxOf(max, speedup) - ver.name to speedup app ver.uiColor app data + val subMeans = perVersion.mapValues { (_, v) -> v.mapValues { (_, acc) -> acc.mean() } } + val baseline = subMeans[bl] ?: return@let null + + val versionSpeedups = subMeans.mapValues { (_, v) -> + v.mapNotNull { (input, mean) -> + 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 } @@ -775,7 +789,7 @@ fun ProjectPlotArea(vm: ProjectVM, benchmark: ProjectVM.Benchmark) { item { Spacer(Modifier.height(10.dp)) } - items((allInputs intersect inputFilter.toSet()).toList()) { + items((visibleInputs intersect inputFilter.toSet()).toList()) { Row(Modifier.fillMaxWidth().clickable { if(inputFilter.size == allInputs.size) { 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 { if(inputFilter.size == allInputs.size) { inputFilter.clear() diff --git a/clients/compose/src/desktopMain/kotlin/com/jaytux/phoebench/clients/PlatformAPI.desktop.kt b/clients/compose/src/desktopMain/kotlin/com/jaytux/phoebench/clients/PlatformAPI.desktop.kt index d467460..22a1883 100644 --- a/clients/compose/src/desktopMain/kotlin/com/jaytux/phoebench/clients/PlatformAPI.desktop.kt +++ b/clients/compose/src/desktopMain/kotlin/com/jaytux/phoebench/clients/PlatformAPI.desktop.kt @@ -21,7 +21,7 @@ import kotlin.uuid.Uuid object JVMStore : IStore { private val json = Json - const val SERVICE = "com.jaytux.phoebench" + const val SERVICE = PersistenceConstants.SERVICE private class StoredProperty( val key: String,