PHP Image Manipulation Options Compared

I recently released SSTiles, a map tile maker which used ImageMagick (using Imagick) or GD to generate tiles. It worked great locally, but when I uploaded it to my shared hosting provider I found that the Imagick module wasn’t enabled.

When I started looking into how to enable it, I found out that I had several other options, so I decided to implement the tile creation algorithm using each of the libraries and benchmark them. You can check out the code on GitHub, and below you’ll find the results.

The Contenders

  • GD
  • Imagick (ImageMagick)
  • MagickWand (ImageMagick too)
  • convert (ImageMagick command-line binary)
  • GraphicsMagick (a fork from ImageMagick).

The Testing Setup

The machine was a ThinkPad W530 with 32 Gigs of RAM and an Intel  i7-3610QM CPU at 2.30GHz. It has a 5400rpm hard drive.

I’m running Debian Jessie, with the Linux 3.10-3-amd64 kernel. The server software was Apache 2.4.6 and PHP 5.5.4.

Xdebug was enabled to generate cachegrind files, but it’s known to have performance implications. I used XHProf to capture memory usage information. I used microtime to time each tile creation.

I ran 1000 tile create operations with each of the contenders. Each iteration does the following algorithm:

  1. Determine the dimensions of the source image.
  2. Determine the number of tiles in the requested slippy map zoom leve.
  3. Crop the specified tile out of the source image.
  4. If the tile is not square, stretch it to the appropriate dimensions.
  5. Write the image to a cache file.
  6. Print the image to the browser.

For a different server configuration or a different set of operations a different library may be faster or use less memory.

Speed

Using the ImageMagick command line tools (convert and identify) via shell_exec (or backticks) was both the fastest and the slowest method of generating thumbnails. It trended heavily towards the faster end of the spectrum though.

GD was the most consistent image library, having both least variation between tile creation rounds.

Box and Whisker Chart of Tile Making Speeds
Box and Whisker Chart of Tile Making Speeds
Fastest, Average and Slowest Runs
Fastest, Average and Slowest Runs

 

Here’s a chart showing the fastest, average and slowest run for each function. Each function was called 1000 times, and each function created the same set of 1000 tiles.

makeCacheMagickWand makeCacheGD makeCacheGM makeCacheIM makeCacheIMExec
Fastest 0.55773 0.43987 0.41371 0.60702 0.03325
Average 0.66085 0.44901 0.48161 0.64898 0.36651
Slowest 0.85648 0.47315 0.52995 0.70556 0.90478

You can also see the breakdown for each method as visualized by KCachegrind. I added the red bars to show where each method is divided.  It seems that in all cases reading the image is what takes the most time.

KCachegrind View of The Time Breakdown
KCachegrind View of The Time Breakdown

Memory

I’m not 100% sure how to interpret these XHProf memory usage results. There are two columns in the output tables: Inclusive Memory Usage and Inclusive Peak Memory Usage. I tried asking on Reddit but got no answer. I assume that someone will come along here at some point and tell me that I missed some obvious documentation somewhere.

At the moment I believe that Inclusive Memory Usage is memory managed by PHP, while Inclusive Peak Memory Usage is total memory used. This is especially important on shared hosting environments where the PHP memory limit is low but the shell memory doesn’t count.

In any case, less memory used is better so let’s take a look.

Inclusive Memory Usage
Inclusive Memory Usage
Inclusive Peak Memory
Inclusive Peak Memory Usage
Combined Memory Usage Chart
Combined Memory Usage Chart

 

 

MagickWand GD GM IM IMExec
Incl Mem Use (bytes) 21032 13592 144080 176296 7216
Incl Peak Mem Use (bytes) 22728 22920 5024 12296 28152

 

Conclusion

In my use case the tiles only need to get generated once (due to caching), but that generation needs to work without running out of memory. Since SSTiles automatically picks which method to use to create tiles, I’ve ordered those checks by which uses the least memory (Inclusive Memory Usage).

This entry was posted in Computers, GitHub, Programming, Something Interesting and tagged , , , , , . Bookmark the permalink.

3 Responses to PHP Image Manipulation Options Compared

  1. Ronald says:

    Here’s a quick Google find on the mem usage issue: http://blog.cnizz.com/2012/05/05/enhanced-php-performance-profiling-with-xhprof/

    For the usage itself what kind of shared hoster are you talking about? Something like shared root servers or just PHP enabled webspaces. For the latter I guess you’re right. They may just limit the amount of memory that PHP and the webserver respectively may allocate. For shared root servers (a.k.a. VEs, usually running on OpenVZ) the story is a different one. A memory quota there will effect both shell and webserver memory usage…

    • stuporglue says:

      Thanks for the link.

      Yes, I was talking about PHP enabled web spaces like Bluehost/GoDaddy/DreamHost/etc. In my experience their memory limit is just based on the memory usage that PHP itself reports.

      • Ronald says:

        Left alone that would be risky. Its highly likely that the web servers used for operations like that would run in at least chroots, better yet OpenVZ VEs or the likes that allow for a more restrictive memory management. Otherwise I could think of a number of ways to compromise such a service within minutes. Thus I wouldn’t count on unlimited shell memory for your purposes and would advice against the use of memory intensive operations running as shell scripts.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current day month ye@r *