My struct has reference semantics. should it just become a class?

i have a struct with reference semantics laid out roughly like:

public final
class ExampleState
{
    var x:Int
    var y:Int
}
public
struct Example
{
    let state:ExampleState
    
    let id:Int
    let z:[Int]
}

it has:

  • properties with shared mutable state (state.x, state.y), which i have put into ExampleState,
  • properties that are immutable and do not use reference counting (id), and
  • properties that are immutable, but use reference counting (z).

my question is then: are there any benefits or downsides to moving everything into ExampleState, and making that the new Example type?

public final
class Example
{
    var state:(x:Int, y:Int)
    
    let id:Int
    let z:[Int]
}

If you use the structure, then the id and z properties can be stored on the stack (technically not guaranteed I think, but very likely). The instance will be 3 words long (existential containers can fit 3 words without boxing). When the structure is copied/dropped, it will be required to do two reference-counting operations: one retain/release for state, and one retain/release for z.

If you put everything into the class, then the id and z properties will be stored on the heap. Reading those values will now require a dereference, which could slightly hurt performance. The instance will be 1 word long. When the class is copied/dropped, it will only need to do one retain/release.

5 Likes