Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVG optimisation #79

Open
anthonydillon opened this issue May 6, 2016 · 6 comments
Open

SVG optimisation #79

anthonydillon opened this issue May 6, 2016 · 6 comments

Comments

@anthonydillon
Copy link
Contributor

For example,
The homepage of ubuntu.com has a image Google deems unoptimised.

Optimize the following images to reduce their size by 21.2KiB (97% reduction).
Compressing and resizing https://assets.ubuntu.com/v1/a0ae228b-laptop-base.png could save 21.2KiB (97% reduction).

@ghost ghost removed the enhancement label Sep 7, 2016
@nottrobin nottrobin changed the title Review optimised images to check they are fully Improve image optimisation Sep 13, 2017
@nottrobin
Copy link
Contributor

Are there examples of bigger images whose optimisation is seriously sub-optimal? Until we find some cases where we can save at least 100kb I'm considering this pretty low priority.

@barrymcgee
Copy link
Contributor

barrymcgee commented May 29, 2019

Given the reach this assets server now has across all our products and sites, I think we should prioritise any image optimisations we can.

We're actually in a very fortunate position here in that we can make one change to this one codebase and significantly improve the performance of tens of sites almost instantly.

In some cases, optimising might shave a negligible percentage from overall file sizes of an image asset but it other cases, such as complex pictograms, it could more than half the file size.

Over the past couple of years, we have moved to using SVGs wherever possible but the assets server doesn't currently optimise them at all, serving them straight back to the client verbose with all metadata included;

Screenshot 2019-05-29 at 16 05 22

Actions

  • Add SVGO to optimise all SVG files
  • Use Imagemin to optimise all jpgs/pngs

I'm hoping we can also run the above on all current images currently served as well as all new images?

@anthonydillon
Copy link
Contributor Author

The asset server uses SVGO and imagemin but I believe there are improvements to be made to the settings.

@nottrobin nottrobin changed the title Improve image optimisation Assets.ubuntu.com: SVG optimisation Jun 3, 2019
@nottrobin nottrobin changed the title Assets.ubuntu.com: SVG optimisation SVG optimisation Oct 8, 2019
@nottrobin
Copy link
Contributor

nottrobin commented Oct 9, 2019

The clear problem with SVGs, which was highlighted during the performance workshop with @csswizardry, is that SVGs on the assets server aren't compressed. In fact, nothing is compressed at all, let alone compressed with Brotli. This will be fixed by moving the application to Kubernetes, which we hope to do at least by April 2020, but I've also filed an issue here to track it.

I've looked into the benefits of compressing various SVGs that we use on our sites. I tested the following, hopefully representative, SVGs. When checking Gzip compression against Brotli, Brotli was better in every case, so I've only bothered showing Brotli compression in this test:

And I performed the following operations on each:

  • Downloaded it uncompressed
  • Ran svgo and output with a .svgo.svg extension
  • Compressed each of the output files with Brotli for comparison
  • Ran it through cloudinary by prepending the URL https://res.cloudinary.com/canonical/image/fetch/f_auto,q_auto,fl_sanitize/ (which invariably converted it to a PNG), and saved it with a .cloudinary.svg.png extension

Important to note here that Cloudinary doesn't bother compressing formats that it thinks won't benefit from it - which includes PNG. So there's no point testing Brotli with Cloudinary images.

Here are the resulting sizes, in bytes. The sizes here are so small we have to drop to bytes, rather than kilobytes, to see the differences (I reformatted the output a bit for readability):

$ du -sb *

36437   Deep+tech+ubuntu+-+light.svg
14165   Deep+tech+ubuntu+-+light.svgo.svg

9206    Deep+tech+ubuntu+-+light.svg.br
3880    Deep+tech+ubuntu+-+light.svgo.svg.br
5797    Deep+tech+ubuntu+-+light.cloudinary.svg.png

---

5825    jaas-logo1.svg
3400    jaas-logo1.svgo.svg

2153    jaas-logo1.svg.br
1251    jaas-logo1.svgo.svg.br
953     jaas-logo1.cloudinary.svg.png

---

2464    logo-mozilla--snapcraft-homepage.svg
1692    logo-mozilla--snapcraft-homepage.svgo.svg

1023    logo-mozilla--snapcraft-homepage.svg.br
786     logo-mozilla--snapcraft-homepage.svgo.svg.br
662     logo-mozilla--snapcraft-homepage.cloudinary.svg.png

---

6228    openstack-hero.svg
6183    openstack-hero.svgo.svg

1319    openstack-hero.svg.br
1314    openstack-hero.svgo.svg.br
7514    openstack-hero.cloudinary.svg.png

---

3767    postgresql-circle.svg
3763    postgresql-circle.svgo.svg

1247    postgresql-circle.svg.br
1246    postgresql-circle.svgo.svg.br
1987    postgresql-circle.cloudinary.svg.png

---

31909   Slide+-+Jaas.svg
20947   Slide+-+Jaas.svgo.svg

6486    Slide+-+Jaas.svg.br
4960    Slide+-+Jaas.svgo.svg.br
16496   Slide+-+Jaas.cloudinary.svg.png

---

11133   snapcraft-logo--web-white-text.svg
5621    snapcraft-logo--web-white-text.svgo.svg

3400    snapcraft-logo--web-white-text.svg.br
2440    snapcraft-logo--web-white-text.svgo.svg.br
896     snapcraft-logo--web-white-text.cloudinary.svg.png

Some observations:

  • SVGs are not big. Many of these are under 1KB. everything is well under 50KB.
  • Brotli compression has the biggest clear benefit to SVGs, usually reducing filesize by at least 3 times
  • Conversion to a binary format is sometimes hugely beneficial (snapcraft-logo--web-white-text.cloudinary.svg.png is a third of the size of the best compressed SVG), but also often detrimental (openstack-hero.cloudinary.svg.png is about 6 times the size of the compressed SVG) - maybe worth filing an issue to cloudinary?
    • Actually I noticed that often once we've added w_ and h_ attributes to the cloudinary query, it actually gets returned as a webp instead of a png. But I think adding w_ and h_ is problematic for my test data here.
  • Running SVGO before compression sometimes reduces the file-size by 3 times (Deep+tech+ubuntu+-+light.svgo.svg.br), sometimes halves it (jaas-logo1.svgo.svg.br), often reduces the size by a third (logo-mozilla--snapcraft-homepage.svgo.svg.br, Slide+-+Jaas.svgo.svg.br, snapcraft-logo--web-white-text.svgo.svg.br) and often has negligible benefit (postgresql-circle.svgo.svg.br, openstack-hero.svgo.svg.br). This is a pretty huge win.

Following the thread of the SVGs being very small in most cases, I was curious about the times involved in downloading them. Here are some examples from https://snapcraft.io/:

image

These results kinda baffled me a bit - 2 files from cloudinary really took ages, but most of them took negligable "receive" (download) time compared to the "wait" time. The snapcraft logo took 11ms of "wait" then 20ms of "receive", whereas the 36ms it took to get icon-arrow-up.svg was 5ms "blocked" and 31ms "wait", with no receive time. 2 other assets from the assets server took 8ms, which was all "wait", with no relevant "receive" time.

Possible actions:

  • Enable Brotli compression (by moving to Kubernetes)
  • SVGO optimisation (need to be able to release changes to the assets server)
  • Request everything through Cloudinary (would be beneficial if they fixed the cases where binary formats are detrimental)

My thoughts

To get optimal file-size on SVGs, we really need Brotli compression. Adding SVGO optimisation would also be a huge benefit.

However, both of these are probably not the biggest optimisations we could make to performance overall simply because our SVGs do tend to be very small, and so most of the time spent getting the images is spent waiting for connections to open.

Therefore the biggest win we could make would be to move the assets server to HTTP2, which should also be achieved by moving it to our Kubernetes infrastructure.

Ideally, both of these would be irrellevant because we would request everything through Cloudinary which would automatically return the best file format with the optimal compression format. However, as this is currently not the case, we may want to consider optimising the assets server and then explicitly not using Cloudinary for SVGs. Although Cloudinary does support HTTP2 where the assets server does not. Until the assets server has HTTP2, we should use Cloudinary just for that reason, even without optimal filesize.

I'm going to keep pushing on moving the assets server to k8s so that we can get Brotli + HTTP2, and so that we can actually do meaningful work on it.

We may be able to move the assets server as soon as a couple of months' time, which will mean we can release optimisations and have Brotli compression, but we almost certainly won't have HTTP2 until after April 2020.

@nottrobin
Copy link
Contributor

I submitted a support ticket to Cloudinary with the following contents:

When requesting an SVG from Cloudinary with f_auto, q_auto, it seems to be converted to a binary format every time (either PNG or WebP). However, this is often very far from the optimal file-size that could be achieved by leaving it as an SVG and using e.g. Brotli compression.

For example:

You can see more of my findings here:
#79

This effect is significant enough to make us consider not using Cloudinary for serving SVGs at all.

Would you be able to improve your automatic optimisations so that you are returning Brotli-compressed SVGs where they provide better filesizes than an equivalent binary format?

@barrymcgee
Copy link
Contributor

Excellent job on this @nottrobin 🙌🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants