Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repeated calls to LSL.StreamInlet .info().channel_count() leaks memory #9

Open
boulder-on opened this issue Jun 20, 2024 · 4 comments

Comments

@boulder-on
Copy link

The following code will leak memory

while (true) {
   float[] sample = new float[inlet.info().channel_count()];
   inlet.pull_sample(sample);
}

Whereas this works properly

float[] sample = new float[inlet.info().channel_count()];
while (true) {
   inlet.pull_sample(sample);
}

I my experiment, I was collecting data at about 1 kHz. After an hour using the first snippet, my Java process was using about 20 GB. This obviously has an easy work around, but it does indicate that there is memory leaking somewhere (inside the native code?).

@cboulay
Copy link
Contributor

cboulay commented Jun 20, 2024

I'm not very good with Java, but the difference between the two snippets is that you're calling new to create new memory inside the loop vs outside. I don't know if you need to do manual cleanup here or if Java is expected to do garbage cleanup when you exit scope.
This doesn't seem like an LSL issue to me... unless you got the first snippet from a provided example?

@cboulay
Copy link
Contributor

cboulay commented Jun 20, 2024

If you found the pattern in the first snippet (new inside a while loop) in any example code or liblsl documentation then please open a documentation-focused issue.

@cboulay cboulay closed this as completed Jun 20, 2024
@boulder-on
Copy link
Author

The new float[], whether inside or outside the loop isn't a problem, The garbage collector can handle the extra allocations without problem. Allocating in the loop isn't great form. I've tested the following and it will show the memory leak as well.

while (true) {
   inlet.info().channel_count();
}

Looking deeper into the code, the StreamInfo needs to be destroyed in order to avoid the leak.

while (true) {
   var info = inlet.info();
   info.channel_count();
   info.destroy();
}

A better idiom here would be to have StreamInfo implement AutoCloseable. That way the IDE can let you know that you are not closing the resource.

As the examples are written, they all leak memory by not destroying the StreamInfo. Albeit, they leak very little. A super quick look over the codebase shows there are Pointer objects in many places, all of which could represent a memory leak if they are not destroyed.

@cboulay cboulay reopened this Jun 21, 2024
@cboulay
Copy link
Contributor

cboulay commented Jun 21, 2024

Ah, I understand better now, thanks.
Well, I am not a Java developer and I doubt @tstenner is using liblsl on Android anymore. So I think this can only be fixed with a community PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants