Thunar performs IO in UI functions
I faced performance issues while using Thunar with my phone connected by MTP. The Thunar UI froze often and was not very responsive with scrolling, selecting files and other mere file actions.
I tried to find the cause of issues and it turns out some UI functions make calls that drill down to IO, and freeze while waiting for IO to finish.
This is the list of IO calls I found. The tree structure represents the call stack.
-
From list model:
thunar_list_model_get_value `-thunar_file_get_content_type `-g_file_query_info -- [1]
-
From icon renderer:
thunar_icon_renderer_render `-thunar_icon_factory_load_file_icon +-thunar_icon_factory_get_show_thumbnail | `-thunar_file_get_preview_type | `-g_file_query_filesystem_info -- [2] +-g_loadable_icon_load -- [3] `-thunar_file_get_icon_name `-thunar_file_get_content_type `-g_file_query_info -- [4]
-
From misc UI:
thunar_standard_view_get_property `-thunar_list_model_get_statusbar_text `-thunar_g_file_get_free_space `-g_file_query_filesystem_info -- [5]
thunar_standard_view_request_thumbnails_real (via g_idle_add) `-thunar_thumbnailer_begin_job `-thunar_thumbnailer_file_is_supported `-thunar_file_get_content_type
thunar_folder_content_type_loader_idle (via g_idle_add) `-thunar_file_load_content_type `-thunar_file_get_content_type
thunar_path_entry_set_current_file `-gtk_entry_set_text ...signal "changed" `-thunar_path_entry_changed `-thunar_folder_get_for_file `-thunar_file_watch `-g_file_monitor `-g_file_query_file_type
I believe there are other IO calls too, but I haven't found them yet. (Should I split the issue per case?)
I'd like to solve the issue, but before doing so I wanted to discuss the solution. I see two approaches to it:
-
Ad-hoc solution
-
Prefetch
GFileInfo
with content-type beforehand. This solves [1] and [4], but slows down folder opening. -
Prefetch file system info in
ThunarFolder
to prevent [2]. -
How to deal with [3]? I have no good clues for now.
-
-
Async model solution
-
Create a layer that connects GtkTreeView to async values. This could be a special column renderer, a custom data function for a list column, a custom GValue transformation function. When the value is pending the
get_value
call returns a placeholder (blank or "..."); when the value is ready returns it. -
Use asynchronous
thunar_file_async_get_content_type
in the list model. This solves [1]. -
Move the code from
thunar_icon_renderer_render
to a newthunar_file_async_get_icon
that returns the icon asynchronously. This solves [2] [3] and [4].
This solution increases code complexity because it introduces a new layer and a notion of async values that can be pending or ready.
-
For the status bar ([5]) it seems just enough to listen to the
notify::statusbar-text
signal.
Could any of these solutions be accepted to the Thunar code? Maybe someone could think up something better? Because I'm not absolutely happy with the approaches above.