Efficiently Mutating Nested Swift Data Structures
That feel when you’re profiling a React Native app, and you’re sure JavaScript is the source of your problems… but no, it’s ridiculously misoptimized Swift doing… well… nothing much for two minutes.
[…]
Code does something that seems completely reasonable, but ends up creating a new copy of a large
Set
10,000s times. Not entirely sure if Swift is supposed to be smart enough to figure out that it can safely mutate it, or it’s programmer’s responsibility.The intention is to insert to a
Set
that’s in aDictionary
that’s a mutable variable on a class
Older versions could not modify values in dictionaries without copying them, but 5.0 and later should be able to.
Yep,
Array
&Dictionary
both support in-place mutations. ForDictionary
, the recommended way is to use the defaulting subscript. E.g., this won’t make a CoW copy:sets[key, default: Set()].insert(foo)But this will:
var tmp = sets[key] tmp.insert(foo) sets[key] = tmpThe
Dictionary.Values
collection also supports this, and it may come handy if you need to distinguish between existing and new keys:if let i = sets.index(forKey: key) { sets.values[i].insert(foo) } else { fatalError("Unknown key \(key)") }
I’ve written about this before, but I think it’s worth re-emphasizing how this works. It’s counterintuitive and unusual in programming for introducing a temporary variable, as people often do when debugging, to radically change the behavior of the code. Copy-on-write is a leaky abstraction.
Previously:
Update (2019-11-02): See also: Karoy Lorentey.
2 Comments RSS · Twitter
Agreed, COW does not quite accomplish its goal of freeing the user from having to think of the memory implications of manipulating arrays as value types. It's a very primitive optimization, but at least it's fairly easy to reason about once you are aware. Now that swift 5 does the right thing with nested collections, it behaves predictably and it can be managed.
Most languages don't even try, and arrays are always references, which brings its own set of issues...