GNOME Bugzilla – Bug 687882
loads and parses CSS background/border/etc. images in the main thread
Last modified: 2021-07-05 14:03:41 UTC
+++ This bug was initially created as a clone of Bug #687362 +++ St loads resources referenced by CSS in the main thread: 31106 1352317144.712156 access("GLib-GIO-START: g_local_file_read: /home/jhbuild/usr/share/gnome-shell/theme/panel-button-highlight-wide.svg", F_OK) = -1 ENOENT (No such file or directory) <0.000029> 31106 1352317144.712254 open("/home/jhbuild/usr/share/gnome-shell/theme/panel-button-highlight-wide.svg", O_RDONLY) = 23 <0.000030> 31106 1352317144.712342 fstat(23, {st_mode=S_IFREG|0644, st_size=3580, ...}) = 0 <0.000025> 31106 1352317144.712434 access("GLib-GIO-END: g_local_file_read: /home/jhbuild/usr/share/gnome-shell/theme/panel-button-highlight-wide.svg", F_OK) = -1 ENOENT (No such file or directory) <0.000027> 31106 1352317144.712536 access("GLib-GIO-START: g_local_file_input_stream_read: 0x4446f00", F_OK) = -1 ENOENT (No such file or directory) <0.000031> 31106 1352317144.712624 read(23, "<?xml version=\"1.0\" encoding=\"UT"..., 8192) = 3580 <0.000033> 31106 1352317144.712711 access("GLib-GIO-END: g_local_file_input_stream_read: 0x4446f00 -> 3580", F_OK) = -1 ENOENT (No such file or directory) <0.000029> 31106 1352317144.712801 access("GLib-GIO-START: g_local_file_input_stream_read: 0x4446f00", F_OK) = -1 ENOENT (No such file or directory) <0.000027> 31106 1352317144.712883 read(23, "", 8192) = 0 <0.000025> 31106 1352317144.712959 access("GLib-GIO-END: g_local_file_input_stream_read: 0x4446f00 -> 0", F_OK) = -1 ENOENT (No such file or directory) <0.000029> 31106 1352317144.713047 access("GLib-GIO-START: g_local_file_input_stream_close: 0x4446f00", F_OK) = -1 ENOENT (No such file or directory) <0.000030> 31106 1352317144.713132 close(23) = 0 <0.000026> 31106 1352317144.713205 access("GLib-GIO-END: g_local_file_input_stream_close: 0x4446f00 -> success", F_OK) = -1 ENOENT (No such file or directory) <0.000029> (This example is from strace'ing Bug #687465.) I don't see any mutex contention here, so I suspect that it's also parsing and rendering these SVGs in the main thread. It would be nice if the compositor didn't have to become unresponsive while waiting for I/O. I realise that fixing this is non-trivial, because the compositor needs to draw things, and to do that, it needs these images to be ready...
Complicating factors: * Until we use the image, we don't know whether it's going to have to be a Cairo surface or a COGL texture. I assume having each image in both formats is probably a bad move? * Presumably only the main thread can upload textures to the GPU? which would mean we could load (and render) the images as pixbufs from a worker thread, but then we'd have to pass those into the main thread to turn them into Cairo surfaces and/or COGL textures. We presumably don't want to keep the pixbuf afterwards, unless we later realise that we really wanted this particular texture in both formats. * When the main thread draws (e.g.) a menu, it wants all the images needed for that menu, synchronously - so if we loaded the textures "idly", we'd need a mechanism for "wait for at least this set of textures", and possibly "prioritize these textures". * We could solve many of those by precaching every image referenced by the CSS before drawing our first frame - but that hurts the "time to log in" metric, which I also want to try to improve.
We can't punt SVG rendering to a separate worker thread yet, until pango becomes thread-safe.
(In reply to comment #2) > We can't punt SVG rendering to a separate worker thread yet Thanks, that's useful to know. Blocking on I/O and rendering during Shell startup still seems like a possibility: it would hurt startup time (I'll try to benchmark how much), but would prevent unexpected blocking later. Another possible way to load the images before they're needed would be to do the I/O in a thread, and pass the file's contents to the main thread to be rendered and turned into a texture/surface in an idle (which would spread out the blocking over multiple frames, at least). The actual I/O could even continue to block, and happen in an idle in the same way, if necessary? What I'm mainly trying to avoid is "user does something, Shell becomes unresponsive for half a second while it thinks about it".
(In reply to comment #1) > Complicating factors: > > * Until we use the image, we don't know whether it's going to have to be > a Cairo surface or a COGL texture. I assume having each image in > both formats is probably a bad move? Not quite true. We know based on the complications of the CSS. It's probably also possible to put more things on the GPU, right now we just have a slow cairo fallback for simplicity. It's also entirely possible through things like hover states to have to render the texture as both cogl and cairo othertimes. We should detect these cases so we hold onto both. > * Presumably only the main thread can upload textures to the GPU? which > would mean we could load (and render) the images as pixbufs from a > worker thread, but then we'd have to pass those into the main thread > to turn them into Cairo surfaces and/or COGL textures. We presumably > don't want to keep the pixbuf afterwards, unless we later realise > that we really wanted this particular texture in both formats. Owen would have to be the expert on this, and how much uploading textures to the GPU "costs" in terms of perf. As said above, we want to keep the pixbuf if we know about cairo usage, so we don't have to reload switching between cairo / cogl usage. > * When the main thread draws (e.g.) a menu, it wants all the images > needed for that menu, synchronously - so if we loaded the textures > "idly", we'd need a mechanism for "wait for at least this set of textures", > and possibly "prioritize these textures". Yeah. What do we show until the image is loaded? Blank nothing that we fill in later? Should we render simple borders and backgrounds, or just leave the entire thing blank?
Another option is to take the GTK+ approach and prerender all theme assets as compressed data in a gresource.
GNOME is going to shut down bugzilla.gnome.org in favor of gitlab.gnome.org. As part of that, we are mass-closing older open tickets in bugzilla.gnome.org which have not seen updates for a longer time (resources are unfortunately quite limited so not every ticket can get handled). If you can still reproduce the situation described in this ticket in a recent and supported software version, then please follow https://wiki.gnome.org/GettingInTouch/BugReportingGuidelines and create a new ticket at https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/ Thank you for your understanding and your help.