Improving JNA Performance

I have the following situtuation on the C side. I have a function that builds and returns an array of integers representing the RGB values ​​for the image,

int* pxs(Image* m){ int* colors = malloc(height * width * sizeof(int)); //fill the array return colors; } 

On the Java side, I retrieve it with

 //invoke Pointer ptr = ref.getPointer(); int pxs[] = pointer.getIntArray(0, width*height); //to an image Image img = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(width, height, pxs, 0 ,width));
//invoke Pointer ptr = ref.getPointer(); int pxs[] = pointer.getIntArray(0, width*height); //to an image Image img = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(width, height, pxs, 0 ,width)); 

Then the image will be drawn on the panel, from my time doing everything that takes about 50-60 ms, the images from the camera, so I get a new one and draw in a loop, but after a while (10 seconds or so) my car stops. I think this is related to garbage collection? so I was wondering if there is a way to fix this?

+4
source share
3 answers

You are never free in an array of colors! If JNA does not majic, a classic memory leak.

It is best to pass a ByteBuffer to a native function and pxs take a char * to populate with data.

+3
source

In addition to missing free ones, you should take extra care, as this can lead to memory problems in any case:

If you reallocate memory from "c-space" (rather than heap), the VM does not want to collect garbage because empty space is not used. But DirectByteBuffers will free the allocated space c only within the finalize method -> This will lead to a "virtual" memory leak.

You can get around with frequent calls to System.gc or even better not to allocate as much memory c, for example, using only one transfer buffer.

+3
source

Like the memory leak that mtraut and Hamza Erlikaya pointed out, you are also an unnecessary copy of the pixel data ( MemoryImageSource wraps the array, but then Image allocates its own buffer and copies the original pixels into it.)

You can avoid this by creating a BufferedImage that partitions 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); 
+3
source

Source: https://habr.com/ru/post/1335313/


All Articles