Category Archives: Programming

My programming projects and hacks.

GeoServer GetLegendGraphic Fails With “Width (0) and height (0) cannot be <= 0"

I had a weird issue with WMS GetLegendGraphic requests failing with the following message:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE ServiceExceptionReport SYSTEM "http://michael.mapfeeder.net:80/geoserver/schemas/wms/1.1.1/WMS_exception_1_1_1.dtd"&gt ;<ServiceExceptionReport version="1.1.1" &gt ;<ServiceException>
java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0
Width (0) and height (0) cannot be &amp;= 0
</ServiceException></ServiceExceptionReport>

This was weird because my request definitely included non-zero height and widths, like so:

/geoserver/wms?LAYER=parcel_area&REQUEST=GetLegendGraphic&FORMAT=image%2Fpng&STYLE=michael_test&WIDTH=20&HEIGHT=20

Eventually I tracked it down to an issue with the SLD xml. The XML was valid, but GeoServer didn’t like the use of CDATA tags inside of <Name>,<Title> and <ogc:Literal> tags.

So anywhere with formatting like this

<NamedLayer>
<Name>
<![CDATA[Parcel Area]]>
</Name>
<UserStyle>
<FeatureTypeStyle>
<Rule>
<Name>
<![CDATA[ Low Density Residential ]]>
</Name>
...

had to be changed to

<NamedLayer>
<Name>Parcel Area</Name>
<UserStyle>
<FeatureTypeStyle>
<Rule>
<Name>Low Density Residential</Name>
...

Once I got rid of the CDATA tags everything worked beautifully.

This issue was on GeoServer 2.5. YMMV, etc.

Posted in Computers, GIS Portfolio, Programming | Tagged , , , , | Leave a comment

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).

Posted in Computers, GitHub, Programming, Something Interesting | Tagged , , , , , | 3 Comments