Resizing "large" images is slow and consumes a lot of memory

Description

This is true for Lucee 4.5, Lucee 5.2 and Adobe ColdFusion 10, 11, and 2016. There may not be a good way to improve this, but I'm putting this ticket in so it can at least be looked into.

Taking a JPG file that's around 18 Megs and resizing it to another size takes over 1 minute of processing and consumes 500 MB to 1 GB of RAM on the heap. By contrast the same resize operation using the ImageMagik CLI uses around 1GB of RAM but only runs for around 9 seconds. The java resize code spends a great deal of time doing getRGB calls. Probably once for every single Pixel in the image which would be millions of times.

Here is the only line of code needed to reproduce this:

Here is a URL to download the image file (too large to attach to this ticket)
https://drive.google.com/open?id=1spSr2qaPwdpXdzkfBH2XW7s8Kzbany1Z

Here's the ImageMagik call I tested with that took 9 seconds (requires you to install ImageMagik)

Environment

None

Activity

Show:
Grant Griffith
October 29, 2018, 2:38 PM

I can confirm this issue with 4.5 and we are looking for a better way to handle. ImageMagik was thrown into the mix on our side to look into, is there somewhere that maybe lists some options people are using today? We are looking to upgrade to 5.2.x in the next few months and since it has not been enhanced as a core, we will look at another solution to handle images.

Gary Stanton
October 29, 2018, 2:51 PM

I've found that ACF is much quicker than Lucee for image resizing. I'm not sure what the difference might be under the hood.
I can't really imagine Lucee including an ImageMagick binary but I suppose it could be an extension.

Personally I'm using ImageMagick for resizing on my Lucee boxes and it works great. TBH, even if native resizing was faster, it's nice to have IM take the pressure off of the JVM.

Bruce Kirkpatrick
December 5, 2018, 4:50 AM
Edited

ACF2018 has java imageio and JAI jars - i assume thats what it uses for cfimage then.

Imagemagick has these options to limit memory usage:
-limit memory 100MB -limit map 100MB

It would be interesting if Java or cfimage could have a limit feature like that, since then you could have predictable heap vs disk usage. If there is no limit, then the image feature is like a virus able to take down your machine especially if the image generation is public.

I use imagemagick, and you can even use it wrong, since I had too many threads running at once before when a client uploaded 100 images at once which were then resized in parallel. I had to make a parallel queue manager to deal with that so I could use all cpus, but not more then the number I wanted since it cripples the system to do a dozens at once. If I was implementing a pure java solution, it would be interesting to have an executor service with a configurable thread-pool size and memory limit features. That would make it really predictable and stable like my imagemagick queue did for me.

The Lucee image extension is really big. It sounds like a messy job to try to remap it to a whole new api like imagemagick and then you'd be stuck in time to a specific version of that api.

I had all kinds of trouble with compatibility and performance issues in different imagemagick versions too, so I wouldn't call imagemagick perfect, but it is pretty close. You can also get yourself in trouble if you use the HDRi q16 version since it automatically uses more memory to be able to process images internally in those higher complexity image formats. I used the q8 without hdri to make it much faster.

Michael Offner
February 21, 2019, 12:19 PM
Michael Offner
February 21, 2019, 12:21 PM

we added a new library to handle resizing ("imgscalr"), for me that is not a permanent solution, the bigger goal is to redo the complete implementation.

Fixed

Assignee

Michael Offner

Reporter

Brad Wood

Priority

Critical

Fix versions

Sprint

None
Configure