Skip to content

Instantly share code, notes, and snippets.

@gregheo
Created March 12, 2018 05:51
Show Gist options
  • Save gregheo/00ffc980a9d28a5f3aa0371b12b65150 to your computer and use it in GitHub Desktop.
Save gregheo/00ffc980a9d28a5f3aa0371b12b65150 to your computer and use it in GitHub Desktop.
Size, stride, and alignment of two structs
struct CertifiedPuppy1 {
let age: Int
let isTrained: Bool
let isCertified: Bool
}
MemoryLayout<CertifiedPuppy1>.size // 10
MemoryLayout<CertifiedPuppy1>.stride // 16
MemoryLayout<CertifiedPuppy1>.alignment // 8
struct CertifiedPuppy2 {
let isTrained: Bool
let age: Int
let isCertified: Bool
}
MemoryLayout<CertifiedPuppy2>.size // 17
MemoryLayout<CertifiedPuppy2>.stride // 24
MemoryLayout<CertifiedPuppy2>.alignment // 8
@MrNickBarker
Copy link

Will the compiler ever optimize CertifiedPuppy2?

@mrcompoteee
Copy link

Will the CertifiedPuppy2 be optimized?

@dehesa
Copy link

dehesa commented Sep 6, 2019

@MrNickBarker and @mrcompoteee As far as I understand the compiler won't optimize it.
The ABI contract states that structure order will be kept as it is written in code.

@rickyah
Copy link

rickyah commented Oct 13, 2021

Repacking a data structure is not an easy optimisation as it may seem at first glance, because the compiler does not necessarily know how you intend to access that data. For example, if you have an UnsafeRawPointer that points to memory containing a collection of CertifiedPuppy2 structs, nothing prevents you to operate over the age of all elements in the collection by using pointer arithmetic to "jump" between the bytes that represent the age in the struct, skipping the bytes representing the booleans, and then reading only the bytes of the int representing the age.
This is relatively "safe" (*) to do because you know the data layout of CertifiedPuppy2 in memory.

However, if you allow the compiler to change the layout at will, then you cannot use this access pattern anymore as you cannot be certain on where the elements of the struct are located in the raw bytes of the memory.

(*) Of course if you change the struct manually you'll have the same problem, that's why you should probably not do this manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment