Lazily compute whether attribute changed in _attributeModified(_:old:new:) #1237
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
_attributeModified
is called when an attribute value in an attribute storage dictionary was replaced by a new value. It is responsible for enforcing the invalidation constraints on attributes by removing any dependent attributes from the storage (recursively). Currently (assuming both a new and old value exist) this function unconditionally compares the new and old values to return early if the value didn't change (meaning attributes shouldn't be invalidated). However, this requires unboxing the existential attribute values and calling through to their==
implementation which can be expensive. Instead, we can make this calculation lazy, only performing it when we actually find another attribute dependent upon the changed one. In cases where there are no dependent attributes, we avoid the equality check altogether as it is unnecessary. This shows about a 6% to 11% improvement in thesetAttribute
benchmark: