ComponentAnimator memory leak

Noticed an issue with ComponentAnimator that causes memory usage to keep rising. 

When animating components using a proxy component, the proxy component appears to not be properly deleted when the animation is finished, causing a memory leak. 

I'm seeing this on OSX but I assume this is an across-the-board issue. 

n

 

Hmm. I'm sceptical about that - the proxies are safely held in a ScopedPointer and if there was a leak, it'd happen in the demo app, where lots of animations are used.

I'd need to see some code that reproduces it if you want me to look deeper.

That's easy, the demo doesn't use any proxy components :). Change line 236 of the animation demo to true. Click buttons. Watch memory use slowly rise.

Watch memory use slowly rise.

Watch it where?

BTW there were no leaks when I changed that boolean, otherwise they'd appear the leak report on shutdown.

I'm just watching the dashboard in xCode and with every click it goes up. It's not going up by a lot in the Juce demo because you're just moving buttons, but I've got much bigger components to deal with so it's more dramatic for me. 

"Rising memory use" != "leaks".

It could just be fragmentation, or some internal OSX graphics storage being wasted.

Ok, well sorry for the sloppy semantics. Yes, there is no memory leaking on closing as far as I can tell. But I do get memory use increasing, to the point where the app could be using 100MB for nothing by the end of a session. I don't see anything obvious from looking at ComponentAnimator after hunting around a bit. 

Did you use the leaks instrument in Xcode to pofile the allocations?

100MB of virtual memory is insignificant - it could easily be heap fragmentation, or just an artifact of the way malloc has decided to handle the larger blocks needed by the images used to draw the proxies.

Basically, the take-home message here is that watching at the overall memory footprint of an app is a total waste of time. The reason people have written all those clever leak-detection tools is because they're necessary!

Hi Dave, I did but it didn't throw up any red flags. Or at least nothing that was obvious to me. 

This is still a huge problem for me. It repros on iOS and OSX. I have fairly large components that I'm animating, and when using proxy components (which is the only way I can get smooth animations) memory usage keeps rising and rising. Eventually iOS gives me a memory warning. Then the OS kills the app. This is a stop ship issue for me. I'm not going to release an app that quits after a half hour just because the user is navigating around the UI! 

No leaks detected by instruments. I've been over the ComponentAnimator and snapshot code, and I don't see anything wrong with it. As you mentioned the proxy is held in a scoped pointer. So when the animation task ends, it should be taken care of. I even tried replacing it with a regular pointer, deleting it manually. Not working. Memory still rises every time I animate a component. Then the app dies. 

Why would memory use continue to rise like this? Is there anything else I should look for or try? Open to any suggestions at this point!

Normally when you have phantom leaks, it's because you're creating objects and keeping them in some sort of array, so that technically they're not leaked, but in practice they're being created and left hanging around.

Hard to track down, but if you're convinced it's the component animator (which sounds unlikely but not impossible) then maybe try to create a small standalone test-case to narrow-down the cause.

Hmmm. The memory only climbs if I actually draw the proxy image! If I comment out the g.drawImageTransformed() line in paint(), the memory usage stays steady. That's really odd. 

The Instruments tool should be able to show you all the current allocations, so you can look for suspicious patterns in there.

Or try to reproduce the problem in a small piece of test code.

I am having trouble understanding how OpenGL image drawing happens in Juce so hoping someone can help me understand if this is normal:

  • the memory climbing issue only happens when rendering with OpenGL
  • everytime an animation happens (using proxy component), a snapshot of the componet gets taken. When that snapshot gets drawn it looks like a new TextureID gets generated within the context. So as the memory climbs, so does the count of TextureIDs.
  • if I detach() the openglcontext from my componet and re-attach it again, memory usage drops back down to normal, and those TextureIDs get freed up. 

So doesn't this mean the context is keeping duplicate textures around that it doesn't need anymore?

 

Ok.. doing some digging, it seems that there's an issue where the Images that ComponentAnimator uses are being deleted while the GL context is no longer active, which means their textures can't be freed, and they get leaked. I'll get on the case and sort this out..

FYI this should work better now.. Let me know if you find any more ways to make it go wrong.

thanks for looking into it! I will test this out today and let you know if there's still any issue. 

So far so good. Memory stops climbing for me now. Thanks Jules!