determining how much heap a BufferedImage uses

I’m trying to determine how much heap I should expect a TYPE_INT_ARGB
BufferedImage with x pixels to use. I wrote a test program to find out,
which is posted here:

stackoverflow.com/questions/3854 … data-array

I’m curious if the results I found are consistent across JVMs and OSes.
Presently, I can’t think of any good reason why a BufferedImage which
should have one int (4 bytes) per pixel would apparently need 6 bytes
per pixel. If an int[] really has 50% overhead, that’s just disgracefully
bad.

I believe it is the heap manager causing the problem, not the buffered image itself. I get the following output
640
240
16
from the code below with min/max heap set to 961MB, totalling 896MB of the 961MB available. When I bump the size factor in img3 to 0.2 I run out of heap.

import java.awt.image.BufferedImage;

public class BImageTest {
public static void main(String[] args) {
final int w = Integer.parseInt(args[0]);
final int h = Integer.parseInt(args[1]);

final BufferedImage img1 = 
   new BufferedImage(w*2, h*2, BufferedImage.TYPE_INT_ARGB); 
 System.out.println((4*w*2*h*2) >> 20); 

final BufferedImage img2 = 
  new BufferedImage((int) (w*1.5), h, BufferedImage.TYPE_INT_ARGB); 
System.out.println((int)((4*w*h*1.5)) >> 20); 

final BufferedImage img3 = 
   new BufferedImage((int) (w*0.1), h, BufferedImage.TYPE_INT_ARGB); 

 System.out.println((int)((4*w*h*0.1)) >> 20); 

}
}

I’m having trouble interpreting your results here. Your program is
not the same as mine—the first image can’t be garbage collected
yet when you load the second image, and that will affect how much
heap is still available.

What are the minimum heap sizes you can run at when you use the
same program and parameters as I used?

Running Eclipse on Windows Vista, I first duplicated your results. Then I stepped up to the top range to see if the ratio persisted, which it did - with a min/max heap of 961 MB I could only allocate a single image of 640MB. However I then left the heap allocation as is, and added the code to first create the second image of 240 MB, and then the third of another 16 MB. So with heap set to exactly 961MB I could create 896MB of total buffered image on the heap, though only when the largest single buffered image was no more than 640MB.

There should be other parameters to control how the JVM manages the heap, as this cannot be the only case of a program requiring one single very large memory allocation, and a multitude of smaller ones totalling very much less space. Some how we need a means for telling the heap manager that the one large image is exceptional, and not indicative of total heap requirements. I am new to Java, and might not have looked into this except that last week I was crapping out trying to create a single buffered image of nearly 1GB, and could not quite allocate enough heap on my 3GB workstation.

P.S. Do you know how to get me registered as a VASSAL developer? I am registered as pgeerkens at SF. Thank you.

Pieter

Here are two articles on heap management parameters and diagnostic techniques:
ibm.com/developerworks/library/i-gctroub/
ibm.com/developerworks/ibm/l … bage3.html

Although a bit dated and referring to the IBM JVM, the concepts are common to all JVM’s, and the controls should be similar.

In doing further research, I discovered that to optimize the garbage-collection process, the total heap is usually managed in 2 or more segments, a large one for long-lived objects and smaller ones for initial allocation of small objects and promotion into the main heap. These are usually run as a percentage of total heap space, but the controls vary by JVM. Tweaking these appropriately should allow the large buffered-image to consume a larger percentage of total heap allocation.

Thus spake pgeerkens:

Running Eclipse on Windows Vista, I first duplicated your results. Then
I stepped up to the top range to see if the ratio persisted, which it
did - with a min/max heap of 961 MB I could only allocate a single image
of 640MB. However I then left the heap allocation as is, and added the
code to first create the second image of 240 MB, and then the third of
another 16 MB. So with heap set to exactly 961MB I could create 896MB of
total buffered image on the heap, though only when the largest single
buffered image was no more than 640MB.

There should be other parameters to control how the JVM manages the
heap, as this cannot be the only case of a program requiring one single
very large memory allocation, and a multitude of smaller ones totalling
very much less space. Some how we need a means for telling the heap
manager that the one large image is exceptional, and not indicative of
total heap requirements. I am new to Java, and might not have looked
into this except that last week I was crapping out trying to create a
single buffered image of nearly 1GB, and could not quite allocate enough
heap on my 3GB workstation.

I understand what you were trying to do now. Thanks.

If you try the demo with -XX:+PrintGCDetails, you can see that there’s enough
heap space, but it’s just allocated badly between the young, tenured, and
permanent objects. Hmm. There must be some option which will affect this.

P.S. Do you know how to get me registered as a VASSAL developer? I am
registered as pgeerkens at SF. Thank you.

I replied quite some time ago that you’ve been added, but I think you might
not have seen my reply, due to a bug with the list-forum bridge.


J.

Thus spake Joel Uckelman:

If you try the demo with -XX:+PrintGCDetails, you can see that there’s enough
heap space, but it’s just allocated badly between the young, tenured, and
permanent objects. Hmm. There must be some option which will affect this.

I asked about this on StackOverflow, and got this answer:

stackoverflow.com/questions/4269 … ge-objects

The summary is that I need to use -XX:MaxNewSize to ensure that the new
generation stays small enough so that the the old generation can grab
enough of heap space.


J.

Thanks J. I have bookmarked that for when I get back to creating large maps.