Stack-allocated collections

Is it a good idea to define fixed-size types and using pointers to interact with the Collection API?

For example:

struct Triplet<Element> {
    private var storage: (Element, Element, Element)
    
    // use `withUnsafeBytes(of:)` to implement `subscript`.
}

I’m worried about copying overhead if I use this pattern to define larger types like CollectionOfNine.

It can sometimes be helpful, but yes, copy overhead can become a problem, especially if you're storing object types (since a copy then becomes "increment 9 reference counts").

2 Likes

No, I’m using it to store a very basic struct holding a boolean and an optional non-indirect enum.

memcpy is pretty fast, I'd expect you could get decently large before it becomes a significant problem.

1 Like

You can always try to implement your own copy-on-write fixed-size collection using ManagedBuffer.

I believe this class allows you to access the same optimisations as most of the Swift native collections use. It is widely used by the swift-collections repo (for example).

1 Like

I’m a bit torn. As far as I know, heap allocations are not without their overhead. Maybe I should just profile and stop optimizing blindly, but I’m still trying to learn how to properly test and profile in Xcode.

1 Like

A collection designed around ManagedBuffer alongside with isKnownUniquelyReferenced should be able to avoid heap allocation in certain scenarios. I can't provide you more details on that.

I certainly agree, that learning about profiling is super useful! Especially, if you want to verify, that your optimisations are effective.

Anyway, you can also look at this document swift/OptimizationTips.rst at main · apple/swift · GitHub and find some recommendations there.

Definitely measure and profile first. Swift performance can be tricky to understand even with data, it's going to be nigh-impossible if you're just guessing.

alloca and ManagedBuffer are different things nowadays, the easiest way to get a stack allocation now is to just call withUnsafeTemporaryAllocation(of:capacity:_:).

2 Likes