How to deal with ARC on a background thread?

I understand how automatic reference counting works:

At compile time, the possible types of relationships between objects are determined and hence when releases might occur, then at runtime the number of strong pointer references to each object is tracked and it is freed when that number reaches 0. I have yet to run into 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 doesn't release any created objects until the thread ends. I gave an example:

enter image description here

Essentially, an automatic "@autoreleasepool" is placed around the call to the thread, so it should be obvious that placing my own will not solve this problem. In fact, I tested this with the same results. If I am correct on this, then the existence of this forced pool is definitely causing my problem, but I guess this is the best that ARC can do in a multithreaded application. Memory usage is slow and consistent. If I leave this thread too long, the application will eventually run out of memory. This is a problem, as the thread must be able to run indefinitely in the worst case.

I have already removed some of the main selection in the stream. I believe I figured some of the leftover memory allocations are NSNumbers emitted from NSMutableArray because I am rewriting them.

So, I suppose I would need to do one of the following:

  • Remove a consistent selection from the stream as a whole.
  • Change your app to non-ARC to manually free memory on a background thread.
  • Detect when memory is high, save the state of the thread, synchronize with the main thread to free objects, and then resume the algorithm.
  • Find out if there is a way to tell the main thread or ARC that I want the object to be in sync so that it can be freed.
  • Understand that Apple does have a way to send ARC to properly handle other streams asynchronously and has never said anything about it on the main help page.
  • Disable ARC on files with selected objects, such as a dictionary. How can I disable ARC for one file in a project?

None of them look like pretty solutions to my problem, although I can try 1 or 6. Does anyone have any advice?

Update:

I ran the same algorithm, but with the following autocomplete blocks added to the code, I thought at first that I would refute rmaddy and Aaron Brager's answers.

-(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:

enter image description here

They were correct. I'm glad I was wrong in this case. This means that my coding will be much easier than I first imagined.
+3


source to share


1 answer


Auto-rendered objects are freed when their auto-ad pool is merged. This usually happens at the end of the thread's execution cycle.

This behavior is the same if you are talking about a main thread or a background thread. And of course, this only applies to objects that no longer have strong references.

This analysis is not entirely correct:

Basically, the automatic "@autoreleasepool" is placed around the call to the thread, so it should be obvious that placing my own will not solve this problem.

Consider this code:

@autoreleasepool {
    for (int i = 0; i < 100000; i++) {
        // create an expensive autoreleased object
        // do something with it
    }
}

      

In this case, none of the autoresolved objects will be released until the end of the run cycle, when the autoresource pool is depleted.



However, if you add your own autocomplete pool:

@autoreleasepool {
    for (int i = 0; i < 100000; i++) {
        @autoreleasepool {
            // create an expensive autoreleased object
            // do something with it
        }
    }
}

      

Objects will be freed if the internal pool is depleted for each iteration of the loop for

.

If adding your own auto-solver pool, as shown above, did not solve your problem, the rest of the possibilities:

  • You are using ARC and the objects are not deallocated because they still have a strong reference (you may have a strong reference loop)
  • The increase in memory usage does not come from Objective-C objects (like you created CGImageRef

    and never named CGImageRelease

    )
  • You are mistakenly not using ARC for this class (and you are not calling release

    )

Your six suggested solutions might also fix the problem, but it's probably easier to fix it.

+4


source







All Articles