<https://github.com/JetBrains/compose-jb/issues/16...
# compose-desktop
r
https://github.com/JetBrains/compose-jb/issues/165 I opened this ticket, does somebody have the same issue?
d
Are you using multiple monitors?
r
Tomorrow I will check with only one monitor. however what does suprise me is that both these tickets are closed
t
I think the imageview sample is in a very early stage and do some things wrong in terms of performance optimization. Can you please try this application. In my setup it runs near to 60fps most of the time: https://gitlab.com/compose1/imagebrowser
r
cloned the repo and launched it using
./gradlew run
like the imageviewer the lag is intense. do you want me to make a youtube video to show?
t
No it is fine. I also do have a Laptop where i see very bad performance on dual monitor setup. Using sinle monitor it is fine.
r

https://youtu.be/qzrxDvSV50g

too late I already did 🙂
I tried the example program from Skiko and allthough it does not have animations the response is very fast.
t
Ok yes i also have this on my laptop setup with 2 monitors. When i disconnect one monitor the performance is fine.
On my desktop with 2 monitors and a nvidia gtx 1660Ti the performance is best when i am running a ubuntu wayland session (~60fps). Using XFCE the performance is at about 15 fps
r
Hmmmz I have been holding of running wayland
i
We use Swing timer for FPS cap. It is unreliable and can produce too long delays. We are planning to replace it (probably we will just use system VSync). Can you try to run "testtimers" (or code from code.txt) and post results here?
My results
d
Arch Linux, OpenJDK 11
Copy code
Display refresh rates: [0, 0]
SwingTimer 58.31309
SwingTimer 2.704995
SwingTimer 2.386215
SwingTimer 2.241772
SwingTimer 2.761946
SwingTimer 3.153788
SwingTimer 2.72869
SwingTimer 2.760606
SwingTimer 2.884179
JavaExecutor 4.534687
JavaExecutor 2.301134
JavaExecutor 2.244506
JavaExecutor 2.322305
JavaExecutor 2.244005
JavaExecutor 2.257171
JavaExecutor 2.272915
JavaExecutor 2.304403
JavaExecutor 2.281415
parkNanos 2.20124
parkNanos 2.155934
parkNanos 2.142515
parkNanos 2.188291
parkNanos 2.163999
parkNanos 2.138517
parkNanos 2.300902
parkNanos 2.148329
parkNanos 2.172973
(With dual monitors)
i
Thanks! Then it is probably not because of the timer 🤔
d
That's upsetting.
t
A little bit late but here are my numbers for my Laptop. When i connect a external monitor CfD apps are completely unusable:
Copy code
XUbuntu 20.04.1 LTS Quadro T2000 <http://X.Org|X.Org>
Laptop 1 Monitor

Display refresh rates: [50]
SwingTimer 48.476007
SwingTimer 2.672245
SwingTimer 2.781381
SwingTimer 2.684943
SwingTimer 2.666884
SwingTimer 2.779816
SwingTimer 2.739812
SwingTimer 2.949209
SwingTimer 2.685916
JavaExecutor 4.764661
JavaExecutor 2.462111
JavaExecutor 2.44146
JavaExecutor 2.229795
JavaExecutor 2.260279
JavaExecutor 2.268853
JavaExecutor 2.181486
JavaExecutor 2.238391
JavaExecutor 2.502922
parkNanos 2.254869
parkNanos 2.399531
parkNanos 2.176666
parkNanos 2.392465
parkNanos 2.251481
parkNanos 2.423844
parkNanos 2.116831
parkNanos 2.250089
parkNanos 2.238798


1 internal + 1 external Monitors (In this setup CfD is completely unusable because of lag)

