Replace SnapshotStateObserver.invalidated with ArraySet
Using ArraySet here removes iterator allocation for frequent state invalidations (e.g. on scroll)
Fixes: 224584836
Test: SnapshotStateObserverBenchmark#notifyChanges (lower alloc count)
Change-Id: I4809ae362fd88e1aef7c49c726e3fe9638a3d597
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
index 6b31b4e..6bfd57c 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
@@ -91,9 +91,7 @@
* Remove all values from the set.
*/
fun clear() {
- for (i in 0 until size) {
- values[i] = null
- }
+ values.fill(null)
size = 0
}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
index 2e0396c..b7f31f9 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
@@ -21,6 +21,7 @@
import androidx.compose.runtime.TestOnly
import androidx.compose.runtime.collection.IdentityArrayIntMap
import androidx.compose.runtime.collection.IdentityArrayMap
+import androidx.compose.runtime.collection.IdentityArraySet
import androidx.compose.runtime.collection.IdentityScopeMap
import androidx.compose.runtime.collection.mutableVectorOf
import androidx.compose.runtime.observeDerivedStateRecalculations
@@ -261,7 +262,7 @@
/**
* Scopes that were invalidated during previous apply step.
*/
- private val invalidated = hashSetOf<Any>()
+ private val invalidated = IdentityArraySet<Any>()
// derived state handling
@@ -417,7 +418,7 @@
// Invalidate only if currentValue is different than observed on read
if (!policy.equivalent(derivedState.currentValue, previousValue)) {
valueToScopes.forEachScopeOf(derivedState) { scope ->
- invalidated += scope
+ invalidated.add(scope)
hasValues = true
}
}
@@ -425,7 +426,7 @@
}
valueToScopes.forEachScopeOf(value) { scope ->
- invalidated += scope
+ invalidated.add(scope)
hasValues = true
}
}
@@ -436,7 +437,7 @@
* Call [onChanged] for previously invalidated scopes.
*/
fun notifyInvalidatedScopes() {
- invalidated.forEach(onChanged)
+ invalidated.fastForEach(onChanged)
invalidated.clear()
}
}