I understand how Automatic Reference Counting works:
At compile time, it is determined the possible types of relationships between objects and thus where releases may occur, then at run time, the number of strong pointer references to each object is tracked and it is released when that number reaches 0. I have yet to encounter problems with this in concept or in practice, at least when dealing with the main thread.
I noticed that when I start a new background thread, it does not release any produced objects until the thread ends. I ran an example:
Essentially, an automatic '@autoreleasepool' is placed around the thread call, so it should be obvious that placing my own will not fix this issue. In fact, I have tested that with the same results. If I am correct in that, then the existence of that enforced pool is exactly causing my issue, but I assume that is the best that ARC can perform on a multithreaded application. The memory usage slowly and consistently inclines. If I leave this thread too long, the app eventually runs out of memory. This is a problem since the thread needs to be able to run indefinitely at worst.
I removed some of the main allocing in the thread already. I believe that I have determined that some of the remaining memory allocing are NSNumbers being released from an NSMutableArray because I am overwriting to it.
So I suppose I will have to do one of the following:
- Remove consistent allocing in the thread altogether.
- Change app to non-ARC to manually release memory in background thread.
- Detect when memory is high, save the state of the thread, sync with main thread to release objects, then resume the algorithm.
- Find out if there exists some way to notify the main thread or ARC that I want an object synchronized so that it may be released.
- Realize that Apple actually has a way to dispatch ARC to properly handle another threads asynchronously and never said anything about it on the main reference page.
- Disable ARC in the files with the alloced objects such as the dictionary. How can I disable ARC for a single file in a project?
None of those look like pretty solutions to my problem, although I may try 1 or 6. Does anyone have advice?
Update:
I ran the same algorithm but with the following autorelease blocks added to the code, at first thinking I was going to disprove rmaddy and Aaron Brager's responses.
-(void)setInt: (int)value For: (NSString *)variableName {
@autoreleasepool {
[self.intDictionary setValue:@(value) forKey:variableName];
}
}
-(void)setBool: (bool)value For: (NSString *)variableName {
@autoreleasepool {
[self.boolDictionary setValue:@(value) forKey:variableName];
}
}
Here is the resulting memory allocation graph:
They were correct. I am glad that I was wrong in this case. It means my coding is going to be a lot easier than I was starting to imagine.