Skip to content

Commit d48eaf6

Browse files
Cleanup Side Effects; Able to Freeze
1 parent b7732ca commit d48eaf6

File tree

49 files changed

+623
-458
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+623
-458
lines changed

benchmarks/performance-poetry/complex-poetry/src/androidTest/java/com/squareup/benchmarks/performance/complex/poetry/ComposeInheritanceTest.kt

Lines changed: 0 additions & 59 deletions
This file was deleted.

benchmarks/performance-poetry/complex-poetry/src/androidTest/java/com/squareup/benchmarks/performance/complex/poetry/RenderPassTest.kt

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.test.platform.app.InstrumentationRegistry
88
import androidx.test.uiautomator.UiDevice
99
import com.squareup.benchmarks.performance.complex.poetry.PerformancePoetryActivity.Companion.EXTRA_PERF_CONFIG_INITIALIZING
1010
import com.squareup.benchmarks.performance.complex.poetry.PerformancePoetryActivity.Companion.EXTRA_PERF_CONFIG_REPEAT
11+
import com.squareup.benchmarks.performance.complex.poetry.PerformancePoetryActivity.Companion.EXTRA_RUNTIME_COMPOSE_RUNTIME
1112
import com.squareup.benchmarks.performance.complex.poetry.PerformancePoetryActivity.Companion.EXTRA_RUNTIME_FRAME_TIMEOUT
1213
import com.squareup.benchmarks.performance.complex.poetry.cyborgs.landscapeOrientation
1314
import com.squareup.benchmarks.performance.complex.poetry.cyborgs.openRavenAndNavigate
@@ -16,6 +17,7 @@ import com.squareup.benchmarks.performance.complex.poetry.cyborgs.waitForPoetry
1617
import com.squareup.benchmarks.performance.complex.poetry.instrumentation.RenderPassCountingInterceptor
1718
import org.junit.Assert.fail
1819
import org.junit.Before
20+
import org.junit.Ignore
1921
import org.junit.Test
2022
import org.junit.runner.RunWith
2123

@@ -30,7 +32,8 @@ class RenderPassTest {
3032
val useInitializingState: Boolean,
3133
val useHighFrequencyRange: Boolean,
3234
val baselineExpectation: RenderExpectation,
33-
val frameTimeoutExpectation: RenderExpectation
35+
val frameTimeoutExpectation: RenderExpectation,
36+
val frameTimeoutComposeExpectation: RenderExpectation
3437
)
3538

3639
data class RenderExpectation(
@@ -56,15 +59,15 @@ class RenderPassTest {
5659
}
5760

5861
@Test fun renderPassCounterBaselineComplexWithInitializingState() {
59-
runRenderPassCounter(COMPLEX_INITIALIZING, useFrameTimeout = false)
62+
runRenderPassCounter(COMPLEX_INITIALIZING)
6063
}
6164

6265
@Test fun renderPassCounterBaselineComplexNoInitializingState() {
63-
runRenderPassCounter(COMPLEX_NO_INITIALIZING, useFrameTimeout = false)
66+
runRenderPassCounter(COMPLEX_NO_INITIALIZING)
6467
}
6568

6669
@Test fun renderPassCounterBaselineComplexNoInitializingStateHighFrequencyEvents() {
67-
runRenderPassCounter(COMPLEX_NO_INITIALIZING_HIGH_FREQUENCY, useFrameTimeout = false)
70+
runRenderPassCounter(COMPLEX_NO_INITIALIZING_HIGH_FREQUENCY)
6871
}
6972

7073
@Test fun renderPassCounterFrameTimeoutComplexWithInitializingState() {
@@ -79,19 +82,43 @@ class RenderPassTest {
7982
runRenderPassCounter(COMPLEX_NO_INITIALIZING_HIGH_FREQUENCY, useFrameTimeout = true)
8083
}
8184

85+
@Ignore(
86+
"Not sure why but this gets stuck on initializing. Compose doesn't get the next" +
87+
" frame when this is started by the test, but it does when running directly."
88+
)
89+
@Test fun renderPassCounterFrameTimeoutComposeComplexWithInitializingState() {
90+
runRenderPassCounter(COMPLEX_INITIALIZING, useFrameTimeout = true, useCompose = true)
91+
}
92+
93+
@Test fun renderPassCounterFrameTimeoutComposeComplexNoInitializingState() {
94+
runRenderPassCounter(COMPLEX_NO_INITIALIZING, useFrameTimeout = true, useCompose = true)
95+
}
96+
97+
@Test fun renderPassCounterFrameTimeoutComposeComplexNoInitializingStateHighFrequencyEvents() {
98+
runRenderPassCounter(
99+
COMPLEX_NO_INITIALIZING_HIGH_FREQUENCY,
100+
useFrameTimeout = true,
101+
useCompose = true
102+
)
103+
}
104+
82105
private fun runRenderPassCounter(
83106
scenario: Scenario,
84-
useFrameTimeout: Boolean
107+
useFrameTimeout: Boolean = false,
108+
useCompose: Boolean = false
85109
) {
110+
if (useCompose) require(useFrameTimeout) { "Only use Compose Frame Timeout." }
111+
86112
val intent = Intent(context, PerformancePoetryActivity::class.java).apply {
87113
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
88114
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
89115
putExtra(
90116
EXTRA_PERF_CONFIG_INITIALIZING,
91117
scenario.useInitializingState
92118
)
119+
putExtra(EXTRA_RUNTIME_FRAME_TIMEOUT, useFrameTimeout)
93120
if (useFrameTimeout) {
94-
putExtra(EXTRA_RUNTIME_FRAME_TIMEOUT, useFrameTimeout)
121+
putExtra(EXTRA_RUNTIME_COMPOSE_RUNTIME, useCompose)
95122
}
96123
if (scenario.useHighFrequencyRange) {
97124
putExtra(EXTRA_PERF_CONFIG_REPEAT, PerformancePoetryActivity.HIGH_FREQUENCY_REPEAT_COUNT)
@@ -111,11 +138,19 @@ class RenderPassTest {
111138
device.openRavenAndNavigate()
112139

113140
val expectation =
114-
if (useFrameTimeout) scenario.frameTimeoutExpectation else
141+
if (useFrameTimeout) {
142+
if (useCompose) {
143+
scenario.frameTimeoutComposeExpectation
144+
} else {
145+
scenario.frameTimeoutExpectation
146+
}
147+
} else {
115148
scenario.baselineExpectation
149+
}
116150

117151
val title = if (useFrameTimeout) {
118-
"Runtime: FrameTimeout; "
152+
val usingCompose = if (useCompose) "(Using Compose Optimizations)" else "(No Compose)"
153+
"Runtime: FrameTimeout $usingCompose;"
119154
} else {
120155
"Runtime: RenderPerAction; "
121156
} + scenario.title
@@ -227,6 +262,11 @@ class RenderPassTest {
227262
totalPasses = 41..42,
228263
freshRenderedNodes = 85..85,
229264
staleRenderedNodes = 436..436
265+
),
266+
frameTimeoutComposeExpectation = RenderExpectation(
267+
totalPasses = 41..42,
268+
freshRenderedNodes = 85..85,
269+
staleRenderedNodes = 436..436
230270
)
231271
)
232272

@@ -243,6 +283,11 @@ class RenderPassTest {
243283
totalPasses = 40..41,
244284
freshRenderedNodes = 83..83,
245285
staleRenderedNodes = 431..431
286+
),
287+
frameTimeoutComposeExpectation = RenderExpectation(
288+
totalPasses = 40..41,
289+
freshRenderedNodes = 113..113,
290+
staleRenderedNodes = 82..82
246291
)
247292
)
248293

@@ -270,9 +315,14 @@ class RenderPassTest {
270315
staleRenderedNodes = 2350..2350
271316
),
272317
frameTimeoutExpectation = RenderExpectation(
273-
totalPasses = 64..68,
318+
totalPasses = 60..64,
274319
freshRenderedNodes = 106..108,
275320
staleRenderedNodes = 679..698
321+
),
322+
frameTimeoutComposeExpectation = RenderExpectation(
323+
totalPasses = 59..64,
324+
freshRenderedNodes = 259..259,
325+
staleRenderedNodes = 207..207
276326
)
277327
)
278328

benchmarks/performance-poetry/complex-poetry/src/main/java/com/squareup/benchmarks/performance/complex/poetry/PerformancePoemWorkflow.kt

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com.squareup.benchmarks.performance.complex.poetry
22

33
import androidx.compose.runtime.Composable
4-
import androidx.compose.runtime.MutableState
5-
import androidx.compose.runtime.mutableStateOf
6-
import androidx.compose.runtime.remember
74
import com.squareup.benchmarks.performance.complex.poetry.PerformancePoemWorkflow.Action.ClearSelection
85
import com.squareup.benchmarks.performance.complex.poetry.PerformancePoemWorkflow.Action.HandleStanzaListOutput
96
import com.squareup.benchmarks.performance.complex.poetry.PerformancePoemWorkflow.Action.SelectNext
@@ -20,7 +17,6 @@ import com.squareup.benchmarks.performance.complex.poetry.views.BlankScreen
2017
import com.squareup.sample.container.overviewdetail.OverviewDetailScreen
2118
import com.squareup.sample.poetry.PoemWorkflow
2219
import com.squareup.sample.poetry.PoemWorkflow.ClosePoem
23-
import com.squareup.sample.poetry.StanzaListScreen
2420
import com.squareup.sample.poetry.StanzaListWorkflow
2521
import com.squareup.sample.poetry.StanzaListWorkflow.NO_SELECTED_STANZA
2622
import com.squareup.sample.poetry.StanzaScreen
@@ -326,7 +322,7 @@ class PerformancePoemWorkflow(
326322
.copy(selection = stanzaIndex)
327323

328324
if (stanzaIndex != NO_SELECTED_STANZA) {
329-
val previousStanzas = renderProps.stanzas.subList(0, stanzaIndex)
325+
val stackedStanzas = renderProps.stanzas.subList(0, stanzaIndex + 1)
330326
.mapIndexed { index, _ ->
331327
context.ChildRendering(
332328
StanzaWorkflow,
@@ -337,36 +333,20 @@ class PerformancePoemWorkflow(
337333
),
338334
key = "$index",
339335
) {
340-
noAction()
336+
when (it) {
337+
CloseStanzas -> ClearSelection(simulatedPerfConfig)
338+
ShowPreviousStanza -> SelectPrevious(simulatedPerfConfig)
339+
ShowNextStanza -> SelectNext(simulatedPerfConfig)
340+
}
341341
}
342-
}
343-
val visibleStanza = context.ChildRendering(
344-
StanzaWorkflow,
345-
Props(
346-
poem = renderProps,
347-
index = stanzaIndex,
348-
eventHandlerTag = ActionHandlingTracingInterceptor::keyForTrace
349-
),
350-
key = "$stanzaIndex",
351-
) {
352-
when (it) {
353-
CloseStanzas -> ClearSelection(simulatedPerfConfig)
354-
ShowPreviousStanza -> SelectPrevious(simulatedPerfConfig)
355-
ShowNextStanza -> SelectNext(simulatedPerfConfig)
356-
}
357-
}
358-
359-
val stackedStanzas = visibleStanza.let {
360-
(previousStanzas + it).toBackStackScreen<Screen>()
361-
}
342+
}.toBackStackScreen<Screen>()
362343

363344
return OverviewDetailScreen(
364345
overviewRendering = BackStackScreen(stanzaListOverview),
365346
detailRendering = stackedStanzas
366347
)
367348
}
368349

369-
370350
return OverviewDetailScreen(
371351
overviewRendering = BackStackScreen(stanzaListOverview),
372352
selectDefault = {

benchmarks/performance-poetry/complex-poetry/src/main/java/com/squareup/benchmarks/performance/complex/poetry/PerformancePoemsBrowserWorkflow.kt

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
2525
import com.squareup.workflow1.ui.container.BackStackScreen
2626
import kotlinx.coroutines.delay
2727
import kotlinx.coroutines.flow.MutableStateFlow
28+
import java.lang.IllegalStateException
2829

2930
/**
3031
* Version of [PoemsBrowserWorkflow] that takes in a [SimulatedPerfConfig] to control the
@@ -161,6 +162,22 @@ class PerformancePoemsBrowserWorkflow(
161162
renderState: State,
162163
context: RenderContext,
163164
): OverviewDetailScreen {
165+
166+
// Again, then entire `Initializing` state is a smell, which is most obvious from the
167+
// use of `Worker.from { Unit }`. A Worker doing no work and only shuttling the state
168+
// along is usually the sign you have an extraneous state that can be collapsed!
169+
// Don't try this at home.
170+
if (renderState is Initializing) {
171+
context.runningWorker(TraceableWorker.from("BrowserInitializing") { Unit }, "init") {
172+
isLoading.value = true
173+
action {
174+
isLoading.value = false
175+
state = NoSelection
176+
}
177+
}
178+
return OverviewDetailScreen(overviewRendering = BackStackScreen(BlankScreen))
179+
}
180+
164181
val poemListProps = Props(
165182
poems = renderProps,
166183
eventHandlerTag = ActionHandlingTracingInterceptor::keyForTrace
@@ -174,26 +191,12 @@ class PerformancePoemsBrowserWorkflow(
174191
choosePoem(selected)
175192
}
176193
when (renderState) {
177-
// Again, then entire `Initializing` state is a smell, which is most obvious from the
178-
// use of `Worker.from { Unit }`. A Worker doing no work and only shuttling the state
179-
// along is usually the sign you have an extraneous state that can be collapsed!
180-
// Don't try this at home.
181-
is Initializing -> {
182-
context.runningWorker(TraceableWorker.from("BrowserInitializing") { Unit }, "init") {
183-
isLoading.value = true
184-
action {
185-
isLoading.value = false
186-
state = NoSelection
187-
}
188-
}
189-
return OverviewDetailScreen(overviewRendering = BackStackScreen(BlankScreen))
190-
}
191194
is NoSelection -> {
192195
return OverviewDetailScreen(
193-
overviewRendering = BackStackScreen(
194-
poemListRendering.copy(selection = NO_POEM_SELECTED)
195-
)
196+
overviewRendering = BackStackScreen(
197+
poemListRendering.copy(selection = NO_POEM_SELECTED)
196198
)
199+
)
197200
}
198201
is ComplexCall -> {
199202
context.runningWorker(
@@ -243,8 +246,10 @@ class PerformancePoemsBrowserWorkflow(
243246
key = "",
244247
) { clearSelection }
245248
}
249+
else -> {
250+
throw IllegalStateException("$renderState state is impossible.")
251+
}
246252
}
247-
248253
}
249254

250255
override fun snapshotState(state: State): Snapshot? = null

benchmarks/performance-poetry/complex-poetry/src/main/java/com/squareup/benchmarks/performance/complex/poetry/PerformancePoetryActivity.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ class PerformancePoetryActivity : AppCompatActivity() {
8484
}
8585

8686
val isFrameTimeout = intent.getBooleanExtra(EXTRA_RUNTIME_FRAME_TIMEOUT, false)
87+
val useCompose = intent.getBooleanExtra(EXTRA_RUNTIME_COMPOSE_RUNTIME, false)
8788
val runtimeConfig = if (isFrameTimeout) {
88-
FrameTimeout(useComposeInRuntime = true)
89+
FrameTimeout(useComposeInRuntime = useCompose)
8990
} else {
9091
RenderPerAction
9192
}
@@ -247,6 +248,8 @@ class PerformancePoetryActivity : AppCompatActivity() {
247248
const val EXTRA_PERF_CONFIG_DELAY = "complex.poetry.performance.config.delay.length"
248249
const val EXTRA_RUNTIME_FRAME_TIMEOUT =
249250
"complex.poetry.performance.config.runtime.frametimeout"
251+
const val EXTRA_RUNTIME_COMPOSE_RUNTIME =
252+
"complex.poetry.performance.config.runtime.compose"
250253

251254
const val SELECT_ON_TIMEOUT_LOG_NAME =
252255
"kotlinx.coroutines.selects.SelectBuilderImpl\$onTimeout\$\$inlined\$Runnable"

benchmarks/performance-poetry/complex-poetry/src/main/java/com/squareup/benchmarks/performance/complex/poetry/cyborgs/PoetryCyborgs.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ fun UiDevice.resetToRootPoetryList() {
4848
*/
4949
fun UiDevice.openRavenAndNavigate() {
5050
waitForIdle()
51+
waitForIdle(5_000)
5152
waitForAndClick(RavenPoemSelector)
5253
waitForLoadingInterstitial()
5354
waitForAndClick(By.textStartsWith("Deep into that darkness peering"))

0 commit comments

Comments
 (0)