#12 Performance issue using c++ java native code


I am using GraphicsMagick C++ api and calling it in a java web project which is deployed on tomcat to resize images dynamically on runtime from a certain size to given width/height. I am using scale() method of C++ api.

Now the performance is normal when there is not much load on tomcat but when number of connections/load increases on server the performance of Image resizing declines greatly. Even it goes to 30 to 40 seconds on each resize. Although memory , cpu and io utilization of the system seems normal and not bad at all.

Can any one help me with this issue? I would be highly grateful


  • Bob Friesenhahn

    Bob Friesenhahn - 2012-07-19

    The problem may be that the Java VM limits the available size of "heap" used by C code because it needs address space for the Java VM and for Java programs to use. If a large memory allocation for image data fails (e.g. due to several images already being loaded), then GM uses a temporary file for image data instead. These files may be in /tmp, /var/tmp, or some other place depending on how the system is configured. Using files is much slower than RAM.

    A simple solution is to come up with a way to pipeline your requests so that only a limited number of image processing activities are going on at once. This should still result in better throughput than if temporary files were used.

    You might also be able to enlarge the memory available to the VM and/or to the C heap via a VM configuration option.

  • Bob Friesenhahn

    Bob Friesenhahn - 2012-07-20

    It seems that I did not expose the generalized resource limit API via Magick++. Regardless, you can control the number of threads that GraphicsMagick will use via the OMP_NUM_THREADS environment variable. By default, GraphicsMagick will use as many threads as your system has cores, or the number of system virtual cores. You probably want to use less than that.

    See http://gcc.gnu.org/onlinedocs/libgomp/Environment-Variables.html#Environment-Variables for documentation on the environment variables which may be used.

  • Asad

    Asad - 2012-07-20

    Thanks for the info.. I will surely try these settings..

    But what about memory.. I have all the ram for this but still its creating temp files in /tmp ... Can we also configure it somewhere to use memory instead of file?

  • Bob Friesenhahn

    Bob Friesenhahn - 2012-07-20

    The question which was not asked is if you are using a 64-bit Java VM or a 32-bit Java VM. If it is 32-bit then that would explain why GM is running out of memory. A 32-bit VM is likely limited to 3GB maximum addressable memory.

  • Asad

    Asad - 2012-07-21

    its a 64 bit Sun HotSpot jvm version 1.6

  • Bob Friesenhahn

    Bob Friesenhahn - 2012-07-23

    Another distinct possibility is that you are encountering a memory leak issue. If the Magick++ images are not deleted when they should be, that would result in a huge memory leak which would rapidly consume all available heap memory and so GraphicsMagick would switch to using disk files and leak memory slower.

    Make sure that you are not relying on Java's lazy garbage collector to free objects referring to C heap memory (like Magick++ Image). Since the Java object would be very tiny (even though it refers to a lot of memory), Java would be less likely to free it right away. Java must provide a way to force certain deallocations to occur right away.

  • Bob Friesenhahn

    Bob Friesenhahn - 2013-03-31

    A 'batch' mode was added to GM 1.3.18. We are told that using this batch mode improves performance by 50% when GM is executed by the Java VM and that throughput is then stable. The performance improvement comes from avoiding the need to "fork/exec" GM for each image. Instead many images may be processed by the same GM, perhaps running almost as long as the Java VM.

  • Bob Friesenhahn

    Bob Friesenhahn - 2014-01-06
    • status: open --> closed
    • assigned_to: Bob Friesenhahn
    • Group: --> v1.0_(example)
  • Bob Friesenhahn

    Bob Friesenhahn - 2014-01-06

    Traditionally Java's JNI has been single-threaded so that only one Java thread may invoke the interface at a time. This may have something to do with the performance issue you have been seeing. If the time for individual resizes is increasing, then I have few ideas (other than previously mentioned) as to the cause.

    I am closing this for now since it seems that discussion has stopped.


Log in to post a comment.