Currently, the ActiveStorage guide opening section contains the following phrase: “Using Active Storage, an application can transform image uploads with ImageMagick”.
A developer looking to start using ActiveStorage will assume that this is Rails recommendation, even if they later see in the Transforming Images
section that using vips is possible.
It is my experience, running Active Storage in production since version 5.2, that this is not a good enough default and Rails should steer users away from it, and incentivize them to use vips instead.
The original PR by janko gave the technical reasons why supporting vips was a good idea, so I’ll stick to explaining why vips is better from a user experience point of view.
Vips is faster, so it improves queue times
Let’s say you have a feature in your app that allows your user to upload multiple photos at the same time, and after the upload is done you direct them to their photo gallery. Let’s also say that your user just uploaded 5 photos.
When that user reaches the photo gallery, his browser will make 5 requests to the representations_controller
, which will start processing the 5 variants, keeping 5 puma workers occupied. For smaller apps, that might be as many workers as they have available, which means that every other HTTP request must wait until the representations_controller
is done processing the variant. This wait time is the “queue time”. With its faster processing vips can reduce the queue time and provide a faster user experience.
This is specially bad on Heroku. From my experience in the CGRP Slack group and from talking to other devs, I’ve noticed that many are using Heroku as a host and using Standard-1x or Standard-2x dynos with a puma concurrency of 1-2. Since Heroku’s load balancer assigns requests at random, this means that even if there are puma workers free, users nagivigation requests might get stuck in the queue of a server that is busy processing an image.
Back when we were in Heroku this got so bad that we could tell when a user had uploaded a large amount of photos at the same time by the fact that there was a spike in queue times and the auto scaler had kicked in.
Vips consumes less memory, so it improves response times
ImageMagick is very memory intensive when processing variants. Benchmarks by libvips author demonstrate it using 3GB memory versus 200MB by vips. With cameras in mobile phones getting better and better, the photos that must be processed are becoming larger. This inefficiency causes problems for developers running their apps in servers with tight memory constraints, like 512MB or 1GB (eg: Heroku). With Rails apps already being memory intensive, they should be always close to the memory ceiling.
Processing a single photo with ImageMagick might be enough to force the server to start swapping, and this kills ActiveRecord’s performance. I’ve seen Scout reporting that a simple find
had increased from 1-2ms to 10-30ms sometimes as much as 50ms when our Heroku dyno reached its memory limit. With most pages requiring a few queries, we are talking about an additional few hundred ms of response time for at least as long as ImageMagick is processing.
Conclusion
Recommending Vips is a form of conceptual compression. It eliminates the need for developers to understand how Active Storage’s chosen implementation for variant generation, when combined with ImageMagick slow processing and high memory requirements, is impacting their user’s experience.
Vips creates a better user experience. Let’s make it the recommended option. If possible, let’s make it the default in Rails 7 since it’s a major version and allowed to introduce breaking changes.