Astal icon indicating copy to clipboard operation
Astal copied to clipboard

Mpris and UI jank

Open JohnOberhauser opened this issue 9 months ago • 3 comments

Describe the bug I experience UI jank when using Mpris.get_default() and the spotify-player tui app. The spotify-player app sends more mpris signals than required. About 1 per second for playback status. That's certainly a bug with spotify-player, but 1 signal per second shouldn't cause UI jank. I ended up writing my own mpris monitor in ags and it doesn't produce the UI jank.

So I think there could be some inefficiencies in the astal code. Perhaps something in the sync function? I'm honestly not sure.

To Reproduce

  1. Install and run spotify-player
  2. Use Mpris.get_default() somewhere in your ags setup
  3. Setup a revealer or something that you can toggle to view ui jank.

Expected behavior No UI jank

Additional context

Screen recording of my mpris component with no ui jank Using this widget video

Screen recording of the astal mpris component with ui jank Using this widget video

Another user has the same issue based on the comment in this closed issue https://github.com/Aylur/astal/issues/226

JohnOberhauser avatar Mar 22 '25 01:03 JohnOberhauser

Recently I tried Gnome's Decibel app, which for me locks up the whole event loop. My initial thought was that it was caused by the Player class where we poll the position synchronously, but it was not. Afaik only the property getters and setters are synchronous so maybe giving mpris the same treatment as tray #323 would solve this?

Aylur avatar Mar 22 '25 01:03 Aylur

I played around with the vala code a little. I don't know vala and my IDE (intellij idea) doesn't have vala syntax highlighting, so it's a little tough. But I tried creating a sync2 function that is a copy of sync and I use that only for watching for property updates with proxy.g_properties_changed.connect(sync2);. I tried commenting out all the content within the function and the jank goes away. It's hard to pinpoint what in the function is causing the jank. As I uncomment more, I see more jank. I tried making sync2 asynchronous, but that didn't seem to help.

I'm kind of out of my element here, so not really sure what else I can try.

JohnOberhauser avatar Mar 22 '25 02:03 JohnOberhauser

Afaik only the property getters and setters are synchronous

While property getter and setters are always synchronous when using valas DBusProxy, the functions depend on the signature. In the mpris lib they are synchronous as well, eg: public abstract void play_pause() throws GLib.Error; Instead of public abstract async void play_pause() throws GLib.Error;

But afaik all those dbus methods are only invoked upon user interaction and therefore shouldn't be the reason for these freezes as they seem to appear in any case.

kotontrion avatar Mar 22 '25 06:03 kotontrion

One easy way to freeze the whole event loop is to mpv rtsp://1.1.1.1:554, with mpv-mpris installed, of course.

navidmafi avatar Sep 06 '25 20:09 navidmafi

#333 is probably related for locking up the event loop.

Mabi19 avatar Sep 11 '25 09:09 Mabi19

I was able to reproduce it with mpv rtsp://1.1.1.1:554 and astal-mpris monitor. From a quick look in GDB, it appears to be stuck in this g_main_loop_run, which is caused by this Bus.get_proxy_sync.

The stacktrace

The first three entries are signal receiving machinery because I paused it with Ctrl-C.

#4  0x00007ffff7e89e04 in ppoll
    (__fds=0x5555555b7da0, __nfds=1, __timeout=0x7fffffffc680, __ss=0x0)
    at /usr/include/bits/poll2.h:101
#5  g_main_context_poll_unlocked
    (priority=<optimized out>, context=0x5555555ba480, timeout_usec=<optimized out>, fds=0x5555555b7da0, n_fds=1) at ../glib/glib/gmain.c:4632
#6  g_main_context_iterate_unlocked
    (context=0x5555555ba480, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:4309
#7  0x00007ffff7e8a097 in g_main_loop_run (loop=0x5555555b7a70)
    at ../glib/glib/gmain.c:4516
#8  0x00007ffff7cf3135 in initable_init
    (initable=0x5555555b88b0, cancellable=0x0, error=0x7fffffffc8c8)
    at ../glib/gio/gdbusproxy.c:1899
#9  0x00007ffff7c47e10 in g_initable_new_valist
    (object_type=<optimized out>, first_property_name=0x555555579c8c "g-flags", var_args=var_args@entry=0x7fffffffc780, cancellable=0x0, error=0x7fffffffc8c8)
    at ../glib/gio/ginitable.c:249
#10 0x00007ffff7c47efc in g_initable_new
    (object_type=<optimized out>, cancellable=<optimized out>, error=<optimized out>, first_property_name=<optimized out>) at ../glib/gio/ginitable.c:163
#11 0x0000555555571c23 in astal_mpris_player_setup_proxy
    (self=0x5555555b8810, error=0x7fffffffc968) at ../player.vala:605
#12 0x0000555555574679 in _astal_mpris_player___lambda8_ (self=0x5555555b8810)
    at ../player.vala:577
#13 0x00005555555747a2 in __astal_mpris_player___lambda8__g_object_notify
    (_sender=0x5555555b8810, pspec=0x5555555a2300, self=0x5555555b8810)
    at ../player.vala:575

A similar analysis could be performed for other sources of freeze or jank.

Mabi19 avatar Sep 11 '25 15:09 Mabi19