abdel-17
(Abdelrahman)
1
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
abdel-17
(Abdelrahman)
3
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
stuchlej
(Mikoláš Stuchlík)
5
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
abdel-17
(Abdelrahman)
6
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
stuchlej
(Mikoláš Stuchlík)
7
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