Scsynth memory leak?

Greetings,

I was running some stuff for a while and suddenly I got the exception in real time: alloc failed, increase server's memory allocation (e.g. via ServerOptions) error. I was able to narrow down what may be causing it. The same thing happens with this code (below). Also attached is a little log of sorts that shows it (you can see how the log is rendered in the code too if that’s useful for reading). You can see that scsynth memory starts at 195MB and slowly climbs to 207MB before firing off the memory error (the audio file it is playing is 133MB). I’m just letting this code run–no other reason why I would be adding to the memory usage (I think).
210105_160224_mem_leak_search.txt.zip (41.5 KB)

(
s.waitForBoot({
	Task({
		var audioBuf = Buffer.read(s,"/Volumes/Ted's 10TB My Book (June 2020)/SOUND DESIGNS/_EURORACK SOUNDS/201201 eurorackies/audio/01-201201_1505.wav");
		var synth, bus = Bus.audio(s,2);
		var vec_size = 7;
		var analysis_bus = Bus.control(s,vec_size);
		var analysis_synth, serverBuf = Buffer.alloc(s,vec_size);
		var ds = FluidDataSet(s);
		var counter = 0;
		var n_indices = 300;
		var circle_buf_full = false;
		var write_buf_synth;


		s.sync;

		// play sound
		synth = {
			arg rate = 1;
			var sig = PlayBuf.ar(audioBuf.numChannels,audioBuf,rate,startPos:rrand(0,audioBuf.numFrames-1),loop:1);
			//var sig = SoundIn.ar(0);
			Out.ar(bus,Mix(sig));
			sig;// * -20.dbamp;
		}.play;

		s.sync;

		analysis_synth = {
			var vector = FluidSpectralShape.kr(Mix(In.ar(bus,2)) / 2);
			Out.kr(analysis_bus,vector);
		}.play(synth,addAction:\addAfter);

		s.sync;

		write_buf_synth = {
			var vector = In.kr(analysis_bus,vec_size);
			vec_size.do({
				arg i;
				BufWr.kr(vector[i],serverBuf,i,1);
			});
			SendReply.kr(Impulse.kr(30),"/clock");
		}.play(analysis_synth,addAction:\addAfter);

		OSCFunc({
			var name = (counter % n_indices).asString;

			if(circle_buf_full.not,{
				ds.addPoint(name,serverBuf);
			},{
				ds.updatePoint(name,serverBuf);
			});

			counter = counter + 1;

			if(counter >= n_indices,{circle_buf_full = true;});
		},"/clock");

		~out = File("/Users/ted/Desktop/%_mem_leak_search.txt".format(Date.localtime.stamp),"w");
		inf.do({
			var str;
			p = Pipe("top -l 1 | grep scsynth","r");
			str = Date.localtime.asString;
			str = str + p.getLine + "\n";
			str.post;
			~out.write(str);
			p.close;

			ds.dump({
				arg dict;
				"n points in ds: %".format(dict.at("data").size).postln;
			});

			1.wait;
		});
	},AppClock).play;
});
)

~out.close;

FWIW a graph of scsynth MB over time: x axis is seconds since the code started essentially. The y axis is taken from the terminal output. It is either floored or rounded, I don’t know but you can still see the general rate.

Cheers @tedmoore (and especial thanks for the thorough documentation). I’ll take a look: I don’t do much with the server’s rt memory pool, so hopefully it’ll be simple enough to trace (that said, I don’t think standard leak tracing tools will help with it).

1 Like

Ok, looking at the scsynth I think there’s a bit where I’ve misunderstood whether or not it takes ownership of some memory, so I can see where the problem might be. I’ve compiled with a hopeful fix, and will leave your thing running for a while (looks like it took about 20 min to croak from above?)

FWIW, I don’t think the output of top will help here: that will report the size of scsynth's heap, but the real-time memory pool is all allocated from the free store when the server boots, and can’t grow (hence the error). However, you will see the heap grow over time with calls to malloc from other threads: that doesn’t necessarily point to a memory leak (because freed memory will be returned to the application free store, not necessarily the OS).

If needed, I can track the real-time pool size in the debugger (I think)

Cool. Thanks for the speedy reply!

Yeah it was about a half hour.

Thank you thank you!!

Cool, well I might just leave it running overnight and see if it still breathes in the morning :smiley:

1 Like

So far, so good. Will report back in some hours :sleeping_bed::sleeping_bed::sleeping_bed:

Still running, so I’ll tentatively call that fixed at this end.

2 Likes