0

I have a method to build and return an array:

- (NSArray *)foo 
{
    NSUInteger capacity = [self getArrayCapacity];
    if (capacity == 0) {
        return @[];
    } else {
        NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:capacity];
        // add elements to the array, as many as capacity 
        ...
        return array;
    }
}

Is there a difference in memory used or performance if I simplify the code as follows:

- (NSArray *)fooSimplified 
{
    NSUInteger capacity = [self getCapacity];
    NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:capacity];
        // add elements to the array, as many as capacity 
        ...
        return array;
    }
}

So when capacity == 0 instead of returning @[] it would return [[NSMutableArray alloc] initWithCapacity:0]

Is there a performance or memory penalty/difference?

jscs
  • 63,694
  • 13
  • 151
  • 195
iOScoder
  • 53
  • 4
  • Can't you test that yourself? You can call it in a loop a million times and see if the speed is different between the 2. You can use Instruments to see if there's a difference in memory size. Also, does the immediate syntax create a mutable or immutable instance? My reading of the docs only shows immutable creation. – user1118321 Dec 21 '17 at 19:44
  • Don't prefix getters with `get` (objc doesn't use the `get` prefix generally). – bbum Dec 21 '17 at 21:08

1 Answers1

1
[[NSMutableArray alloc] initWithCapacity:0]

This will create a mutable array and allocate memory that is enough to hold specified number of elements, so it can by any high enough number depending on implementation.

@[]

Is optimized to return an instance of __NSArray0 class which is the same instance each time you create it, so there's no extra memory allocations in this case.

So using @[] is more optimal, however you probably won't see real difference unless you call this function very frequently.

Running some benchmarks in iOS simulator:

NSLog(@"%llu", dispatch_benchmark(100, ^{
    for (int i = 0; i < 1000000; ++i) {
      NSArray *a = @[];
    }
  }));

NSLog(@"%llu", dispatch_benchmark(100, ^{
    for (int i = 0; i < 1000000; ++i) {
      NSArray *a = [[NSMutableArray alloc] initWithCapacity:0];
    }
  }));


 Array Literal: 9835575 ns
 Mutable Array: 157169503 ns
Vladimir
  • 170,431
  • 36
  • 387
  • 313
  • 3
    Minor point; `initWithCapacity:` doesn't necessarily pre-allocate the space. It just hints to the mutable array how memory should potentially be optimally managed. – bbum Dec 21 '17 at 21:10