Want to show your appreciation? Please to my charity.

Saturday, October 27, 2012

Integrate Java and GraphicsMagick – im4java Performance

Introduction

In the post Integrate Java and GraphicsMagick – Conception, I have expressed the performance concern of im4java’s integration approach. In order to verify whether the issue actually exists, we implemented our first beta application using im4java to run the baseline test.

Application

This is a web application that dynamically resize the source images that is 700x700 or less to a smaller dimension. An HTTP request come in with the individual image and the target size specified, the web application locates the source image and resize it to the target size, then streams the image back to the requester, typically a browser.

The application simply use “gm convert <source> –scale <width>x<hight> <target>”, which is probably the fastest way to scale down an image. We have throttled to only run max 32 gm processes at any given time because we got the best throughput with that setting.

Test Environment

Hardware

RAM: 32GB

CPU: 32 cores - 4 AMD Opteron(TM) Processor 6274 (8 cores)

Test Tool

JMeter is used to execute the test. The machine runs the JMeter has identical hardware as the test machine. There is high speed network connection between them.

Test Setup

We used 200K unique sample image and each image are being request twice, one converts to 260x420 and another converts to 114x166.

On thread group is used to run multiple threads in parallel. Each thread represent one concurrent user. We run the test multiple times, with different number of concurrent users. Each thread will request image one after another, there is no delay whatsoever.

We measure the throughput in terms of total number of images resized within a second by the server.

Test Result

Table below listed the total throughput under different load.

Concurrent Users Total Throughput (images/second)
50 278
500 109
5000 19
20000 4

The throughput degrades significantly when number of concurrent user increases, it performs worst when we need it most under high load. The throughput isn’t idea even at 50 concurrent users considering it is running on such a powerful server.

Conclusion

It is clear that we need a better solution than this. We also want to make it clear that the bottleneck is not the im4java, as it simply constructs the command line and invoke the GM process. The major overhead is spawning the new process. The test simply proves that the overhead is huge for JVM to spawn a new process, especially when it has large amount of open file handlers for socket connect.

Finally, we set out to implement our proposed solution.

Other Posts in the “Integrate Java and GraphicsMagick” Series

  1. Conception
  2. im4java Performance
  3. Interactive or Batch Mode
  4. gm4java
  5. gm4java Performance

Monday, October 01, 2012

Integrate Java and GraphicsMagick – Conception

Introduction

Working on building a new Java application that will use GraphicsMagick (hereafter GM) to perform the image transformation when both preparing the master image and dynamically resizing the image on the fly for web serving of a large ecommerce website.

Technical Challenge

GM is a C/C++ application. It doesn’t come with native Java implementation. GM has two types of the integration solution currently available for Java.

One type of integration is to use JNI (Java Native Interface). JMagick is the most matured one in this kind. But the stability issue of the application server is the main concern using JNI integration. If you search the Google or the GM support forum, it is not uncommon to see discussions about GM crashing on certain malformed image files, and/or leaking memory in one way or another. This make it a poor choice for a large website needs 24/7 uptime.

Another type of integration is to use command line wrapper represented by im4Java. im4java is a very nicely implemented command line wrapper for both ImageMagick and GM. The only concern to this approach is the performance. When every command line operation requires starting of a new process, it introduces significant overhead.

How to integrate GM with Java in most reliable and scalable way is the challenge.

Proposed Solution

Due to the reliability issue of the JNI approach, we decided to focus on solutions that run GM out of JVM process. If we can run GM in some sort of batch or interactive mode, then Java application can continuously send GM commands without starting a new GM process every time and then shutting it down.

Further, multiple GM processes can be started and pooled, and recycled when necessary for concurrency, performance and reliability.

This solution requires changes to GM command line utility and development of new Java integration library. We set out to start the work and will contribute back to the community when it’s done.

Other Posts in the “Integrate Java and GraphicsMagick” Series

  1. Conception
  2. im4java Performance
  3. Interactive or Batch Mode
  4. gm4java
  5. gm4java Performance