Display refresh rates: [0, 0]
SwingTimer 30.337472
SwingTimer 2.873444
SwingTimer 3.035576
SwingTimer 2.87054
SwingTimer 2.93538
SwingTimer 3.065611
SwingTimer 2.649201
SwingTimer 2.68013
SwingTimer 2.977981
JavaExecutor 3.016719
JavaExecutor 2.268075
JavaExecutor 2.235638
JavaExecutor 2.301366
JavaExecutor 2.274967
JavaExecutor 2.467533
JavaExecutor 2.2521
JavaExecutor 2.412322
JavaExecutor 2.481701
parkNanos 2.116187
parkNanos 2.328079
parkNanos 2.38368
parkNanos 2.11959
parkNanos 2.384245
parkNanos 2.443436
parkNanos 2.363443
parkNanos 2.159839
parkNanos 2.390302
🙏 1
d
Maybe this has to do with event handling? i.e cursor, scroll, typing, etc.
I'm guessing you use Swing to pass events to compose?
Although, thinking about it more, I don't think there's a real alternative here anyway.
i
I'm guessing you use Swing to pass events to compose?
Yes, we use Swing for event handling. But it seems slowness happens not only with input events, but also with animations, where the only event that happens is "timer event".
I created a special build of Compose:
org.jetbrains.compose:compose-gradle-plugin:0.0.0-renderinglog-build16
(it is in maven repo) This build will log into console some points of the rendering process. It will be very helpful if we know what actually is slow. We need to launch imageviewer, click on text of item and see what log will be after "[FrameDispatcher] mousePressed" (I attached imageviewer with changed version).
t
First results from my dual monitor laptop setup:
Copy code
6562442594141 [FrameDispatcher] mousePressed
6562444825211 [FrameDispatcher] begin
6562444858385 [ComposeLayer] beginRecording
6562444864347 [DesktopOwners] begin
6562444870627 [DesktopOwners] onFrame
6562444938407 [DesktopOwners] recompose
6562444955214 [DesktopOwners] measureAndLayout
6562445764418 [DesktopOwners] draw
6562445786280 [DesktopOwners] end
6562445806455 [ComposeLayer] finishRecordingAsPicture
6562445933707 [ComposeLayer] onRender 1
6562445941785 [ComposeLayer] onRender 2
6562446105613 [ComposeLayer] onRender 3
6562446112770 [ComposeLayer] onRender 4
6562447067423 [ComposeLayer] onRender glFinish
6562447700744 [FrameDispatcher] end
6562799887368 [FrameDispatcher] waiting 13 ms
6562813208253 [FrameDispatcher] begin
6562813306923 [ComposeLayer] beginRecording
6562813313802 [DesktopOwners] begin
6562813532117 [DesktopOwners] onFrame
6562813750181 [DesktopOwners] recompose
6562813769848 [DesktopOwners] measureAndLayout
6562814269800 [DesktopOwners] draw
6562814305948 [DesktopOwners] end
6562814325637 [ComposeLayer] finishRecordingAsPicture
6562817915909 [ComposeLayer] onRender 1
6562817962729 [ComposeLayer] onRender 2
6562818194545 [ComposeLayer] onRender 3
6562818201252 [ComposeLayer] onRender 4
6562821154773 [ComposeLayer] onRender glFinish
6562825324495 [FrameDispatcher] end
6563181549404 [FrameDispatcher] waiting 4 ms
6568672813183 [FrameDispatcher] begin
6568672845478 [ComposeLayer] beginRecording
6568672852095 [DesktopOwners] begin
6568672971252 [DesktopOwners] onFrame
6568673248746 [DesktopOwners] recompose
6568673265805 [DesktopOwners] measureAndLayout
6568673670634 [DesktopOwners] draw
6568673690770 [DesktopOwners] end
6568673713111 [ComposeLayer] finishRecordingAsPicture
6568673821877 [ComposeLayer] onRender 1
6568673832193 [ComposeLayer] onRender 2
6568673989964 [ComposeLayer] onRender 3
6568673996906 [ComposeLayer] onRender 4
6568674317634 [ComposeLayer] onRender glFinish
6568675050392 [FrameDispatcher] end
6569665452979 [FrameDispatcher] waiting 14 ms
6570390590577 [FrameDispatcher] begin
6570390651149 [ComposeLayer] beginRecording
6570390657186 [DesktopOwners] begin
6570390981740 [DesktopOwners] onFrame
6570537709803 [DesktopOwners] recompose
6570538359057 [DesktopOwners] measureAndLayout
6570539173542 [DesktopOwners] draw
6570539186099 [DesktopOwners] end
6570539212071 [ComposeLayer] finishRecordingAsPicture
6570539347161 [ComposeLayer] onRender 1
6570539366428 [ComposeLayer] onRender 2
6570545231440 [ComposeLayer] onRender 3
6570545270684 [ComposeLayer] onRender 4
6570550598013 [ComposeLayer] onRender glFinish
6570551400478 [FrameDispatcher] end
6570903678849 [FrameDispatcher] waiting 0 ms
🙏 1
🎉 1
i
Thanks! Probably now we know what is slow. There is a huge delay between "[FrameDispatcher] end" and "[FrameDispatcher] waiting", where we only call this:
Copy code
JFrame.graphicsConfiguration.device.displayMode.refreshRate
We get refresh rate every frame. We tested it on some configurations, and it was very fast (0.1 ms). But it seems not on all configurations. To be sure, we can run this code:
Copy code
import java.awt.Dimension
import java.awt.GraphicsEnvironment
import javax.swing.JFrame
import kotlin.system.measureNanoTime

fun main() {
    val frame = JFrame()
    frame.size = Dimension(100, 100)
    frame.isVisible = true

    test("jframeRefreshRate") {
        frame.graphicsConfiguration.device.displayMode.refreshRate
    }

    test("allDevicesRefreshRate") {
        GraphicsEnvironment
            .getLocalGraphicsEnvironment()
            .screenDevices.maxOfOrNull { it.displayMode.refreshRate }
    }

    frame.dispose()
}

fun test(name: String, test: () -> Unit) {
    Thread.sleep(1000)
    print("$name ")
    repeat(10) {
        print(
            String.format(
                "%.2f ",
                measureNanoTime {
                    test()
                } / 1E6
            )
        )
        test()
        Thread.sleep(20)
    }

    println()
}
Soon we will not use this, probably we switch to system vsync.
d
Yup, all the symptoms showed up when I ran this. Laggy cursor. Fans turned on.
XOrg
process increased CPU usage etc.
Copy code
jframeRefreshRate 60.79 60.10 59.62 59.72 59.30 60.79 59.31 59.61 59.59 59.48 
allDevicesRefreshRate 149.65 119.89 120.38 119.87 120.01 119.68 120.12 120.10 120.31 119.36
🙏 1
Is there a ticket somewhere for this that I can watch?
i
You can track it here: https://github.com/JetBrains/compose-jb/issues/23 I reopened it. I am working on this problem at the moment.
👍 1
d
Awesome! Thank you very much for patiently debugging this.