I’m trying to create a FixedArray4<Element>
struct along the lines of FixedArray.swift
in the standard library. I need this functionality because I’m implementing a JPEG codec, and the JPEG standard uses a lot of array variables of length 4 (eg, 4 quantization tables, 4 huffman tables, 4 component selectors, etc). However, the @_fixed_layout
attributes don’t work on internal
declarations when compiling a normal binary (as opposed to the standard library), and I obviously need the guarantee that the backing storage won’t get rearranged on the stack (regardless of whether the declared layout is respected at the module interface boundary). Any help on this would be appreciated, as I really don’t want to resort to switch
statements in hot subscripts.
Tuples of one element type will always have contiguous layout (not counting padding), and a struct with a single element always has the same layout as that element. So your implementation is just
struct FixedArray4<Element> {
var storage: (Element, Element, Element, Element)
}
and then whatever conveniences you want to add on top of that.
but if I declare a local variable of type FixedArray4
won’t the compiler dismantle it for optimization like it does for any other struct?
That's true for absolutely everything. If the compiler notices you allocating an UnsafeMutablePointer, storing into it, and immediately freeing it, it's allowed to delete the store, for example.
The important point here is that while you have an address for the variable, it has to have its standard layout.
I did some actual testing, and… it seems there is absolutely no difference at all. If anything normal swift Array
s are a little faster if Element
is a large struct. (The tuple-backed FixedArray is faster if Element
is small, like an Int
.) I have no explanation why this is the case.
./arraybenchmarks // lower is better
fixed size array of Ints, with pointer subscript: 263262
fixed size array of Ints, with switch case subscript: 281201
normal Swift array of Ints: 268217
fixed size array of large structs, with pointer subscript: 275872
fixed size array of large structs, with switch subscript: 266557
normal Swift array of large structs: 266825
The testing code is here.