ursus
12/12/2025, 7:04 PMvar canvasRefreshTrigger by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
while (isActive) {
awaitFrame()
coroutineScope { <--------------------------------
launch {
withContext(Dispatchers.Default) {
updateParticles2(particles, startIndex = 0, endIndex = half)
}
}
launch {
withContext(Dispatchers.Default) {
updateParticles2(particles, startIndex = half, endIndex = end)
}
}
}
canvasRefreshTrigger = !canvasRefreshTrigger
}
}
Canvas {
...draw particles
}
and ofc its paralelizable problem, so I wanna process half of the particles on one CPU core, and the other half on a second core
This works, but obviously this will be called every frame, so every 8-16ms
I was wondering, since this does seem to create a throw-away coroutine scope in coroutineScope , if there is a more light weight, ideally non allocating way while keeping coroutines
Or is coroutines a bad idea for such high frequency thing?Zach Klippenstein (he/him) [MOD]
12/12/2025, 10:07 PMawaitFrame() in compose, that's a kotlin thing. Use withFrameNanos or withFrameMillisZach Klippenstein (he/him) [MOD]
12/12/2025, 10:08 PMlaunch { withContext(context) {} } to just launch(context)Zach Klippenstein (he/him) [MOD]
12/12/2025, 10:08 PMZach Klippenstein (he/him) [MOD]
12/12/2025, 10:09 PMursus
12/12/2025, 10:11 PMZach Klippenstein (he/him) [MOD]
12/13/2025, 12:25 AMLaunchedEffect(particleSystem) {
while (isActive) {
// This kicks off some work on a background thread and returns
// immediately.
// On subsequent iterations of the loop this will run immediately
// after the frame is done and so this lets the work get started
// while waiting for the next vsync.
particleSystem.startUpdatingParticlesForFrame()
withFrameNanos {
// This blocks until the update from above is done then returns.
// This callback is run synchronously before the next frame's
// composition.
particleSystem.waitForParticleUpdateToFinish()
}
}
}
Where particleSystem is some object that synchronizes the work on a background thread. Since you're doing it on every frame, you could launch a coroutine every time but might make more sense to set up a worker pool once and then signal the existing workers every frame or something.ursus
12/13/2025, 10:37 AM