don't poll icon theme directories while blocking the app
Submitted by Simon McVittie
Link to original bug (#688273)
Description
Under strace, applications that use GtkIconTheme can be seen re-stat()ing icon directories every so often:
20685 1352746286.879498 stat("/usr/share/pixmaps/gnome", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000074>
20685 1352746286.879696 stat("/home/jhbuild/usr/share/pixmaps/gnome", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000048>
20685 1352746286.879854 stat("/usr/share/icons/gnome", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000047>
20685 1352746286.880044 stat("/home/jhbuild/usr/share/icons/gnome", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000044>
20685 1352746286.880195 stat("/home/jhbuild/.icons/gnome", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000049>
20685 1352746286.880382 stat("/home/jhbuild/.local/share/icons/gnome", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000045>
20685 1352746286.880538 stat("/home/jhbuild/.local/share/icons/hicolor", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000047>
20685 1352746286.880699 stat("/home/jhbuild/.icons/hicolor", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000046>
20685 1352746286.880874 stat("/home/jhbuild/usr/share/icons/hicolor", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000510>
20685 1352746286.882003 stat("/usr/share/icons/hicolor", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000078>
20685 1352746286.882252 stat("/home/jhbuild/usr/share/pixmaps/hicolor", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000097>
20685 1352746286.882510 stat("/usr/share/pixmaps/hicolor", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000095>
20685 1352746286.882735 stat("/home/jhbuild/.local/share/icons", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000062>
20685 1352746286.882931 stat("/home/jhbuild/.icons", 0x7ffff99e8640) = -1 ENOENT (No such file or directory) <0.000052>
20685 1352746286.883093 stat("/home/jhbuild/usr/share/icons", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000054>
20685 1352746286.883300 stat("/usr/share/icons", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000052>
20685 1352746286.883499 stat("/home/jhbuild/usr/share/pixmaps", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000046>
20685 1352746286.883693 stat("/usr/share/pixmaps", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000045>
Looking at the source code reveals that GtkIconTheme opportunistically calls rescan_themes() when applications look up an icon, if at least 5 seconds have elapsed since the last rescan_themes() call.
This is somewhat unfortunate if you're looking up icons that might already be loaded, in response to user input: before giving you an answer, GtkIconTheme will perform some disk I/O while you wait (even if the theme did not, in fact, change), which is on the critical path for responding to whatever the user input was.
I'm currently trying to stop gnome-shell from blocking the compositor for ~180ms while responding to input: this pile of stat() calls only costs 4ms, but it's a start...
One possibility would be to schedule the rescan (if one is needed) in an idle, and give the application an answer based on old information; then rescan when we're back in the main loop, and in the unlikely event that the theme has changed since the last iteration, the application will have to respond to the ::changed signal. (Gtk assumes that g_main_context_default() is the only main context that can touch the Gtk thread, right?)
Another possibility would be to use a GFileMonitor, so we inotify on the theme directories; that would effectively also move responding to changes into an idle.