-
-
Save gregheo/00ffc980a9d28a5f3aa0371b12b65150 to your computer and use it in GitHub Desktop.
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 |
Will the CertifiedPuppy2
be optimized?
@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.
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.
Will the compiler ever optimize
CertifiedPuppy2
?