NSMutableArray initWithCapacity nuances

Joey picture Joey · Oct 16, 2010 · Viewed 9.3k times · Source

Does anyone have advice on how to best initialize an NSMutableArray when it comes to dictating the capacity? The documentation mentions that "...even though you specify a size when you create an array, the specified size is regarded as a “hint”; the actual size of the array is still 0." So...

1) If I init with a greater capacity than I typically use, do I not have to worry about wasted memory?

2) If I init with a capacity typically lower than what I use, do I have to worry about heavier processing time allocating more memory to hold the extra elements?

Just how impacting is this initialized capacity to the performance/memory usage of this data type?

Answer

Regexident picture Regexident · Oct 16, 2010

Matt Gallagher has written a pretty informative article on Cocoa's collection classes, along with a couple of benchmarks (with & without initWithCapacity:, as well as cross class comparisons)

http://cocoawithlove.com/2008/08/nsarray-or-nsset-nsdictionary-or.html

His test (source available) for an NSMutableArray of length 1,000,000 took 0.582256sec without capacity and just 0.572139sec with capacity.

Test                                       | Time
[NSMutableArray array]                     | 0.582256 seconds
[NSMutableArray arrayWithCapacity:1000000] | 0.572139 seconds
Iterating contents                         | 0.004713 seconds

I'd say that in 99% of the use cases [NSMutableArray array] is just fine. If you do know the actual size of the resulting array, however, it won't hurt to use [NSMutableArray arrayWithCapacity:] either.


And then there is this article by Peter Ammon (who is a developer on Apple’s AppKit/Foundation team) featuring several insightful benchmarks:

http://ridiculousfish.com/blog/archives/2005/12/23/array/


Edit (March 12th 2012):

More insight on array initialization performance from http://darkdust.net/writings/objective-c/nsarray-enumeration-performance

[…] I [=>DarkDust] also wanted to know whether the performance is any different depending on how the array was created. I tested two different methods:

  • Create a C array which references the object instances and create the array using initWithObjects:count:.
  • Create a NSMutableArray and subsequently add objects using addObject:.

[…] there is a difference when allocating: the initWithObjects:count: method is faster. With a very large number of objects, this difference can become significant.


Edit (March 6th 2014):

Further more insight on array initialization performance from http://ciechanowski.me/blog/2014/03/05/exposing-nsmutablearray/:

Let’s allocate new arrays with initial capacity set to consecutive powers of two:

for (int i = 0; i < 16; i++) {
    NSLog(@"%@", [[[NSMutableArray alloc] initWithCapacity:1 << i] explored_description]);
}

Surprise surprise:

size:  2 // requested capacity:   1
size:  2 // requested capacity:   2
size:  4 // requested capacity:   4
size:  8 // requested capacity:   8
size: 16 // requested capacity:  16
size: 16 // requested capacity:  32
size: 16 // requested capacity:  64
size: 16 // requested capacity: 128
...
// 'size: 16' all the way down