I've noticed that when creating an array of any of the fundamental types, given a sizeof(..)
<= 16 bytes (Bool
, Double
, Float
and some Int
types tested, see below), then Swift seemingly always pre-allocates memory in multiples of 16 bytes by default. Also, when using the .reserveCapacity(..)
array method; even if a multiple of 8 bytes would suffice, Swift still allocates space in multiples of 16 bytes.
Question: Out of curiosity, what is the reason for Swift (compiler) doing like this? Or is it possibly something that doesn't specifically depend on Swift, but rather the compiler used by Swift, or my processor?
Example
Default:
/* Memory footprint */
sizeof(().dynamicType) // 0
sizeof(Bool) // 1
sizeof(Int16) // 2
sizeof(Int32) // 4
sizeof(Int64) // 8
sizeof(Float) // 4
sizeof(Double) // 8
sizeof(String) // 24 <-- for this, in multiples of 24 bytes, OK
/* Default pre-allocation in multiples of 16 bytes? */
let boolArr : [Bool] = [true]
let boolArrExact = [Bool](count: 16, repeatedValue: true)
let boolArrNext = [Bool](count: 17, repeatedValue: true)
let boolArrNextNext = [Bool](count: 33, repeatedValue: true)
boolArr.capacity // 16 elements <=> 16 bytes
boolArrExact.capacity // 16 elements <=> 16 bytes
boolArrNext.capacity // 32 elements <=> 32 bytes
boolArrNextNext.capacity // 48 elements <=> 48 bytes
let int16arr = [Int16](count: 1, repeatedValue: 1)
let int16arrExact = [Int16](count: 8, repeatedValue: 1)
let int16arrNext = [Int16](count: 9, repeatedValue: 1)
int16arr.capacity // 8 elements <=> 2*8 = 16 bytes
int16arrExact.capacity // 8 elements <=> 2*8 = 16 bytes
int16arrNext.capacity // 16 elements <=> 2*(2*8) = 32 bytes
let int64arr = [Int64](count: 1, repeatedValue: 1)
let int64arrNext = [Int64](count: 3, repeatedValue: 1)
int64arr.capacity // 2 elements <=> 8*2 = 16 bytes
int64arrNext.capacity // 4 elements <=> 2*(8*2) = 32 bytes
Same behaviour using .reserveCapacity(...)
:
/* even when explicitly reserving capacity for less than default */
var boolArrCustomA : [Bool] = []
boolArrCustomA.reserveCapacity(5) // 8 bytes should suffice
boolArrCustomA.append(true)
boolArrCustomA.capacity // 16
var boolArrCustomB : [Bool] = []
boolArrCustomB.reserveCapacity(17) // 24 bytes should suffice
boolArrCustomB.append(true)
boolArrCustomB.capacity // 32
I'm running Swift 2.1.1, XCode 7.2, on a 64-bit Intel Core i5 machine.
Somewhat related threads that, however, have not provided me with an answer to this question: