What is the advantage of using arrayWithCapacity

arrayWithCapacity is a method defined in NSArray.h and implemented in NSArray.m

When I look at the GNUStep code, I can get that arrayWithCapacity is a regular method that calls initWithCapacity

 + (id) arrayWithCapacity: (NSUInteger)numItems { return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] initWithCapacity: numItems]); } 

And initWithCapacity is a simple method that does only initialization.

 - (id) initWithCapacity: (NSUInteger)numItems { self = [self init]; return self; } 

Nothing about memory allocation with the number of items executed.
What is the advantage of using the arrayWithCapacity method? Better to just use [[NSArray alloc] init] ?

+6
source share
3 answers

Providing an explicit size is expected to improve memory allocation since there is no need to adjust the size of the array as elements are added. In practice, this is just a hint, and there is some evidence that it was not actually used (see this article for objc.io in Foundation Collection classes).

+7
source

These methods are actually part of NSMutableArray , not NSArray .

It gives a hint about how many items you like to store, so it can already allocate enough memory ahead, rather than increase the memory as necessary, which can be costly because it may require allocation, copying from the old memory to the new one, freeing up the old memory . And if you add a lot of elements, this increase can happen a lot, so it’s more efficient if NSMutableArray can allocate the required amount of memory at a time.

Remember that this is just a hint and the implementation may ignore it. In fact, CFArray/CFMutableArray ignores capacity when creating a mutable array:

 static CFArrayRef __CFArrayInit(CFAllocatorRef allocator, UInt32 flags, CFIndex capacity, const CFArrayCallBacks *callBacks) { struct __CFArray *memory; UInt32 size; ... switch (__CFBitfieldGetValue(flags, 1, 0)) { case __kCFArrayImmutable: size += capacity * sizeof(struct __CFArrayBucket); break; case __kCFArrayDeque: case __kCFArrayStorage: break; } ... return (CFArrayRef)memory; } CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks) { ... return (CFMutableArrayRef)__CFArrayInit(allocator, __kCFArrayDeque, capacity, callBacks); } 

According to this article related to @azsromej, NSMutableArray also seems to ignore the hint.

+2
source

This applies to NSMutableArray , since NSArray does not have an arrayWithCapacity method, this also applies to initWithCapacity :

There is little if there is any advantage to using arrayWithCapacity from POV at runtime. This can be considered premature optimization.

It has a drawback or it takes some time and / or code to come up with a value that very rarely gives a significant advantage in time and increases mental stress.

It is also considered a hint and may or may not be used, that is, an implementation detail that Apple may change to any value.

Note. I conducted time tests with and without capacity hint, and the time that was saved was extremely short.

Also see ridiculousfish for more information on NSArray .

Comment by @bbum: "The state of just documents sets the initial capacity, and not that the array allocated memory to store all this capacity. The array support store is not linearly distributed pieces of memory, but the details change with the size of the array."

+1
source

Source: https://habr.com/ru/post/972838/


All Articles