Copy-On-Write in Swift
Copy-On-Write is a common computing technique that helps boost performance when copying structures. Today I would like to show you how can we apply it to Swift.
As far as we know that there’re 2 types in Swift: Reference type & Value type. When we assign value of a variable to a new variable, these things happen for 2 types above, let’s talk about Reference type first:
Classes are Reference types, then both of variables point to a memory allocation together. This is how reference type works while copying. Now take a look for Value type:
Structs are Value types then each variable will be allocated a specific memory cell. This is a biggest difference thing between reference & value types. Now, let’s talk about a specific value type: Array
Array is a Value type in Swift, but in this example, 2 variables point to a memory allocation like Reference type. Too confusing?? Let’s do something next:
After mutating array2 by appending a new element, finally it has been allocated by a new memory cell and still follow the Value type rule but “a little bit later”. This “a little bit later” called Copy-On-Write: Compiler only allocate a new memory allocation for a new variable if needed. This is a memory optimization tip on programming.
Unfortunately, Swift only support this Copy-On-Write for some kinds of value types such as: Array, Dictionary, Set, String … How about Struct? It’s a common value type we’re using and need to be applied this mechanism as well? Apple suggested us to implement a data structure named Ref & Box to support all value type:
You can find this official implementation from Apple/Swift: Advice: Use copy-on-write semantics for large values
By this suggestion, we can implement the Copy-On-Write for our Person struct above:
We have to wrap our struct inside another Box struct, it would be more boilerplate codes and not “Human-readable”. I have refactored this implementation by an open-source library named: CopyOnWriteSwift
You can install it easily via favorite dependency managers such as Cocoapods, Carthage & SwiftPackageManager. Now we can apply Copy-On-Write for any value types easier than ever just by an annotation: @CopyOnWrite
Conclusion: I hope Apple will apply Copy-On-Write mechanism for Structs by default in the future because nowadays we’re using Structs more frequently than Classes, particularly in Reactive Programming such as: SwiftUI + Combine or RxSwift + RxCocoa