Simple trick to reduce size and startup time of GNOME-based snaps

This week I began looking into ways to reduce the size and startup time of the LibreOffice snap. Considering the snap is GNOME-based (i.e. uses a GTK backend), the obvious first step was to have it plug into the gnome-3-28-1804 content interface. For those who don’t know, that looks like this:

plugs:
    gnome-3-28-1804:
        interface: content
        target: $SNAP/gnome-platform
        default-provider: gnome-3-28-1804

Cool, so now the snap can grab it’s the runtimes from the gnome-3-28-1804 snap. With this in place, we can actually remove the runtimes that are already in gnome-3-28-1804 from our snap. Here’s a simple part you can add to do that:

cleanup:
    after: [ all, other, parts ]
    plugin: nil
    build-snaps: [ gnome-3-28-1804 ]
    override-prime: |
        set -eux
        cd /snap/gnome-3-28-1804/current
        find . -type f,l -exec rm -f $SNAPCRAFT_PRIME/{} \;

Just adding those two snippets to the LibreOffice snap reduced its size from ~500MB to ~400MB, and reduced its first run time from ~6.5s to ~5s. That’s an improvement of ~20% on both fronts already, not bad.

NOTE: Startup times were measured using @kenvandine’s auto_close_win_id script. You can check out his wiki post here: https://wiki.ubuntu.com/DesktopTeam/GNOMESnapStartup

3 Likes

If instead of doing snap run <snap.app> you do snap run --trace-exec <snap.app>, what does the trace say?

Right, I’m aware. In fact I hacked a bit at the --trace-exec util in snapd recently to get some more detailed traces for this task.

1 Like

that looks rather useful! have you checked in with @mvo about merging that in? (him having implemented the original feature, if my memory serves)

It’s a bit hacky at the moment, but yeah, I should probably clean it up and propose it at some point.

2 Likes

Yeah, this looks pretty cool, looking forward to a PR :slight_smile:

Would it make sense for Snapcraft to support this kind of runtime snap directly? We already avoid packaging libraries provided by the base snap, so could the same be done for libraries provided by a runtime?

We’ve already got a hint as to what will appear at the content interface mount via the default-provider key, so it wouldn’t necessarily even need any changes to individual snapcraft.yaml files.

1 Like

Yes it would be easy, but most of the runtime is setup through a script in the snap, we need to know at build-time what that will look like, I would better like to standardize on a something that describes what that snap provides that we can ignore.

What I was thinking of was something like this:

  1. the snap being built has a plug definition like the following in its snapcraft.yaml:

    plugs:
      gnome-3-28-1804:
        default-provider: gnome-3-28-1804
        interface: content
        target: $SNAP/gnome-platform
    
  2. Similar to how Snapcraft downloads the base snap for the project, it would then download the snap referenced by the default-provider key.

  3. Read meta/snap.yaml from that snap to find the corresponding slot. In this case:

    slots:
      gnome-3-28-1804:
        interface: content
        read:
        - /
    
  4. If the content provided by the slot is $SNAP relative (i.e. it isn’t sharing modifiable data from $SNAP_DATA/$SNAP_COMMON), scan the relevant subtree(s) from the snap looking for ELF libraries.

This is all declarative configuration, and available right now. While it is possible that the snap’s launch scripts might not set LD_LIBRARY_PATH correctly and not find libraries in the runtime snap, I think it is okay to treat that as an error on the part of the snap’s author that they will want to fix.

1 Like

I have planned for something like this and even thought of the last part there, but I guess you are proposing to just scan elf files within the snap and assume the satisfy DT_NEEDED even if potentially not in a library path during runtime?

Yes. I think the cases where that heuristic is wrong will generally fall into one of two categories:

  1. the provider snap contains something it didn’t mean to.
  2. the consumer snap needs to fix its launch shell script.

Both probably indicate bugs, and should be immediately obvious the first time the developer attempts to install and run their snap.

Thanks for the input, I am going to be working on a proposal for this

2 Likes