One thing that was bugging me about running snapped desktop apps was the time it took to start the first time around, or after an update. So I’ve been looking at ways to improve performance and the results are promising.
I’ve been focusing on apps using the one of the cloud parts provided by snapcraft-desktop-helpers
(e.g. desktop-gtk3
, desktop-qt5
, desktop-gnome-platform
). I’ve mainly been focusing on snaps using the GNOME platform snap, but we should be able to get similar improvements in other modes.
These parts produce a $SNAP/bin/desktop-launch
script that performs some of the operations that would usually be performed by postinst
scripts on classic Ubuntu. But since the script is doing them after the user has decided to use the app, the work is more noticeable. So I started looking at what could be improved. To start with, I’ve focused on three caches desktop-launch
creates:
- the
shared-mime-info
cache (this one seems to be the heaviest) - compiled versions of gsettings schemas
- icon theme caches
In all three cases, the caches are built by postinst scripts on classic systems because each uses a cache file covering all files in a directory (or directory tree), and multiple packages may place files in the directory. For snap packages though, the directories will be in a read only squashfs, so we should be able to generate a matching cache at package creation time.
I started by updating the gnome-3-26-1604
platform snap to generate these caches as part of the package build:
This change is now live on the edge channel of the store. I then put together a PR for snapcraft-desktop-helpers to take advantage of this:
The basic changes are:
- If the
$RUNTIME/usr/share/mime
folder contains amime.cache
file, don’t bother copying and rebuilding the mime database. - If a gsettings schema directory contains a
gschemas.compiled
file, don’t bother symlinking and compiling schemas from there. - If an icon theme directory contains an
icon-theme.cache
file, don’t bother symlinking and generating an icon cache for it.
These changes should be backward compatible with snaps which use the parts, but give a path for snaps to avoid these steps. For snaps using the GNOME platform snap, they should immediately see some benefits simply by rebuilding once the changes to the cloud part are merged.
So what is the performance difference? Looking at just the performance of just the desktop-launch script on my desktop system (not particularly new, and no SSD), here are the before numbers for the iagno snap:
james@scruffy:~$ time bash $SNAP/bin/desktop-launch true
real 0m16.973s
user 0m0.744s
sys 0m0.894s
… and for the updated desktop-launch:
james@scruffy:~$ time bash desktop-launch true
real 0m0.301s
user 0m0.153s
sys 0m0.143s
In this case, the glib-compile-schemas
is still being run to cover the app’s schemas, but not for anything in the platform snap. That’s getting to the level where it is unnoticeable.
Now it would be nice to automate some of this for snaps that are not using the GNOME platform snap, but it is not clear whether Snapcraft makes this possible. The cloud part is generally configured to run before the app’s main part, but we probably want to generate the caches based on the combined content of the stage/
directory (e.g. so that we can pick up the app’s gsettings schemas).