I was told that @autoreleasepool block in loop can reduce the peak of memory usage until I do a test. The test device is iPhone 6s with iOS 11.4.1.
my code:
@implementation BigMemObj{
NSMutableArray *_mutArr;
}
-(instancetype)init{
if(self = [super init]){
_mutArr = [[NSMutableArray alloc] initWithCapacity:1024*1024*30];
for(int i = 0; i < 1024*1024*30; i++){
[_mutArr addObject:@(i)];
}
}
return self;
}
- (void)viewDidLoad {
NSMutableArray *arr = [[NSMutableArray alloc] init];
for(int i = 0 ; i < 10000; i++){
@autoreleasepool {
BigMemObj *mem = [[BigMemObj alloc] init];
}
}
}
- (void)viewDidLoad {
NSMutableArray *arr = [[NSMutableArray alloc] init];
for(int i = 0 ; i < 10000; i++){
BigMemObj *mem = [[BigMemObj alloc] init];
}
}
I run both test 34 seconds, in test 1, the highest memory usage is 458M, but in the test 2 the highest memory usage is 362M. and both test have a triangle shape.
with @autoreleaspool block
Did the autoreleasepool implementation changed? or the compiler dose some optimization?
Thank You!


It all looks normal actually. The growth you are seeing is this part:
So here you are adding your numbers to an array
_mutArrand you are adding1024*1024*30of them. When this loop finishes the_mutArris valid and full, it retains all of those numbers. This would not even be changed by adding another autorelease pool within this loop because your array will not let those numbers be released.Now after this constructor is being called you have
so autorelease pool will be drained in this moment releasing all the numbers inside
BigMemObjinstancememand your memory is back to normal.You might expect that your application should keep growing in memory without the call to
@autoreleasepool. But there is no change at all if you remove that call. The reason for that is that none of your code uses autorelease pool at all. What your code translates to (non-ARC) is:But you would need your
autoreleasepoolonly if it wasTo have a situation where autorelease pool is needed:
If in this code you remove the autorelease pool it will grow in memory until the loop ends. The reason for this is because
imageWithContentsOfFileis using autorelease pool and all the images produced by this method will only be released after the pool is drained. Since the main pool will not be released inside the loop we need to create another one.Bottom line this code works nicely but as soon as you remove the
@autoreleasepoolpart it will start growing in memory and probably crash you application.Note 1: You need to add image
profile.pnginto your app for this code to work (just drag it among source files, not the assets).Note 2: We use "drain" where it comes to pools because this used to be the name of the method you needed to call when you wanted for the pool to remove it's objects. This is how it used to be: