Verifying and avoiding copy-on-write overhead
CoW mechanics and mutation patterns.
confirm extra copies via isKnownUniquelyReferenced or instruments and the retain trace; ensure unique references, mutate inout/in place, reserveCapacity, avoid aliasing.
WHAT THIS TESTS It checks whether you understand the precise condition that triggers a copy-on-write copy and can both prove and prevent it, rather than hand-waving about value semantics.
HOW COW WORKS Standard collections share an underlying buffer until a mutation happens while the buffer is referenced more than once. At that mutation the buffer is deep-copied so the writer gets a private copy. A copy is not caused by mere assignment or passing; it is caused by mutating a non-uniquely-referenced buffer.
VERIFYING IT Profile with Instruments and look for unexpected memory allocations or large memcpy and retain or release activity inside the hot function. For your own CoW types, instrument the copy path or assert with isKnownUniquelyReferenced on the backing storage to see whether uniqueness is being lost. A common tell is that the array is captured or stored elsewhere, bumping its reference count just before you mutate.
GUARANTEEING IN-PLACE MUTATION Keep a single owner of the array. Mutate through an inout parameter or directly on a local var so the buffer stays uniquely referenced. Avoid passing the array to anything that retains it during the mutation window, and avoid capturing it in escaping closures. Call reserveCapacity up front to prevent repeated reallocation as the array grows. For custom storage, use isKnownUniquelyReferenced to copy only when truly shared.
COMMON WRONG ANSWERS Declaring CoW the culprit without proving a copy fired. Thinking passing an array to a function always copies it. Believing let versus var changes CoW behavior of the buffer itself.
LIKELY FOLLOW-UPS What exactly makes a buffer non-uniquely referenced? How does isKnownUniquelyReferenced work? Why does capturing in an escaping closure matter? When does reserveCapacity help most?
ONE CONCRETE EXAMPLE A function stores the working array in a property and also mutates a local copy in a loop. Each mutation sees a reference count above one and deep-copies the buffer per iteration. Refactoring to mutate the property in place through a single owner, plus reserveCapacity before the loop, eliminates the repeated copies and the function speeds up sharply.
Read the original → github.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.