perf(encoders): set web-tuned effort default (heif=1, webp=2)#113
Conversation
libvips' heifsave and webpsave default to effort=4. The Avif, Heic and Webp specialized encoders never set effort, so they inherited that default, which spends a lot of encoder CPU for little size gain on web sources. Set effort=1 for heif (avif/heic) and effort=2 for webp. On libvips 8.18.2 a 1920x1280 AVIF encode drops from ~410ms to ~60ms with near-identical bytes. WebP roughly halves its time within ~3% bytes; effort=1 was not used for webp because it costs +13-19% bytes. Both CI libvips versions (8.17.2 and 8.18.1) have effort on both ops, so no version gate is needed.
|
Follow up idea, separate from this PR if you prefer. This hardcodes the default in the driver, so users can't override it. The other option is to add Happy to do that as a follow-up (the values here would just become the fallback defaults), or fold it in now if you would rather have the public option from the start. Let me know which you prefer. |
|
Just so you have all cards in hands, this is how other libvips-based image services default the AVIF/WebP effort knob, for reference.
imgproxy already defaults AVIF to effort 1, the same as this PR. imagor and weserv both leave AVIF at the libvips default of 4. For WebP, all three keep effort 4. AVIF effort=1 is pretty obvious default. WEBP might be worth deciding the right default balance between speed/compression (x2 speed for a roughly +4% on size at 2). |
|
Looks good to me, thank you! |
|
Thanks. This is a good optimization. |
To be honest, I don't think much of the idea of integrating one single driver-specific parameters into Intervention Image's public API. The main goal is to provide a unified API and interchangable driver architecture, adding these options wouldn't be aligned with the product direction. However, I think it’s worth considering expanding the encoder options in general while maintaining consistency across drivers. However, we would first need to discuss to what extent this would even be possible (GD has very limited capabilities in this regard) and how to standardize it in a user-friendly way. This topic is beyond the scope of this discussion. I've opened a new issue for it. |
|
Providing user control over drive options seems like a nice addition 👍 But yes, probably another scope. Thanks for your feedback and merging this! |
The Vips Avif, Heic and Webp encoders set lossless, Q and keep, but they never pass libvips'
effort. So they inherit libvips' default of effort=4 (heifsave range 0..9, webpsave range 0..6), which is slower than needed for web encodes.This sets effort=1 for heif (avif/heic) and effort=2 for webp.
I found this on a demo that negotiates AVIF from the browser Accept header. The Vips driver was slower than GD on the same encode, and it turned out to be the effort default.
Repro on libvips 8.18.2, decode + encode, best of 3, Q=75 for AVIF, Q=80 for WebP. Cells are ms / output bytes, percent is bytes vs the default.
AVIF (heifsave):
WebP (webpsave):
Reasoning for the values:
No version gate: both CI libvips versions (8.17.2 and 8.18.1) have effort on both ops.
On tests: effort leaves no readable trace in the output (unlike progressive on JpegEncoder), so there is nothing stable to assert on the encoded bytes across libvips builds. The existing encoder tests now exercise the effort path on both CI versions. This matches how optimize_coding=true is already set on JpegEncoder without a dedicated test.