JOCL: Memory issues with Pointer

Hi

While memory-profiling my project with Netbeans I noticed that org.jocl.Pointer creates an increasing amount of live objects and with that an progressive acquisition of memory over lifetime.

I compared it with some of the jocl samples provided and pinned this issue down to OpenGL-based projects which use the OpenGL Animator. On every other occasion the Pointers get flushed/garbagecollected/killed/whatever at some amount, but with the animator they seem to be created faster than to be deleted.

I don’t know if this issue is with JOCL or with a bad configured JVM, but I would appreciate, if someone has an idea how to deal with it.

Hello

The garbage collector does not immediately kill objects that are no longer referenced. When there are many small objects created in a loop (as in the GL samples due to the animation) then they may stay alife for a while. When the JVM is short on memory, the objects will be GC’ed.

I considered that it might be a bug/memory leak on native side (e.g. a constant reference that is created and not deleted) but I just did a test like

for (int i=0; i<1000; i++)
{
    srcA = Pointer.to(srcArrayA);
    memObjects[0] = clCreateBuffer(context, 
	CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
	Sizeof.cl_float * n, srcA, null);

    if (i<99) clReleaseMemObject(memObjects[0]);
    System.gc();
}

i.e. creating 1000 Pointer objects and passing them to a CL method. Additionally, I appended a “System.gc()” to recommend doing a garbage collection (just for testing). And the HPROF profiler output shows


          percent          live          alloc'ed  stack class
 rank   self  accum     bytes objs     bytes  objs trace name
...
  487  0.02% 98.27%        64    2     32000  1000 300508 org.jocl.Pointer

I.e. there have been allocated 1000 Pointers, but only 2 of them have been alive at the end. So I assume that it is not a real memory leak, but just an artifact of the memory management of the JVM. Nevertheless, I’ll have a look at the native code again and see whether there might be a memory leak under different conditions.

Did you encounter any real problems, like unexplicable OutOfMemoryErrors or something…?

However, one aspect should be kept in mind: The “runJOCL” method of the SimpleGL sample is called quite frequently, via the Animator. It contains a line that sets the kernel argument for the current animation state:

    clSetKernelArg(kernel, 3, Sizeof.cl_float,
        Pointer.to(new float[]{ animationState }));

which creates a newly allocated Pointer to a newly allocated array. This causes many short-lived objects are created. This could be avoided by doing something like

private float animationStateArray[] = new float[1];
private Pointer animationStatePointer = Pointer.to(animationStateArray);

void runJOCL(...)
{
    ....
    animationStateArray[0] = animationState;
    clSetKernelArg(kernel, 3, Sizeof.cl_float, animationStatePointer);

}

I.e. creating the object and the pointer only once, and only updating the contents of the array before it is passed to the clSetKernelArg method. I did not do this in the sample, because it might seem counterintuitive. If there are many of these Pointers+Arrays, and the method is time-critical and called frequently, and the Garbage Collection turns out to be a bottleneck, pulling the object creations out of the method as described above could be an optimization, but I don’t think that this will be necessary or really beneficial.

Another (more important) issue that I’m currently working on: It might happen that garbage collection is done too early in some cases, e.g. when doing asynchronous (i.e. non-blocking) memory copies with clEnqueueWriteBuffer, but I’m already investigating some solutions for this one…

Thanks for your answer.

Hm… I think I ran into an OutOfMemoryError, but I’m not sure… I don’t know why, but I can’t reproduce the problem right now, due to some other codechanges… Though the allocated memory keeps increasing.

I already exchanged the Pointer.to() calls in the methods for pointer objects, but that doesn’t seem to have much effect.

An explicit call for the garbage collector slows down the pointer increment, but doesn’t stop it. I tested it on the MandelbrotGL project (just added an animator) for 6 minutes each. The profiler results are in the screenshots below:

Without GC: http://i429.photobucket.com/albums/qq12/Phil2008FhS/Projects/jocl-gc.png
With GC: http://i429.photobucket.com/albums/qq12/Phil2008FhS/Projects/joclgc.png

Indeed, you’re right -_- I did some profiling with VisualVM, provoked a high number of calls to the ‘render’ method by using a small window and only 5 iterations, and limited the heap size to 12 MB, and then it threw an OutOfMemoryError after some hundred thousand render passes.

I already tracked it down to the Pointer that is created for the OpenGL Buffer: When commenting out this block…

// Map the buffer object into client memory
Buffer buffer = gl.glMapBuffer(GL.GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
CL.clEnqueueReadBuffer(commandQueue, pboMem, CL_TRUE, 0,
    Sizeof.cl_int * sizeY * sizeX, Pointer.to(buffer), 0, null, null);
gl.glUnmapBuffer(GL.GL_PIXEL_UNPACK_BUFFER);

everything seems to work fine.

Unfortunately, I’ll be on a business trip in the next few days, but I’ll have a closer look at this as soon as possible. There are already some other, minor bugfixes and improvements in the current in development version, so when this issue is resolved (which will hopefully not take too long) it’s definitely time for an update.

Thank you for pointing this out!

And thank you for investigating it further.
Just take your time. I appreciate the work your doing with this all.