https://kotlinlang.org logo
Title
s

suresh

01/29/2021, 9:20 PM
Hi, i want to display a small FPS counter when a debugging option is enabled. This is what i did to achieve that. Could somebody review and check if this is ok?
// Data class holding the total count
val renderFrame = RenderFrame(0)

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun FrameRate() {
    var frameRate by remember { mutableStateOf(0L) }

    LaunchedEffect(Unit) {
        withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
            var prevCount = renderFrame.count
            while (isActive) {
                val count = renderFrame.count
                delay(1000)
                frameRate = count - prevCount
                prevCount = count
       
            }
        }
    }

    LaunchedEffect(Unit) {
        while (isActive) {
            withFrameNanos {
                renderFrame.inc()
            }
        }
    }
}
 Text("Frame rate: $frameRate fps")
}
i

Igor Demin

01/30/2021, 10:17 AM
Looks OK, this should show FPS with +- 2 precision. To be more precise we probably shouldn't use delay(1000), on Windows the actual delay can be 1015 ms. We can write something like this:
@Composable
fun FrameRate() {
    var frameRate by remember { mutableStateOf(0) }

    LaunchedEffect(Unit) {
        var frameCount = 0
        var prevTime = withFrameNanos { it }

        while (isActive) {
            withFrameNanos {
                frameCount++

                val seconds = (it - prevTime) / 1E9 // 1E9 nanoseconds is 1 second
                if (seconds >= 1) {
                    frameRate = (frameCount / seconds).toInt()
                    prevTime = it
                    frameCount = 0
                }
            }
        }
    }

    Text("Frame rate: $frameRate fps")
}
P.S.1. This should work only in 0.3.0-build146, before this version withFrameNanos isn't synchronized with the actual window frames. P.S.2. there is a built-in FPS counter for desktop, you can enable it with system properties:
skiko.fps.enabled=true
skiko.fps.count=200 // show fps every 200 frames
You can set them with
System.setProperty(name, value)
or with gradle:
compose.desktop {
    application {
        jvmArgs("-Dskiko.fps.enabled=true", "-Dskiko.fps.count=200")
P.S.3. currently the FPS can't be more than the display refresh rate because of vsync. in the future we will add the ability to disable vsync:
skiko.vsync.enabled=false
:thank-you: 2
👍 1
r

romainguy

01/30/2021, 8:31 PM
note that fps isn't a very good performance tool. You should look at the frame time of each frame and also make sure frames are scheduled at the right time
s

suresh

01/31/2021, 4:00 AM
@Igor Demin @romainguy thanks v much for the feedback!