COW đ
swift iOS COW copy-on-write Estimated reading time: 4 minutesSwift provides a lot of optimizations and swiftiness to our codebase and to the way how we can code and handle different cases. There are a lot of concepts, that help to make swiftiness real.
One of such concept - COW.
đ Not the one that eats grass and can give u milk, but a principle/idea that can be constructed from first letters - Copy-On-Write.
This principle provides a copy-on-write semantic for types that use it. This means, that we can get some boost in terms of performance and memory usage, even with a lot of elements in it.
The problem
Using values is fast and easy, but sometimes it may cost additional memory and performance.
If we simply perform a copy, we need additional memory for placing all the elements and additional time to do so, so performance will be lost.
But there are a lot of cases where u just need to pass an array (or another struct, array is just a sample) as a parameter to some function or for some iteration or to just have the same data in another obj. Do we need a copy in this case? The answer is no.
These cases are optimized and resolved thanks to copy-on-write semantics. This semantics can be used for any large value. The idea behind this is to do a copy only when we need it - when we edit the source.
Thatâs all the idea - not always create a copy of value for the variable that was used during assigning.
COW
Not all value types are coming with COW out of the box in Swift.
The COW is implemented as a feature for well-known data structures (array, dictionary, set) from the standard Swift library. This is done by Apple.
So, if u create a custom value type - this type doesnât have any implementation related to COW. But u can add it if u need this.
As one of the samples how u can do this - check Apple advice
The king of the process is isKnownUniquelyReferenced(_:)
function.
Example
As always, a good example is worth 1000 words. The best way to inspect how everything needs to be implemented - is to check a source code.
Letâs inspect URLRequest
class from Foundation
framework. If u do so, u can find next:
function _applyMutation
is the heart of the process. U can see, that under the hood, Swift use obj-C class NSMutableURLRequest
as a storage:
In case we modify something in the URLRequest
struct copy, the copy of the backed object is created.
Custom type and COW
The steps that is needs to be done, to use COW in our custom type are next:
- create a kind of storage - a place where uâr data will be stored.
- wrap to a struct, and use this storage under the hood
- on setting a new value / change, check with
isKnownUniquelyReferenced(_:)
to know if u needs to make a copy.
Here is a sample of data structure that uses COW - kind of FIFO.
The FIFO idea:
I didnât implement all functions needed for real FIFO, because this is not important right now.
Click to see the code
If u test the code above, u will see a message
as soon as u execute line fifo2.put(2)
.
Of cause, I can just use array as storage and this will give me COW for free, but the idea is to show the possible implementation of the COW in a custom data structure.
Resources
- Advice: Use copy-on-write semantics for large values
isKnownUniquelyReferenced(_:)
- FIFO
- âObjcIO >< - Optimizing Collectionsâ by Karoly Lorentey
- âSwift Protocol-Oriented Programmingâ by Jon Hoffman
Share on: