Forums > Java

new JitterMatrix() leaking memory

September 28, 2009 | 5:17 pm

hello,
repeated use of new JitterMatrix() in an mxj external seems to cause max’s memory use to grow boundlessly.
i don’t know much about garbage collection etc. but this doesn’t look right to me.
if i start max and open e.g. one of the jitter-java examples that processes an incoming matrix (like javajitterfirsttest.maxpat or jitfeedback-example.maxpat), max uses something like 70 mb. after running this patch for an hour this value has grown to about 560 mb.

the problem seems to be with "new JitterMatrix()" as i see the same memory growth with the simple example code at the bottom.

intel mbp, osx 10.5.7, max 5.0.8

import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class matrixTest extends MaxObject
 {
	public matrixTest()
	{
		declareIO(1, 1);
	}

	public void jit_matrix(String inname)
	{
		JitterMatrix mat = new JitterMatrix(inname);		

		outlet(0, "jit_matrix", inname);
	}
}

September 28, 2009 | 8:12 pm

The memory leak is because you are creating a new JitterMatrix object every time you pass a matrix to your MXJ. What you want to do is create your JitterMatrix object once in your constructor, and then just reassign it in your ji_matrix() method. Something like this (although I can’t be sure this is exactly right as I don’t have any of my code that does this in front of me):

import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class matrixTest extends MaxObject
{

	private JitterMatrix mat; //still works without private

	public matrixTest()
	{
		mat = new JitterMatrix();
		declareIO(1, 1);

	}

	public void jit_matrix(String inname)
	{
		mat.frommatrix(inname);		

		outlet(0, "jit_matrix", inname);
	}
}

Untested, and it has been about six months since I’ve done this exactly, but something like that is what you need.


September 28, 2009 | 8:15 pm

Also, another thing about your code, you are actually not even using the internal matrix for your output. I believe you are assigning the input to an internal matrix, and then outputting the input matrix name, not the internal matrix. To output the internal matrix, you would want something like this. Again, this is off the top of my head, so watch out!

import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class matrixTest extends MaxObject
{

	private JitterMatrix mat; //still works without private

	public matrixTest()
	{
		mat = new JitterMatrix();
		declareIO(1, 1);

	}

	public void jit_matrix(String inname)
	{
		mat = frommatrix(inname);		

		outlet(0, "jit_matrix", mat.getName());
	}
}

September 28, 2009 | 8:48 pm
Quote:
The memory leak is because you are creating a new JitterMatrix object every time you pass a matrix to your MXJ.

yes, i’m aware of this. but i think it shouldn’t be like that.

Quote:
What you want to do is create your JitterMatrix object once in your constructor, and then just reassign it in your ji_matrix() method.

the frommatrix method is what seems to work correctly – thanks for pointing me to it!
and yes, forget about the outlet call. it isn’t even needed to demonstrate the problem.

i was simply modifying a source file from /examples/jitter-examples/java/. and they all use "new JitterMatrix()" inside the jit_matrix method. which obviously is a bad idea.
someone should definitely correct these examples.

volker.


September 28, 2009 | 10:40 pm
volker b�hm wrote on Mon, 28 September 2009 16:48
Quote:
The memory leak is because you are creating a new JitterMatrix object every time you pass a matrix to your MXJ.

yes, i’m aware of this. but i think it shouldn’t be like that.

Makes sense on the Java end and I imagine some sort of fix to the Jitter Java library to avoid this could cause some other problems.

It would be really useful (if anyone with the power to make these changes is watching) to have this pointed out in the documentation, because I didn’t realize this myself until I noticed the memory leak.

volker b�hm wrote on Mon, 28 September 2009 16:48
i was simply modifying a source file from /examples/jitter-examples/java/. and they all use "new JitterMatrix()" inside the jit_matrix method. which obviously is a bad idea.
someone should definitely correct these examples.

Yes! Not only should this be pointed out in the documentation, but those examples really should be fixed. Hopefully that change can get made so others don’t have to find this thread to figure it out (or more likely, not realize the problem, but run into potentially HUGE memory leaks).

I guess I shouldn’t sit around hoping someone notices this thread. I’ll send an email to support linking to this right now so hopefully this will be addressed.


September 29, 2009 | 12:00 am

Yes, this looks to be a bug. I’ll log it and we will look into it, but I am not not certain when it will be fixed.

The current workaround would be to do something like what Roth has suggested.

-Ben


September 29, 2009 | 12:21 am
ben@cycling74.com wrote on Mon, 28 September 2009 20:00
Yes, this looks to be a bug. I’ll log it and we will look into it, but I am not not certain when it will be fixed.

The current workaround would be to do something like what Roth has suggested.

-Ben

I did a little searching and found this post from 3 years ago that I now remember looking at this spring when I ran into this problem.

http://www.cycling74.com/forums/index.php?t=msg&goto=75336&rid=4220&S=d002c59b26a677b6db151281208c7d44&srch=garbage#msg_75336

This lead me to believe that this was not a bug, but related to creating Java references to Max C objects causing the reference count to never fall to zero. I don’t claim to be an expert Java programmer, but it seems to me that if the current Max/Java garbage collection issues were documented, it would actually be a feature. Forcing the work around I mentioned would offer some CPU benefit as would not be allocating/deallocating objects at every method call. It may not be much, but as someone who runs into many CPU walls, I’ll do everything I can. I realize fixing this "bug" would not prevent me from continuing to use my workaround, but it seems like a built in way of forcing more efficient style (at least if it were properly documented).

Thoughts?


September 29, 2009 | 3:54 pm

In talking with JKC, this sounds about right. From the linked forum thread, JKC mentions:

"You will want to call JitterMatrix.freepeer() to free any C resources which are not handled fast enough by the garbage collector."

It might be that the GC is not getting triggered on these objects aggressively (since it has no idea about the C memory behind the scenes).

So, in regards to the examples, it may be a case of "do as we say, not as we do" Smile

-Ben


Viewing 8 posts - 1 through 8 (of 8 total)