Skip to content

Commit

Permalink
introduce SignalsMountState
Browse files Browse the repository at this point in the history
Summary:
## What?
The current approach for mount requires all render units to update their binders and defer skipping of content binding to their individual binders. This is not only time consuming but also inefficient and wasteful memory wise as we cache dummy evaluation results for all mount signals (extensions and mount binders).

To make mount more efficient, we must be able to skip updates for render units that do not have any transitive signal dependencies.

## How?
We extend `MountState` and track invocations of the major mount operations:
- initial mount
- updates
- unmounts

Tracking the first two operations gives us the opportunity to figure the set of render units that access signals so that we limit future updates to them. Tracking the last operation allows us to trim the tracked render units as needed.

Doing all of these makes updates faster because we skip a good portion of the tree on updates and only restrict updates to render units that access signals which have changed or render units that have new binders or are affected by changed layout data. It also helps that the dependency tree for render units is shallow too so we spend less time on updates.

Reviewed By: rooju

Differential Revision: D62671753

fbshipit-source-id: 7edf36c40d66371e476d9b7e15a7fc84dc57f4f0
  • Loading branch information
Daniel Famakin authored and facebook-github-bot committed Oct 1, 2024
1 parent 9a29e83 commit 2cd664e
Showing 1 changed file with 36 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import com.facebook.rendercore.utils.isEqualOrEquivalentTo
import java.util.ArrayList
import java.util.HashMap

class MountState
open class MountState
@JvmOverloads
constructor(
private val _rootHost: Host,
Expand Down Expand Up @@ -501,7 +501,7 @@ constructor(

private fun isMounted(id: Long): Boolean = idToMountedItemMap[id] != null

private fun mountRenderUnit(renderTreeNode: RenderTreeNode) {
protected open fun mountRenderUnit(renderTreeNode: RenderTreeNode) {
if (renderTreeNode.renderUnit.id == ROOT_HOST_ID) {
mountRootItem(renderTreeNode)
return
Expand Down Expand Up @@ -845,8 +845,7 @@ constructor(
currentMountItem.update(renderTreeNode)
currentRenderUnit.onStartUpdateRenderUnit()
mountDelegate?.startNotifyVisibleBoundsChangedSection()
if (currentRenderUnit.shouldUpdate(renderUnit) ||
!isEqualOrEquivalentTo(currentLayoutData, newLayoutData)) {
if (shouldUpdateMountItem(currentRenderUnit, renderUnit, currentLayoutData, newLayoutData)) {
val traceIdentifier =
DebugEventDispatcher.generateTraceIdentifier(DebugEvent.RenderUnitUpdated)
if (traceIdentifier != null) {
Expand All @@ -865,16 +864,13 @@ constructor(
if (isTracing) {
tracer.beginSection("UpdateItem: ${renderUnit.description}")
}
renderUnit.updateBinders(
context,
updateRenderUnitBinders(
content,
renderUnit,
currentRenderUnit,
currentLayoutData,
newLayoutData,
mountDelegate,
currentMountItem.bindData,
currentMountItem.isBound,
tracer)
currentMountItem)
if (isTracing) {
tracer.endSection()
}
Expand All @@ -896,6 +892,36 @@ constructor(
currentRenderUnit.onEndUpdateRenderUnit()
}

protected open fun shouldUpdateMountItem(
currentRenderUnit: RenderUnit<*>,
renderUnit: RenderUnit<*>,
currentLayoutData: Any?,
newLayoutData: Any?,
): Boolean {
return currentRenderUnit !== renderUnit ||
!isEqualOrEquivalentTo(currentLayoutData, newLayoutData)
}

protected open fun updateRenderUnitBinders(
content: Any,
renderUnit: RenderUnit<Any>,
currentRenderUnit: RenderUnit<Any>,
currentLayoutData: Any?,
newLayoutData: Any?,
currentMountItem: MountItem,
) {
renderUnit.updateBinders(
context,
content,
currentRenderUnit,
currentLayoutData,
newLayoutData,
_mountDelegate,
currentMountItem.bindData,
currentMountItem.isBound,
tracer)
}

private fun maybeEnsureParentIsMounted(node: RenderTreeNode, parent: RenderUnit<*>) {
if (ensureParentMounted && !isMounted(parent.id)) {
mountRenderUnit(node)
Expand Down

0 comments on commit 2cd664e

Please sign in to comment.