KMPCharts/chart-realtime/build.gradle.kts
Trentin Davide 0e3360e4a0 perf(chart-realtime): cut per-frame render CPU on realtime chart
Profiling (Pixel 7 + SM-T819) showed the chart CPU-bound in Skia
analytic-AA path fill plus a full-buffer copy on every frame.

- LineSignalRenderer: draw the signal polyline with anti-aliasing off,
  via a cached common Paint + drawIntoCanvas (KMP-safe, no nativeCanvas).
  Flips Skia from CPU coverage-mask raster to GPU tessellation;
  configured strokeWidth still honored. Removes the old Stroke cache.
- TieredBuffer/CircularBuffer: replace the full ~60k-sample copy+scan in
  the draw hot path with an O(log n) bisect window read (copyWindow).
  Output byte-identical (equivalence tests incl. ring-wrap + edges).
- RealtimeChart: split the single Canvas into a cold layer (Y-axis line,
  grid, labels) and a hot layer (signal, X-axis, crosshair) so per-frame
  TextMeasurer layout stops running every frame. Y range stabilized to
  the tick grid and shared by both layers (signal never clips).
- minSdk 26 -> 24.

Renderer unit test moved commonTest -> iosTest (Compose Paint delegates
to a non-mockable android.graphics.Paint stub on the JVM host; Skiko
backs it for real). Verified on SM-T819 (release): frame time 150ms ->
48ms, ~10 -> ~31 fps at full 8x200 Hz load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:39:00 +02:00

99 lines
2.6 KiB
Kotlin

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.android.library)
alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.compose.compiler)
`maven-publish`
}
group = "dev.dtrentin"
version = "0.5.0-SNAPSHOT"
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler_reports")
metricsDestination = layout.buildDirectory.dir("compose_compiler_metrics")
}
kotlin {
applyDefaultHierarchyTemplate()
explicitApi()
androidTarget {
compilations.all {
compileTaskProvider.configure {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
}
}
}
publishLibraryVariants("release")
}
val xcf = XCFramework("ChartRealtime")
listOf(
iosArm64(),
iosSimulatorArm64()
).forEach { target ->
target.binaries.framework {
baseName = "ChartRealtime"
xcf.add(this)
}
}
sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.ui)
implementation(compose.foundation)
implementation(compose.material3)
implementation(libs.coroutines.core)
}
androidMain.dependencies {
implementation(libs.androidx.core)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
}
}
}
android {
namespace = "dev.dtrentin.chart"
compileSdk = 35
defaultConfig {
minSdk = 24
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
publishing {
// KMP plugin auto-creates per-target publications.
// Run: ./gradlew publishToMavenLocal
publications.withType<MavenPublication>().configureEach {
pom {
name.set("chart-realtime")
description.set("KMP real-time line chart for high-frequency sensor data (200Hz+ multi-signal, bounded memory).")
url.set("https://github.com/davide-trentin/KMPCharts")
licenses {
license {
name.set("MIT License")
url.set("https://opensource.org/licenses/MIT")
distribution.set("repo")
}
}
developers {
developer {
id.set("dtrentin")
name.set("Davide Trentin")
}
}
}
}
}