Repository navigation
Report compose session availability from onRemembered instead of a DisposableEffect [CLF-648] - #1593
Conversation
…sposableEffect. [CLF-648] ComposeRenderContext is already a RememberObserver, so the root node's onSessionAvailable callback can be invoked from onRemembered() rather than from a separate DisposableEffect in renderWorkflow. This removes an effect node and its slot table group from every workflow in the compose runtime. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
| // Reported from here rather than from a DisposableEffect in renderWorkflow so that the root | ||
| // node doesn't pay for an extra effect node and slot table group on every workflow (see | ||
| // CLF-648). |
There was a problem hiding this comment.
This comment is pointless, nobody reading this code in the future would question why this is here instead of an effect.
Microbenchmark results:
|
| Class | median Δ time | median Δ allocs |
|---|---|---|
| control (ShallowBushy, traditional runtime) | -1.7% | 0.0% |
| ShallowBushyTree_ComposeNoSkip | -4.1% | 0.0% |
| ShallowBushyTree_ComposeSkipping | +0.2% | 0.0% |
| SquareishTree_ComposeNoSkip | +2.3% | 0.0% |
| SquareishTree_ComposeSkipping | +1.5% | 0.0% |
Full per-benchmark table (median of measured iterations)
| Class | Benchmark | time main (µs) | time PR (µs) | Δ time | allocs main | allocs PR | Δ allocs |
|---|---|---|---|---|---|---|---|
| (default: ShallowBushy, traditional) | initialRenderAllChildren | 1,854.5 | 1,794.8 | -3.2% | 11,594 | 11,595 | +0.0% |
| (default: ShallowBushy, traditional) | initialRenderNewSibling | 234.7 | 226.6 | -3.5% | 1,486 | 1,486 | -0.0% |
| (default: ShallowBushy, traditional) | rememberManyEntries_changingInputs | 321.8 | 320.5 | -0.4% | 3,674 | 3,674 | -0.0% |
| (default: ShallowBushy, traditional) | rememberManyEntries_mixedInputTypes | 371.2 | 361.3 | -2.7% | 4,050 | 4,050 | -0.0% |
| (default: ShallowBushy, traditional) | rememberManyEntries_sameInputs | 287.5 | 294.2 | +2.3% | 3,050 | 3,050 | -0.0% |
| (default: ShallowBushy, traditional) | rerenderAllChildrenByPropsChange | 356.1 | 345.8 | -2.9% | 2,877 | 2,877 | +0.0% |
| (default: ShallowBushy, traditional) | rerenderAllChildrenViaStateChange | 495.0 | 506.6 | +2.3% | 3,842 | 3,842 | -0.0% |
| (default: ShallowBushy, traditional) | rerenderSingleSiblingByPropsChange | 195.1 | 191.0 | -2.1% | 1,396 | 1,396 | -0.0% |
| (default: ShallowBushy, traditional) | rerenderSingleSiblingViaStateChange | 204.2 | 200.8 | -1.7% | 1,400 | 1,400 | -0.0% |
| (default: ShallowBushy, traditional) | stableHandlers_manyCallbacks_propChange | 282.0 | 286.3 | +1.5% | 3,050 | 3,050 | +0.0% |
| (default: ShallowBushy, traditional) | tearDownAllChildren | 1,374.2 | 1,350.1 | -1.8% | 5,505 | 5,505 | -0.0% |
| (default: ShallowBushy, traditional) | tearDownSingleSibling | 250.5 | 243.3 | -2.9% | 1,404 | 1,404 | -0.0% |
| (default: ShallowBushy, traditional) | wideSiblingKeys_initialRenderAllChildren | 2,215.8 | 2,195.9 | -0.9% | 17,869 | 17,869 | -0.0% |
| (default: ShallowBushy, traditional) | wideSiblingKeys_rerenderSingleSiblingByPropsChange | 724.6 | 742.0 | +2.4% | 4,619 | 4,619 | +0.0% |
| ShallowBushyTree_ComposeNoSkip | initialRenderAllChildren | 2,374.5 | 2,232.6 | -6.0% | 10,863 | 10,862 | -0.0% |
| ShallowBushyTree_ComposeNoSkip | initialRenderNewSibling | 722.5 | 678.1 | -6.1% | 2,582 | 2,582 | -0.0% |
| ShallowBushyTree_ComposeNoSkip | rememberManyEntries_changingInputs | 480.9 | 499.7 | +3.9% | 2,865 | 2,865 | -0.0% |
| ShallowBushyTree_ComposeNoSkip | rememberManyEntries_mixedInputTypes | 560.7 | 538.9 | -3.9% | 3,241 | 3,241 | -0.0% |
| ShallowBushyTree_ComposeNoSkip | rememberManyEntries_sameInputs | 434.4 | 430.3 | -0.9% | 2,733 | 2,733 | -0.0% |
| ShallowBushyTree_ComposeNoSkip | rerenderAllChildrenByPropsChange | 607.9 | 566.5 | -6.8% | 1,931 | 1,931 | +0.0% |
| ShallowBushyTree_ComposeNoSkip | rerenderAllChildrenViaStateChange | 545.5 | 511.3 | -6.3% | 1,828 | 1,828 | +0.0% |
| ShallowBushyTree_ComposeNoSkip | rerenderSingleSiblingByPropsChange | 531.1 | 461.6 | -13.1% | 1,914 | 1,914 | +0.0% |
| ShallowBushyTree_ComposeNoSkip | rerenderSingleSiblingViaStateChange | 488.8 | 468.0 | -4.3% | 1,820 | 1,820 | -0.0% |
| ShallowBushyTree_ComposeNoSkip | stableHandlers_manyCallbacks_propChange | 422.4 | 420.0 | -0.6% | 2,733 | 2,733 | +0.0% |
| ShallowBushyTree_ComposeNoSkip | tearDownAllChildren | 1,597.9 | 1,608.3 | +0.7% | 5,036 | 5,036 | +0.0% |
| ShallowBushyTree_ComposeNoSkip | tearDownSingleSibling | 1,306.8 | 1,256.2 | -3.9% | 2,674 | 2,674 | +0.0% |
| ShallowBushyTree_ComposeNoSkip | wideSiblingKeys_initialRenderAllChildren | 3,278.6 | 3,287.9 | +0.3% | 15,854 | 15,854 | -0.0% |
| ShallowBushyTree_ComposeNoSkip | wideSiblingKeys_rerenderSingleSiblingByPropsChange | 605.9 | 572.7 | -5.5% | 1,533 | 1,533 | -0.0% |
| ShallowBushyTree_ComposeSkipping | initialRenderAllChildren | 2,408.0 | 2,428.8 | +0.9% | 11,619 | 11,619 | +0.0% |
| ShallowBushyTree_ComposeSkipping | initialRenderNewSibling | 540.6 | 542.7 | +0.4% | 1,190 | 1,190 | +0.0% |
| ShallowBushyTree_ComposeSkipping | rememberManyEntries_changingInputs | 527.1 | 503.8 | -4.4% | 2,867 | 2,867 | -0.0% |
| ShallowBushyTree_ComposeSkipping | rememberManyEntries_mixedInputTypes | 556.3 | 570.1 | +2.5% | 3,243 | 3,243 | -0.0% |
| ShallowBushyTree_ComposeSkipping | rememberManyEntries_sameInputs | 442.0 | 458.4 | +3.7% | 2,743 | 2,743 | +0.0% |
| ShallowBushyTree_ComposeSkipping | rerenderAllChildrenByPropsChange | 702.6 | 682.6 | -2.8% | 2,085 | 2,085 | +0.0% |
| ShallowBushyTree_ComposeSkipping | rerenderAllChildrenViaStateChange | 655.4 | 656.0 | +0.1% | 2,063 | 2,063 | -0.0% |
| ShallowBushyTree_ComposeSkipping | rerenderSingleSiblingByPropsChange | 300.0 | 296.2 | -1.3% | 514 | 514 | -0.0% |
| ShallowBushyTree_ComposeSkipping | rerenderSingleSiblingViaStateChange | 269.6 | 272.8 | +1.2% | 423 | 423 | -0.0% |
| ShallowBushyTree_ComposeSkipping | stableHandlers_manyCallbacks_propChange | 439.5 | 450.8 | +2.6% | 2,743 | 2,743 | -0.0% |
| ShallowBushyTree_ComposeSkipping | tearDownAllChildren | 1,840.0 | 1,787.4 | -2.9% | 5,041 | 5,041 | +0.0% |
| ShallowBushyTree_ComposeSkipping | tearDownSingleSibling | 1,165.9 | 1,135.7 | -2.6% | 1,275 | 1,275 | +0.0% |
| ShallowBushyTree_ComposeSkipping | wideSiblingKeys_initialRenderAllChildren | 4,864.8 | 4,688.5 | -3.6% | 18,359 | 18,359 | +0.0% |
| ShallowBushyTree_ComposeSkipping | wideSiblingKeys_rerenderSingleSiblingByPropsChange | 679.7 | 689.9 | +1.5% | 1,296 | 1,296 | +0.0% |
| SquareishTree_ComposeNoSkip | initialRenderAllChildren | 10,840.7 | 11,069.0 | +2.1% | 40,446 | 40,446 | +0.0% |
| SquareishTree_ComposeNoSkip | initialRenderNewSibling | 2,527.8 | 2,572.6 | +1.8% | 8,586 | 8,586 | -0.0% |
| SquareishTree_ComposeNoSkip | rememberManyEntries_changingInputs | 515.6 | 536.7 | +4.1% | 2,865 | 2,865 | +0.0% |
| SquareishTree_ComposeNoSkip | rememberManyEntries_mixedInputTypes | 541.3 | 582.8 | +7.7% | 3,241 | 3,241 | -0.0% |
| SquareishTree_ComposeNoSkip | rememberManyEntries_sameInputs | 433.0 | 447.6 | +3.4% | 2,733 | 2,733 | -0.0% |
| SquareishTree_ComposeNoSkip | rerenderAllChildrenByPropsChange | 2,649.7 | 2,635.9 | -0.5% | 8,453 | 8,453 | +0.0% |
| SquareishTree_ComposeNoSkip | rerenderAllChildrenViaStateChange | 2,304.6 | 2,357.0 | +2.3% | 8,344 | 8,344 | +0.0% |
| SquareishTree_ComposeNoSkip | rerenderSingleSiblingByPropsChange | 2,348.6 | 2,402.6 | +2.3% | 8,446 | 8,446 | +0.0% |
| SquareishTree_ComposeNoSkip | rerenderSingleSiblingViaStateChange | 2,174.1 | 2,118.0 | -2.6% | 8,331 | 8,331 | +0.0% |
| SquareishTree_ComposeNoSkip | stableHandlers_manyCallbacks_propChange | 419.0 | 439.8 | +4.9% | 2,733 | 2,733 | +0.0% |
| SquareishTree_ComposeNoSkip | tearDownAllChildren | 6,951.4 | 7,175.5 | +3.2% | 25,351 | 25,336 | -0.1% |
| SquareishTree_ComposeNoSkip | tearDownSingleSibling | 2,744.0 | 2,703.7 | -1.5% | 8,535 | 8,535 | -0.0% |
| SquareishTree_ComposeNoSkip | wideSiblingKeys_initialRenderAllChildren | 3,332.2 | 3,526.3 | +5.8% | 15,854 | 15,855 | +0.0% |
| SquareishTree_ComposeNoSkip | wideSiblingKeys_rerenderSingleSiblingByPropsChange | 621.8 | 565.2 | -9.1% | 1,533 | 1,533 | +0.0% |
| SquareishTree_ComposeSkipping | initialRenderAllChildren | 11,783.7 | 11,858.5 | +0.6% | 43,122 | 43,121 | -0.0% |
| SquareishTree_ComposeSkipping | initialRenderNewSibling | 1,971.9 | 2,020.0 | +2.4% | 4,243 | 4,243 | -0.0% |
| SquareishTree_ComposeSkipping | rememberManyEntries_changingInputs | 559.5 | 537.7 | -3.9% | 2,867 | 2,867 | +0.0% |
| SquareishTree_ComposeSkipping | rememberManyEntries_mixedInputTypes | 583.3 | 598.2 | +2.6% | 3,243 | 3,243 | +0.0% |
| SquareishTree_ComposeSkipping | rememberManyEntries_sameInputs | 468.1 | 461.7 | -1.4% | 2,743 | 2,743 | +0.0% |
| SquareishTree_ComposeSkipping | rerenderAllChildrenByPropsChange | 3,094.3 | 3,316.4 | +7.2% | 9,184 | 9,185 | +0.0% |
| SquareishTree_ComposeSkipping | rerenderAllChildrenViaStateChange | 2,982.3 | 2,962.1 | -0.7% | 9,444 | 9,444 | -0.0% |
| SquareishTree_ComposeSkipping | rerenderSingleSiblingByPropsChange | 1,742.3 | 1,690.3 | -3.0% | 4,095 | 4,095 | +0.0% |
| SquareishTree_ComposeSkipping | rerenderSingleSiblingViaStateChange | 246.2 | 265.8 | +8.0% | 336 | 336 | +0.0% |
| SquareishTree_ComposeSkipping | stableHandlers_manyCallbacks_propChange | 401.0 | 411.7 | +2.7% | 2,743 | 2,743 | +0.0% |
| SquareishTree_ComposeSkipping | tearDownAllChildren | 7,590.9 | 7,786.0 | +2.6% | 26,325 | 26,325 | -0.0% |
| SquareishTree_ComposeSkipping | tearDownSingleSibling | 2,134.6 | 2,202.3 | +3.2% | 4,185 | 4,185 | -0.0% |
| SquareishTree_ComposeSkipping | wideSiblingKeys_initialRenderAllChildren | 4,820.1 | 4,816.3 | -0.1% | 18,358 | 18,359 | +0.0% |
| SquareishTree_ComposeSkipping | wideSiblingKeys_rerenderSingleSiblingByPropsChange | 675.7 | 660.7 | -2.2% | 1,296 | 1,296 | +0.0% |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Follow-up from a review comment on #1442.
ComposeRenderContextis already aRememberObserver, so the root node'sonSessionAvailablecallback can be invoked fromonRemembered()instead of from a separateDisposableEffectinrenderWorkflow. This removes an effect node and its slot table group from the root workflow in the compose runtime.The callback is still only passed by
ComposeWorkflowNodefor the root workflow; child workflows passnull.Microbenchmarks against
mainare posted in a comment below: allocation counts are identical and time is within noise, as expected for a change that only touches the root node.Linear: CLF-648
🤖 Generated with Claude Code