Skip to content

WIP Add a config to use Compose for the runtime.#1442

Draft
zach-klippenstein wants to merge 8 commits intomainfrom
zachklipp/compose-impl-no-api
Draft

WIP Add a config to use Compose for the runtime.#1442
zach-klippenstein wants to merge 8 commits intomainfrom
zachklipp/compose-impl-no-api

Conversation

@zach-klippenstein
Copy link
Copy Markdown
Collaborator

@zach-klippenstein zach-klippenstein commented Jan 14, 2026

@zach-klippenstein zach-klippenstein force-pushed the zachklipp/compose-impl-no-api branch 4 times, most recently from 0cdbded to dcb59b7 Compare January 16, 2026 00:28
@zach-klippenstein zach-klippenstein force-pushed the zachklipp/compose-impl-no-api branch 3 times, most recently from 29a3309 to 9c29e1d Compare January 26, 2026 23:39
zach-klippenstein added a commit that referenced this pull request Jan 27, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 27, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 27, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 27, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 27, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 28, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 28, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 28, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
zach-klippenstein added a commit that referenced this pull request Jan 28, 2026
…time module. (2nd attempt)

First attempt was #1370, but got reverted in
#1378 due to it having broken something.

I need this in order to correctly consume Compose Multiplatform for the work migrating
the runtime to compose (#1442).

This reverts commit 58c1d40.
@zach-klippenstein zach-klippenstein force-pushed the zachklipp/compose-impl-no-api branch 2 times, most recently from 8804b5b to 2887966 Compare January 29, 2026 18:26
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Jan 29, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 2, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 2, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 2, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 2, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 3, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 3, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 3, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 3, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 3, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 3, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 3, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 4, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
zach-klippenstein added a commit that referenced this pull request Feb 4, 2026
These will be expanded on to measure the Compose runtime implementation
in #1442.
@zach-klippenstein zach-klippenstein force-pushed the zachklipp/compose-impl-no-api branch from 44e5792 to ee2d800 Compare February 21, 2026 00:24
See go/compose-based-workflows.
@zach-klippenstein zach-klippenstein force-pushed the zachklipp/compose-impl-no-api branch from ee2d800 to 471b273 Compare April 20, 2026 19:46
@zach-klippenstein zach-klippenstein force-pushed the zachklipp/compose-impl-no-api branch 2 times, most recently from 2a4bc7f to 5c9588d Compare May 5, 2026 23:46
zach-klippenstein and others added 5 commits May 5, 2026 16:57
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The default 1-minute runTest timeout fires for the slowest combinations
on physical devices, surfacing as UncompletedCoroutinesError instead of
a real benchmark result. The benchmark body itself is bounded by
measureRepeated, so widening the test timeout just lets the slow cases
finish.

Without this, 14 of 84 combinations timed out on a Galaxy A25.
Wrap renderWorkflow in rememberSkippableAndRestartableComposable, keyed
on (props, onOutput). When neither key changes and the producer hasn't
been invalidated by a state read, the entire render of that workflow
session is skipped and the cached rendering is returned. State-change
invalidation still flows through the producer's restart group, so
internal updates re-run the producer in the same frame.

Also switch the cache-update check in RememberComposable from equals to
identity. The pre-existing equals comparison violated the workflow
runtime contract that rendering equals/hashCode are allowed to throw,
breaking exceptions_from_renderings_equals_methods_do_not_fail_runtime.
For workflow renderings, equals-based dedup is meaningless anyway since
parent skipping already handles identity dedup; the only remaining job
of the cache check is "did the producer run? if so, take its output".

Microbenchmark deltas (Galaxy A25, ShallowBushyTree / SquareishTree):
- rerenderSingleSiblingByPropsChange:  -67% / -47%
- rerenderSingleSiblingViaStateChange: -58% / -87%
- wideSiblingKeys_rerenderSingleSiblingByPropsChange: -59% / resolved
- initialRenderNewSibling:             -55% / -40%
- tearDownSingleSibling:               -25% / resolved
With small regressions on initial-render-everything cases (around
+11% to +71%) where the wrapper's overhead can't amortize.
- jetbrains-compose-plugin: 1.7.3 -> 1.10.3
- androidx-compose-bom:     2025.03.01 -> 2026.04.01
- jdk-target:               1.8 -> 11

Compose Multiplatform 1.8+ requires JVM 11+ bytecode. The project's
toolchain was already 17, so bumping the target to 11 is mostly a
formality for downstream consumers.

Two unrelated Compose 1.10 deprecations are silenced at file scope so
this benchmark experiment doesn't get tangled up in their cleanup:
  - rememberSaveable(key = ...) is deprecated (RenderAsState.kt)
  - LocalSavedStateRegistryOwner moved to savedstate-compose
    (ScreenComposableFactory.kt)
And one unrelated Android deprecation in a sample (SampleLauncherApp).

Microbenchmark deltas (Compose runtime, on top of skipping):
- wideSiblingKeys_initialRenderAllChildren: -8% / -13%
- remember-heavy & stable-handlers cases:   -1% to -8%
- everything else: within +/-5%

Most of the remaining headroom turned out to already be captured by
skipping; the runtime-version bump is a modest additional win.
Run of dependencyGuardBaseline --refresh-dependencies after the Compose
upgrade. Picks up the new transitive deps from Compose Multiplatform
1.10.3 + AndroidX Compose BOM 2026.04.01.
@zach-klippenstein zach-klippenstein force-pushed the zachklipp/compose-impl-no-api branch from 5c9588d to e1888a4 Compare May 5, 2026 23:58
This internal interface had no implementations, no callers, and its
own KDoc referred to symbols that don't exist on this branch
(LocalWorkflowComposableRuntimeConfig, com.squareup.workflow1.compose
.renderChild). Looks like an early sketch of a Compose-native
interceptor shape that was abandoned in favor of reusing the existing
WorkflowInterceptor (plumbed through WorkflowComposableRuntimeConfig
and consumed in ComposeRenderContext).
Adds 51 unit tests across the compose-runtime helper types that aren't
exercised end-to-end by the existing RenderWorkflowInTest/etc. coverage:

  PeekableMutableStateTest      (10) - read/write, identity vs equals
                                       on the invalidator path, snapshot
                                       isolation.
  TrapdoorTest                  ( 7) - open(block & function form),
                                       inMovableGroup return values,
                                       runIfValueChanged change-detection
                                       semantics.
  RememberComposableTest        ( 8) - skip/run paths for both the
                                       skippable and skippable+restartable
                                       wrappers, plus a regression test
                                       that the cache no longer calls
                                       .equals() on the cached value.
  WithCompositionLocalsTest     ( 7) - default value, returned value,
                                       static locals, nesting,
                                       multi-local provision.
  WorkflowSnapshotSaverTest     ( 4) - snapshotState/initialState
                                       delegation, null-snapshot pass-
                                       through, scope plumbing,
                                       round-trip.
  SynchronizedMoleculeTest      ( 6) - first compose returns its value,
                                       per-call content updates,
                                       between-call state pickup,
                                       close() teardown, exception
                                       propagation.
  SerializableSaveableStateRegistryTest (jvm, 9) - canBeSaved predicate
                                       (Serializable / Function / non-
                                       Serializable / lists-of-lambdas),
                                       restoredValues / consumeRestored,
                                       registerProvider+unregister, and
                                       a doc-anchor test pinning the
                                       fact that toSnapshot() currently
                                       writes empty bytes (since the
                                       writeTo extension is commented
                                       out in the prod source).

Also adds a small TestComposition helper that hosts a SynchronizedMolecule
and applies snapshot writes immediately, so individual tests don't have
to coordinate with a real frame clock.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant