While discussing the idea of adding a way to work with an array's uninitialized capacity, it came up that arrays will sometimes allocate more storage than strictly requested, as a performance optimization. The difference can be significant:
var a: [UInt8] = []
a.reserveCapacity(5)
// a.capacity == 16
I can assume a few possible rationales for this behavior, but I haven't been able to find the reasons documented. In the current paradigm, where the uninitialized part of an array is inaccessible, there generally isn't any ill effect here. However, if we open up a way of accessing the full capacity of an array, not having control over the specific size of the allocation ends up feeling very strange.
The extra padding doesn't appear to be consistent, depending instead of how an array grows to a certain size:
// Appending to an array allocates the same as reserveCapacity
a = []
a.append(contentsOf: 1...5)
// a.capacity == 16
// The same array created using a literal is more stingy
a = [1, 2, 3, 4, 5]
// a.capacity == 5
I'd like to see whether the benefit outweighs the potential confusion here. My specific questions are:
- What's the intended purpose of allocating more space than requested?
- How would I go about turning this off to test whether that purpose is being served? I've followed the code down to
Builtin.allocWithTailElems_1
, and frankly get lost inlib/AST/Builtins.cpp
.