8

I understand the array.count ( the number of elements in the array ). count is useful to iterate over the array's elements. I sort of get the gist of array.capacity

capacity An integer value that represents how many total elements the array can store without reallocation (read-only).

Experiment

I have been playing with the Playground and noticed an array's capacity is an even number ( incremented by 2 )

var arr = [1, 2, 3 , 4, 5, 6, 7]
arr.removeLast() // capacity stays the same after a removal
println(arr.capacity) // 8
println(arr.count)    // 6

var arr = [1, 2, 3 , 4, 5, 6]
arr.removeLast()
println(arr.capacity) // 6
println(arr.count)    // 5

The question

What is the use of an array capacity ? Please give a concrete example ?

Raymond Chenon
  • 11,482
  • 15
  • 77
  • 110
  • Afaik it's just a way of preallocating memory space. You will be able to find it out with a Google search though. Not really a SO question. Also, why do you need to know? Is count not good enough? – Fogmeister Jan 07 '15 at 23:25

3 Answers3

17

An array's capacity—in particular, its reserveCapacity method—lets you preallocate space in the array.

If you're adding elements to an array, and you exceed its capacity, then the array must increase its capacity. Since a Swift array stores its elements contiguously in memory, it must reallocate its internal storage and (usually) copy all of its elements from the old storage to the new storage. (Note that NSArray isn't documented to store its elements contiguously, but we can deduce that Swift Array probably does based on the existence of the withUnsafeMutableBufferPointer method.)

If you know in advance how many elements you intend to add to the array, you can use the reserveCapacity method to preset the array's capacity so that it won't need to perform any reallocations (and associated copying).

The only reasons I can think of to ask an array for its capacity are to learn how the system works, and to debug a performance problem.

Usually you don't need to worry about reserving capacity. A reallocation is rarely a performance problem. Swift uses (I believe) an efficient reallocation schedule so that the number of reallocations is logarithmic in the final count of the array. E.g. if you add a million elements one at a time, Swift should perform no more than 20-30 reallocations.

But if you know your array will be very large (like, gigabytes on a Mac or tens of megabytes on an iOS device), or if you are filling the array in a performance-sensitive code path (e.g. filling an audio buffer that will start playing within microseconds), you may want to reserve capacity and avoid reallocations.

You should probably not worry about reserving capacity unless you know reallocations are a problem, either because the profiler shows that they're a bottleneck or because you have other evidence (like audio glitches in the audio buffer example).

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • To put some context to this: the `map` method uses this to pre-allocate the array, and it's one of the larger performance improvements of `map` over a simple `for-in-append` loop (`map` is almost always faster than an equivalent `for-in-append`). In order to get a measurable difference, you need around 10-100 million elements (depending on platform). Below that the difference is too small to measure accurately. But in the 10 million+ element range, it does become non-trivial and potentially worth the trouble. I've seen improvements ~30% for very large arrays. – Rob Napier Apr 02 '18 at 19:00
  • 1
    To be clear: this has never, ever, come up for me in a "real" iOS app, and I do a lot of high-performance iOS work. I only have numbers on it because I ran microbenchmarks against test code to find where the edges are. If you're running into this issue, you should already be asking if you should be using Accelerate instead, and possibly moving your work to C++ (which is much easier to reason about performance). – Rob Napier Apr 02 '18 at 19:06
  • 1
    I've also ended up switching some performance-critical code to C++. – rob mayoff Apr 02 '18 at 20:38
4

What is the use of an array capacity

Basically, the array capacity has no external use. It is there for Swift's internal use. If you know that you will be allocating 100 objects to this array, you could set the capacity in advance as you create the array, and I have seen some people do that in their code; but there is no particular need to do so and no particular gain in doing so. You've looked under the hood and seen something you didn't really need to see. Now that you've seen, you can forget about it.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • "Now that you've seen, you can forget about it." :) May you give an example how it can be useful for external use ? – Raymond Chenon Jan 07 '15 at 23:43
  • @raychenon why? With NSArray Apple devs specifically discouraged using arrayWithCapacity and just letting everything work on its own. Why do you need an example of how to use something that you should probably never use? – Fogmeister Jan 07 '15 at 23:51
  • @Fogmeister because someone has not yet shown how capacity can be useful . Just a question before I sleep :) – Raymond Chenon Jan 07 '15 at 23:59
  • Then the question should be : why Apple devs discourage to use something that they let access to ? Well Google isn't better either. – Raymond Chenon Jan 08 '15 at 00:07
  • The concept of array capacity is important when it materially affects performance. The ability to find an array's current capacity is probably only useful for debugging and learning. – rob mayoff Jan 08 '15 at 00:14
1

The total number of elements that the array can contain without

allocating new storage.

Every array reserves a specific amount of memory to hold its contents. When you add elements to an array and that array begins to exceed its reserved capacity, the array allocates a larger region of memory and copies its elements into the new storage. The new storage is a multiple of the old storage's size. This exponential growth strategy means that appending an element happens in constant time, averaging the performance of many append operations. Append operations that trigger reallocation have a performance cost, but they occur less and less often as the array grows larger.

The following example creates an array of integers from an array literal, then appends the elements of another collection. Before appending, the array allocates new storage that is large enough store the resulting elements.

var numbers = [10, 20, 30, 40, 50]

numbers.count == 5

numbers.capacity == 5

numbers.append(contentsOf: stride(from: 60, through: 100, by: 10))

numbers.count == 10

numbers.capacity == 12
Reegan Miranda
  • 2,879
  • 6
  • 43
  • 55
raavan199
  • 125
  • 1
  • 1
  • 10