Reputation: 2405
I have an image processing application that I am using to test potential speedup of blocks/threads on iOS. The algorithm works fine, uses a fair amount of memory and then dumps it after running.
I made a test suite that runs the algorithm 10 times sequentially and 10 times using my parallel implementation. If I try to run it on a phone it crashes due to memory pressure - it ends up needing about 432MB of memory. However, once the suite is done it all finally gets cleaned up :/
Each individual run is using around 25MB of memory. So I thought the solution would be to reset all of my objects after each run and they would get cleaned up. I basically have 2 processing objects that do all of my work. So after each run I thought setting them to nil would cause them to be recreated and the old versions to be destroyed and that memory freed. However, it had no effect on my memory usage.
Is there something more I need to do to free up the memory in-between calls? I thought Objective-C was now using reference counting, and once I eliminate the only reference - in my viewController - that it would be freed. Any suggestions would be greatly appreciated.
This is the test suite algorithm with my attempted memory-freeing:
- (void)runTestSuite
{
// Sequential
NSLog(@"Sequential Run: ");
for (int i = 0; i < 10; i++) {
self.imageView.image = self.startImage;
self.imageManipulator = nil;
self.objectRecognizer = nil;
for (UIView *view in self.gameView.subviews) {
[view removeFromSuperview];
}
[self processImageInParallel:NO];
}
[self printResults];
[self clearResults];
// Parallel
NSLog(@"Parallel Run: ");
for (int i = 0; i < 10; i++) {
self.imageView.image = self.startImage;
self.imageManipulator = nil;
self.objectRecognizer = nil;
for (UIView *view in self.gameView.subviews) {
[view removeFromSuperview];
}
[self processImageInParallel:YES];
}
[self printResults];
[self clearResults];
}
Upvotes: 1
Views: 111
Reputation: 17053
Autorelease pool should be used here
Many programs create temporary objects that are autoreleased. These objects add to the program’s memory footprint until the end of the block. In many situations, allowing temporary objects to accumulate until the end of the current event-loop iteration does not result in excessive overhead; in some situations, however, you may create a large number of temporary objects that add substantially to memory footprint and that you want to dispose of more quickly. In these latter cases, you can create your own autorelease pool block. At the end of the block, the temporary objects are released, which typically results in their deallocation thereby reducing the program’s memory footprint
- (void)runTestSuite
{
// Sequential
NSLog(@"Sequential Run: ");
for (int i = 0; i < 10; i++) {
@autoreleasepool
{
self.imageView.image = self.startImage;
self.imageManipulator = nil;
self.objectRecognizer = nil;
for (UIView *view in self.gameView.subviews) {
[view removeFromSuperview];
}
[self processImageInParallel:NO];
}
}
[self printResults];
[self clearResults];
// Parallel
NSLog(@"Parallel Run: ");
for (int i = 0; i < 10; i++) {
@autoreleasepool
{
self.imageView.image = self.startImage;
self.imageManipulator = nil;
self.objectRecognizer = nil;
for (UIView *view in self.gameView.subviews) {
[view removeFromSuperview];
}
[self processImageInParallel:YES];
}
}
[self printResults];
[self clearResults];
}
Upvotes: 1
Reputation: 8180
Other than working on the algorithm to improve memory usage you could give @autoreleasepool
a shot. This will free your freeable objects used in between every loop, without the need of the current loop cycle to end.
for (int i = 0; i < 10; i++) {
@autoreleasepool {
}
}
From the documentation:
In many situations, allowing temporary objects to accumulate until the end of the current event-loop iteration does not result in excessive overhead; in some situations, however, you may create a large number of temporary objects that add substantially to memory footprint and that you want to dispose of more quickly. In these latter cases, you can create your own autorelease pool block. At the end of the block, the temporary objects are released, which typically results in their deallocation thereby reducing the program’s memory footprint
Upvotes: 1
Reputation: 2532
Some source code would help. In absence of that, a general suggestion: wrap the code that is doing the image process in an autoreleasepool (see this Apple document).
This will discard temporary objects as soon as possible, reducing memory spike.
Upvotes: 1