Improving JNA Performence
I have the following situtuation on the C side I have a function that builds and returns an array of integers representing RGB values for an image,
int* pxs(Image* m){
int* colors = malloc(height * width * sizeof(int));
//fill the array
return colors;
}
On the Java side I retrieve it using,
//invoke
Pointer ptr = ref.getPointer();
int pxs[] = pointer.getIntArray(0, width*height);
//to an image
Image img = Toolkit.getDefaultToolkit().createImage(new MemoryI开发者_如何学GomageSource(width, height, pxs, 0 ,width));
Then the image gets painted on a panel, from my timing doing all that takes around 50 60 ms, images are from a camera so I get a new one and paint in a loop but after a while (10 secs or so) my machine comes to an halt. I am thinking this is due to garbage collection? so I was wondering if there is a way to fix this?
You are never free
ing the colors array! Unless JNA does majic, Classic memory leak.
It may be a better idea to pass a ByteBuffer to the native function and have pxs
take a char *
to be filled with data.
Besides the missing free, you must take additional care as this may lead to memory problems anyway:
If you repeatedly allocate memory from "c space" (not the heap), the VM does not feel like collecting garbage because heap space is not used up. But DirectByteBuffers will free allocated c space only within the finalize method -> This leads to a "virtual" memory leak.
You can "workaround" this using frequent calls to "System.gc" or even better not allocate so much c memory, for example by only using a single transfer buffer.
As well as the memory leak that mtraut and Hamza Yerlikaya pointed out, you are also making an unnecessary copy of the pixel data (the MemoryImageSource
wraps the array, but then the Image
allocates its own buffer and copies the source pixels into it.)
You can avoid this by creating a BufferedImage
that shares the array:
ColorModel cm = ColorModel.getRGBdefault();
DataBuffer buffer = new DataBufferInt(pxs, width * height);
WritableRaster raster =
Raster.createPackedRaster(buffer, width, height, width,
new int[] {0xFF0000, 0xFF00, 0xFF, 0xFF000000},
null);
BufferedImage img = new BufferedImage(cm, raster, false, null);
精彩评论