AUv3 iOS Memory

I wanted to check if I am just stupid and insane or if anyone else is seeing the same thing. I have downloaded the AudioUnit V3 example and have been using the FilterDemo (as is) aswell as creating my own extension using the templates Xcode provides. All host apps I have tested including the host app in the example code never properly calls deinit or dealloc on the audio unit viewcontroller or the audio unit, resulting in a memory build up, leading to an eventual crash. I have been staring myself blind for retain cycles and running instruments I can see no leaks but the retain count is higher than it should be, I think, I keep no strong reference to either of the objects that aren't released, all retains I can see in instruments are all not by the extension..


Is there some trick I am missing. really I feel out of my depth here?


Cheers


Erik

Replies

We would like to understand what you're seeing and replicate the problem to make sure we're not missing anything here either. Can you file a bug report with details and a reproducible test case so we can investigate further. Go ahead and post the bug number and I'll pick it up. Thanks!

I hope I submitted it in the right place, I was given this number 26468010.


Thanks 🙂


Erik

Just wanted to give you a quick update since I was playing with the sample on OS X and did find a retain cycle in the example ViewController code. The connectViewWithAU method ends up capturing self, while in viewDidLoad self is assigned to the filter view object as the delegate. Either of these bits of code will prevent the ViewController from being deallocated. So, while we will need to address this in a future update of the sample, it goes without saying that retain cycles are easy to create and not fun to track down.


As for the template, I also created a very basic passthough AU using the template as a starting point - if you add dealloc to the AU and ViewController then use our Host sample to debug with they indeed get called until/unless you're doing something wrong (which I confirmed by doing something wrong and breaking it on purpose). Again, I've only had time to track this on OS X using Obj-C but anyway...you're not crazy, but yea...not fun.

So, it appears this has been resolved for iOS with the current beta(s). I tested with the current beta the other day using using a version of the sample code that fixed the annoying retain cycle issues and deinit is being called for the ViewController. We will roll an update of the v3 sample shortly but I suggest confirming this with your extension, and if it's not being called, start hunting for retain cycles...😕

I see the sample code has been updated, that's great! To save us a lot of detectivework, could you point out which part of the code was changed to fix the retain-cycle bug, so we can bring that snippet over into our existing AUs?


Thanks!

The code has changed substantially since the very first version and the changes are too numerous to go though individually however, the main issue surrounded retain cycles in the parameter observer dispatching block code. Referencing self in a closure's (or blocks) scope will create another reference. So for example, originally in the following code strongSelf was set up correctly (we have an actual comment too!) but it was never used.


// prevent retain cycle in parameter observer
__weak FilterDemoViewController *weakSelf = self;
...
parameterObserverToken = [paramTree tokenByAddingParameterObserver:^(AUParameterAddress address, AUValue value) {
    __strong FilterDemoViewController *strongSelf = weakSelf;
...


The other thing was a strong reference to ViewControllers as the Views delegate. These were preventing view controller deallocation which prevented audio unit deallocation -- that along with the issue on iOS itself mentioned above caused the overall problem.


Hope that's helpful.

Hi cheers for the investigations but I still don't think it is fixed. If I simply create a new au target in xcode and add no other code than a setting the output bus stuff, just so it simply runs, dealloc is never called. Some hosts call deallocateRenderResources but the apple example host doesn't even do that.


I am not sure what I am missing but.. I would expect the template with no changes should just work.


Cheers


Erik

Someone asked:

> Is there some trick I am missing.


My trick is simply to retain audio units in properties so that I can re-use them, instead of re-allocating new ones. Thus no memory build-up. RemoteIO, for instance, is basically a singleton for any iOS app, so I just retain it for the lifetime of the app.

Interesting: I noticed this too, my solution was to arrange for the view controller to release the audio unit when the AU's resources are deallocated. After doing that I noticed everything was released correctly. I will look at the new example code and re-visit this issue.

I am not sure you understood the question but cheers for the reply. 🙂


ERik

That is the only way of doing it as I see it too, but it feels very unsafe in the case of a host actually releasing stuff properly. The current intrument demo from apple leaks about 0.5 MB per instance..


Cheers


ERik

Trying to figure this out I have been looking at the memory graph in the debuger, not that I fully understand what is going on under the hood. When the instrument demo from apple should be deallocated there is still an object, NSExtensionContextVendor that has a dictonary holding a reference to the instrument viewcontroller. I am guessing this is at least one of the problems with releasing memory.


Cheers


ERik

If you guys could take another look at this, I would very much appreciate it. 🙂


Thanks

2 years later and a bit, this memory bug looks to be fixed in iOS 12. Thanks ERik