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…