Thunar (indirectly) does blocking D-Bus calls for every file in thunar_folder_finished
Tested with thunar 4.16.11 (Xfce 4.16) packaged by Arch Linux.
I was switching between list and icon view with ctrl-1/ctrl-3 in a folder with ~150 files, and it took a noticeable amount of time (0.5sec). So I profiled thunar with perf and found that a lot of time was spent alternating between the main thread and dbus thread. The hot path on the main thread is:
thunar_folder_finished
thunar_file_reload
g_local_file_query_info
_g_local_file_info_get
g_daemon_vfs_local_file_add_info
meta_lookup_cache_lookup_path
get_tree_for_device
gvfs_metadata_call_get_tree_from_device_sync
g_dbus_proxy_call_sync
Everything between _g_local_file_info_get
and get_tree_for_device
supports passing a pointer to a cache for the most recent device queried, but the entrypoint g_local_file_query_info creates a fresh cache (GLocalParentFileInfo) every time. With dbus-monitor
I confirmed that the query and reply are the same every time:
[... many more ...]
method return time=1666655820.862265 sender=:1.62 -> destination=:1.427 serial=50086 reply_serial=1865
string "uuid-86cd9bc4-d9fc-457d-a15c-798915671c62"
method call time=1666655820.862695 sender=:1.427 -> destination=:1.62 serial=1866 path=/org/gtk/vfs/metadata; interface=org.gtk.vfs.Metadata; member=GetTreeFromDevice
uint32 254
uint32 2
method return time=1666655820.863090 sender=:1.62 -> destination=:1.427 serial=50087 reply_serial=1866
string "uuid-86cd9bc4-d9fc-457d-a15c-798915671c62"
method call time=1666655820.863522 sender=:1.427 -> destination=:1.62 serial=1867 path=/org/gtk/vfs/metadata; interface=org.gtk.vfs.Metadata; member=GetTreeFromDevice
uint32 254
uint32 2
[... many more ...]
I also attached with gdb and used these breakpoints
(gdb) dprintf _g_local_file_info_get, "_g_local_file_info_get parent_info=%p parent_info->extra_data=%p\n", parent_info, parent_info->extra_data
(gdb) dprintf g_dbus_proxy_call_sync, "g_dbus_proxy_call_sync\n"
(gdb) dprintf thunar_folder_finished, "thunar_folder_finished\n"
(gdb) dprintf thunar_file_reload, "thunar_file_reload\n"
which gives a trace like
[... many cached requests not coming from thunar_folder_finished ...]
_g_local_file_info_get parent_info=0x7fffe800b5b8 parent_info->extra_data=0x7fffe806db20
_g_local_file_info_get parent_info=0x7fffe800b5b8 parent_info->extra_data=0x7fffe806db20
_g_local_file_info_get parent_info=0x7fffe800b5b8 parent_info->extra_data=0x7fffe806db20
_g_local_file_info_get parent_info=0x7fffe800b5b8 parent_info->extra_data=0x7fffe806db20
thunar_folder_finished
thunar_file_reload
_g_local_file_info_get parent_info=0x7fffffffde40 parent_info->extra_data=(nil)
g_dbus_proxy_call_sync
thunar_file_reload
_g_local_file_info_get parent_info=0x7fffffffde40 parent_info->extra_data=(nil)
g_dbus_proxy_call_sync
thunar_file_reload
_g_local_file_info_get parent_info=0x7fffffffde40 parent_info->extra_data=(nil)
g_dbus_proxy_call_sync
thunar_file_reload
_g_local_file_info_get parent_info=0x7fffffffde40 parent_info->extra_data=(nil)
g_dbus_proxy_call_sync
[... many uncached requests ...]
Though the issue is in gio/gvfs, it might be possible to side-step this in thunar (by calling g_local_file_query_info less?). I don't know the APIs well enough to say.