开发者

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 freeing 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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