On the guidance for using a struct versus a class and performance

The guidance for using structs in Swift is very straightforward:

  • Use structures by default.
  • Use classes when you need Objective-C interoperability.
  • Use classes when you need to control the identity of the data you're modeling.
  • Use structures along with protocols to adopt behavior by sharing implementations.

It's nice that it's so straightforward, but it made me wonder if Swift is doing any sort of optimizations under the hood in scenarios where it would be more performant to pass a reference to a function as opposed to a large struct (copy-on-write comes to mind).

I'm sure that there's quite a number of such optimisations, but don't believe there's a comprehensive list of them that would serve as definitive documentation. But at least, if I'm not mistaken, structs are passed to their own methods as references.

Copy-on-Write is kind of a different beast though, since the struct itself (i.e., the fields within) is generally passed by copy — it's just that COW structs have some pointers to the bulk storage (the actual buffer of an array, for instance), so only the pointer gets copied instead of the whole memory chunk. In any case, COW structs are implemented in Swift itself, so there should be (almost always) no additional compiler magic or pure language machinery to that, so you can inspect what actually gets copied by looking at the struct's declaration.

it's just that COW structs have some pointers to the bulk storage (the actual buffer of an array, for instance)

This is interesting. After playing around with it a bit more it's starting to make sense. So for certain built-in types a mutable alias is COW:

var foo: [Int] = [0, 1, 2, 3]
var bar = foo
bar.append(42) // The copy happens here

And for other structs the copy happens during the assignment. That makes sense.

The thing I was hung up on was when passing these structs as parameters to a function. What I didn't understand is that they are always immutable unless passed by reference as an inout parameter, so you can't modify them even if you want to. Given that's the case I would suspect that in the majority of cases the compiler can trivially optimize the copy.

I'm still using this as a guideline:


It appears that this talk was removed. Does anyone know why? Were there changes to Swift that rendered this talk obsolete?


I can still see it in the Apple Developer app. Note mine is version 9.0.1 of the app, which only goes up to WWDC 2020; more recent versions of the app require Big Sur.

the Internet Archive is a wonderful thing


The transcript is available separately as well: WWDC 2016 Session 416 - Understanding Swift Performance - ASCIIwwdc

1 Like
Terms of Service

Privacy Policy

Cookie Policy