Status Update
Comments
ys...@google.com <ys...@google.com> #2
Project: platform/frameworks/support
Branch: androidx-main
Author: Chris Craik <
Link:
Reimplement BenchmarkRule / BenchmarkState on top of coroutines
Expand for full commit details
Reimplement BenchmarkRule / BenchmarkState on top of coroutines
Test: benchmark-common, benchmark-junit4
Bug: 389149423
Fixes: 311242861
This refactor achieves several important goals:
- Move from the extremely complex stateful nature of BenchmarkState to layered suspending functions (the old state deferral system was very obtuse and brittle)
- Simplify the existing measureRepeatedOnMainThread yield behavior to use actual yield()
- Rewrite the thermal throttling sleep to yield() instead of sleep() (which works around ANRs when using measureRepeatedOnMainThread)
- Provide a clear config -> execution -> output control flow, including a clear top level measureRepeated function (which declares all its inputs, and almost wires up the outputs)
- Move as much logic as possible from the JUnit4 layer to benchmark-common
These will indirectly make it more possible to:
- Run trace post-processing within microbenchmark (e.g. interference detection and retry)
- More cleanly add configuration in MicrobenchmarkConfig (similar to what warmupCount / repeatCount BenchmarkState constructor params were previously trying to offer)
- Move benchmark-common to KMP if desired
- Write suspending variants of the benchmark APIs
The downsides are:
- Benchmarks with the `BenchmarkRule.getState().keepRunning()` pattern will no longer capture Perfetto traces
- In a follow up, a replacement API will be offered for Java that more closely matches kotlin
- BenchmarkState is implemented on top of a complex and custom coroutine logic mimicking a suspending sequence
- Ideally this implementation will be deprecated and not have to change much in the future
- Several experimental BenchmarkState APIs were removed, to make way for the new way of solving these problems (configuring benchmarks)
- The most useful of these moved to MicrobenchmarkConfig
The old BenchmarkRule/BenchmarkState are temporarily moved to internal
BenchmarkRuleLegacy/BenchmarkStateLegacy to enable easy internal
comparisons in the short term. Eventually these will be removed.
Relnote: "Refactored BenchmarkRule to be built on top of coroutines, and support better yield() behavior. This refactor removed several experimental BenchmarkState APIs, but will be followed by replacements as needed. Additionally, added runWithMeasurementDisabled to clarify behavior (all measurement is paused). In the future, runWithTimingDisabled will be deprecated."
Change-Id: I19837fc604b9e308957fc01ed009c0e921b8fe28
Files:
- M
benchmark/benchmark-common/api/current.txt
- M
benchmark/benchmark-common/api/restricted_current.txt
- M
benchmark/benchmark-common/build.gradle
- M
benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/BenchmarkStateLegacyConfigTest.kt
- M
benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/BenchmarkStateLegacyTest.kt
- M
benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/MicrobenchmarkPhaseConfigTest.kt
- M
benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
- M
benchmark/benchmark-common/src/main/java/androidx/benchmark/BenchmarkState.kt
- A
benchmark/benchmark-common/src/main/java/androidx/benchmark/BenchmarkStateLegacy.kt
- A
benchmark/benchmark-common/src/main/java/androidx/benchmark/Microbenchmark.kt
- M
benchmark/benchmark-common/src/main/java/androidx/benchmark/MicrobenchmarkConfig.kt
- A
benchmark/benchmark-common/src/main/java/androidx/benchmark/MicrobenchmarkOutput.kt
- M
benchmark/benchmark-common/src/main/java/androidx/benchmark/MicrobenchmarkPhase.kt
- M
benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt
- A
benchmark/benchmark-common/src/main/java/androidx/benchmark/TestDefinition.kt
- M
benchmark/benchmark-common/src/main/java/androidx/benchmark/ThrottleDetector.kt
- M
benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt
- M
benchmark/benchmark-junit4/api/current.txt
- M
benchmark/benchmark-junit4/api/restricted_current.txt
- M
benchmark/benchmark-junit4/src/androidTest/java/androidx/benchmark/junit4/BenchmarkRuleAnnotationTest.kt
- A
benchmark/benchmark-junit4/src/androidTest/java/androidx/benchmark/junit4/BenchmarkRuleLegacyTest.kt
- M
benchmark/benchmark-junit4/src/androidTest/java/androidx/benchmark/junit4/BenchmarkRuleTest.kt
- M
benchmark/benchmark-junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt
- A
benchmark/benchmark-junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRuleLegacy.kt
- M
benchmark/benchmark/src/androidTest/java/androidx/benchmark/benchmark/BenchmarkStateBenchmark.kt
- A
benchmark/benchmark/src/androidTest/java/androidx/benchmark/benchmark/BenchmarkStateLegacyBenchmark.kt
- A
benchmark/benchmark/src/androidTest/java/androidx/benchmark/benchmark/MeasureRepeatedSampleBenchmark.kt
- A
benchmark/benchmark/src/androidTest/java/androidx/benchmark/benchmark/TrivialKotlinBenchmarkLegacy.kt
- M
compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmarkBase.kt
Hash: 329bd0d25247f1eb6c683b921b8cd06f60bf3ad2
Date: Fri Jul 12 15:09:22 2024
am...@google.com <am...@google.com> #3
Shorter term follow up tasks:
- @Deprecate
runWithTimingDisabled
(not done in this CL to limit file changes) - Add more clarifying docs for new BenchmarkState implementation (in code comments as well as
)in the arch doc - Remove BenchmarkRuleLegacy / BenchmarkStateLegacy (after confirmed no significant regressions)
Longer term:
- Add replacements for removed BenchmarkState experimental APIs in MicrobenchmarkConfig (and probably need a MicrobenchmarkOutput)
dp...@phunware.com <dp...@phunware.com> #4
da...@gmail.com <da...@gmail.com> #5
am...@google.com <am...@google.com> #6
Have you tried to disable the render sandbox for this one?
da...@gmail.com <da...@gmail.com> #7
am...@google.com <am...@google.com> #8
When you click on the red error icon on the top-right corner of the preview, you should see the stacktrace you pasted in
Just to add more context, you're getting this error by a combination of two issues:
- A bug introduced in Compose 1.2.0-alpha06, but already fixed in 1.2.0-alpha07, that causes an error to be logged.
- Our logger, inherited from IntelliJ (
IdeaLogger
) being unable to log because of ourRenderSecurityManager
, which prevents access toSystem.getProperties()
. This one was fixed in Dolphin, and that's why you only see the issue in Bumblebee.
da...@gmail.com <da...@gmail.com> #9
ch...@gmail.com <ch...@gmail.com> #10
dp...@phunware.com <dp...@phunware.com> #11
Replying to
Did you add the missing dependencies? Using 1.2.0-alpha07
and manually adding the missing dependencies should work on Bumblebee without needing any extra steps.
debugImplementation "androidx.customview:customview:1.2.0-alpha01"
debugImplementation "androidx.customview:customview-poolingcontainer:1.0.0-alpha01"
ch...@gmail.com <ch...@gmail.com> #12
am...@google.com <am...@google.com> #13
Thanks for confirming the workaround works for now! We'll keep looking into fixing the root cause for this.
an...@steadfastinnovation.com <an...@steadfastinnovation.com> #14
I was able to work around the issue just by adding:
debugImplementation "androidx.customview:customview-poolingcontainer:1.0.0-alpha01"
I see that androidx.compose.ui:ui
depends on androidx.customview:customview-poolingcontainer
, so that makes sense, but I'm not seeing anything compose related that depends on androidx.customview:customview
(from the previous workaround suggestions).
I'm currently using 1.2.0-alpha07
. I've tested on Bumblebee Patch 3 and Dolphin Canary 8 and the workaround works on both.
FYI, this seems related to
na...@gmail.com <na...@gmail.com> #15
I'm also facing this problem. My compose version is 1.1.1.
The following classes could not be instantiated:
- androidx.compose.ui.tooling.ComposeViewAdapter (Open Class, Show Exception, Clear Cache)
Tip: Use View.isInEditMode() in your custom views to skip code or show sample data when shown in the IDE. If this is an unexpected error you can also try to build the project, then manually refresh the layout.
java.lang.ClassNotFoundException: android.view.OnBackInvokedCallback
at com.android.tools.idea.rendering.classloading.loaders.DelegatingClassLoader.findClass(DelegatingClassLoader.kt:81)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at com.android.tools.idea.rendering.classloading.loaders.DelegatingClassLoader.loadClass(DelegatingClassLoader.kt:65)
at androidx.compose.ui.tooling.ComposeViewAdapter$FakeOnBackPressedDispatcherOwner$1.<init>(ComposeViewAdapter.kt:738)
at androidx.compose.ui.tooling.ComposeViewAdapter.<init>(ComposeViewAdapter.kt:737)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.jetbrains.android.uipreview.ViewLoader.createNewInstance(ViewLoader.java:352)
at org.jetbrains.android.uipreview.ViewLoader.loadClass(ViewLoader.java:189)
at org.jetbrains.android.uipreview.ViewLoader.loadView(ViewLoader.java:149)
at com.android.tools.idea.rendering.LayoutlibCallbackImpl.loadView(LayoutlibCallbackImpl.java:301)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:417)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:428)
at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:332)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
at android.view.LayoutInflater.inflate(LayoutInflater.java:663)
at android.view.LayoutInflater.inflate(LayoutInflater.java:505)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:361)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:436)
at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:121)
at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:736)
at com.android.tools.idea.rendering.RenderTask.lambda$inflate$7(RenderTask.java:892)
at com.android.tools.idea.rendering.RenderExecutor$runAsyncActionWithTimeout$2.run(RenderExecutor.kt:187)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
am...@google.com <am...@google.com> #16
@Activity
At...@web.de <At...@web.de> #17
activity-version : 1.5.0-alpha04
am...@google.com <am...@google.com> #18
@
jn...@sammobile.com <jn...@sammobile.com> #19
activity: 1.6.0-alpha03
compose: 1.2.0-alpha08
I'm getting the same stacktrace #1 without these dependencies.
debugImplementation("androidx.customview:customview:1.2.0-alpha01")
debugImplementation("androidx.customview:customview-poolingcontainer:1.0.0-alpha01")
Adding those I get the following error instead
The following classes could not be instantiated:
- androidx.compose.ui.tooling.ComposeViewAdapter (Open Class, Show Exception, Clear Cache)
Tip: Use View.isInEditMode() in your custom views to skip code or show sample data when shown in the IDE. If this is an unexpected error you can also try to build the project, then manually refresh the layout.
java.lang.ClassNotFoundException: android.window.OnBackInvokedCallback
at com.android.tools.idea.rendering.classloading.loaders.DelegatingClassLoader.findClass(DelegatingClassLoader.kt:81)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at com.android.tools.idea.rendering.classloading.loaders.DelegatingClassLoader.loadClass(DelegatingClassLoader.kt:65)
at androidx.compose.ui.tooling.ComposeViewAdapter$FakeOnBackPressedDispatcherOwner$1.<init>(ComposeViewAdapter.kt:744)
at androidx.compose.ui.tooling.ComposeViewAdapter.<init>(ComposeViewAdapter.kt:743)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.jetbrains.android.uipreview.ViewLoader.createNewInstance(ViewLoader.java:339)
at org.jetbrains.android.uipreview.ViewLoader.loadClass(ViewLoader.java:176)
at org.jetbrains.android.uipreview.ViewLoader.loadView(ViewLoader.java:136)
at com.android.tools.idea.rendering.LayoutlibCallbackImpl.loadView(LayoutlibCallbackImpl.java:301)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:417)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:428)
at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:332)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
at android.view.LayoutInflater.inflate(LayoutInflater.java:663)
at android.view.LayoutInflater.inflate(LayoutInflater.java:505)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:363)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:436)
at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:121)
at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:739)
at com.android.tools.idea.rendering.RenderTask.lambda$inflate$8(RenderTask.java:895)
at com.android.tools.idea.rendering.RenderExecutor$runAsyncActionWithTimeout$2.run(RenderExecutor.kt:187)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
am...@google.com <am...@google.com> #20
@1.5.0-beta01
to see if it works for you?
jn...@sammobile.com <jn...@sammobile.com> #21
That did the trick.
implementation("androidx.activity:activity") {
version {
strictly("1.5.0-beta01") // 1.5.0-rc01 also works
}
}
It turns out that appcompat 1.6.0-alpha03 is using activity 1.6.0-alpha03.
By downgrading appcompat to 1.4.1 or 1.5.0-alpha01 also fixes the issue.
I also upgraded compose to 1.2.0-beta01 but that did not fix the issue
Customview is still required
debugImplementation("androidx.customview:customview:1.2.0-alpha01")
debugImplementation("androidx.customview:customview-poolingcontainer:1.0.0-beta01")
am...@google.com <am...@google.com> #22
"Customview is still required"
Yea, unfortunately the transitive dependencies bug was not resolved on the Compose side, so upgrading the library versions won't help. The problem was on how Android Studio resolves transitive runtime dependencies, and the fix will be available in Android Studio Dolphin. From that version, you won't need to specify the dependencies directly.
er...@gmail.com <er...@gmail.com> #23
da...@gmail.com <da...@gmail.com> #24
di...@google.com <di...@google.com>
nu...@gmail.com <nu...@gmail.com> #25
va...@gmail.com <va...@gmail.com> #26
I need to upgrade my activity version to support Android 13, but this issue is still forcing me to use 1.5.0-rc01. How can I work around or fix this issue to both be able to see previews and develop for activity 1.6.0-alpha?
vi...@gmail.com <vi...@gmail.com> #27
si...@zkb.ch <si...@zkb.ch> #28
am...@google.com <am...@google.com> #29
Can someone who reported the activity 1.6.0 bug try it on
si...@zkb.ch <si...@zkb.ch> #30
am...@google.com <am...@google.com> #31
@java.lang.ClassNotFoundException: android.window.OnBackInvokedCallback
?
Also, can you please confirm that you're setting compileSdk
to 33
in build.gradle? As mentioned in the Activity 1.6.0 33
.
Thanks!
am...@google.com <am...@google.com> #32
I can't repro the issue on Electric Eel (see the attached screenshot). I can gladly keep investigating, but I'd like to ask for snippets that are not working in Electric Eel with compileSdk 33
.
Another thing I'll do is to close this bug and keep track of the Activity investigation in androidx.customview.poolingcontainer.R$id
. This was fixed in Android Studio Dolphin, which is now in RC.
Please refer to
Thanks!
Er...@gtempaccount.com <Er...@gtempaccount.com> #33
Hello, I recently updated to Compose 1.2.1 and Compiler to 1.3.0. Also using Android Studio Chipmunk | 2021.2.1 Patch 2
I started to receive the error described in the OP.
Saw this issue is resolved but what is the final solution? I assume I don't need to use the workaround anymore. Is it to use Android Studio Electric Eel ?
Thank you
am...@google.com <am...@google.com> #34
I assume I don't need to use the workaround anymore
Correct. You won't need the workaround anymore. However, the fix will only be available in Dolphin, which will hopefully get to the stable channel soon. Thanks for your patience!
fr...@gmail.com <fr...@gmail.com> #35
We still have an issue with this in a newer version of Android Studio > Dolphin. Was this fixed or not?
Android Studio Jellyfish | 2023.3.1 Beta 2
Build #AI-233.14808.21.2331.11608968, built on March 21, 2024
Runtime version: 17.0.10+0-17.0.10b1087.21-11572160 x86_64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 14.4.1
GC: G1 Young Generation, G1 Old Generation
Memory: 4096M
Cores: 16
Metal Rendering is ON
Registry:
ide.instant.shutdown=false
Non-Bundled Plugins:
com.intellij.marketplace (233.14808.24)
wu.seal.tool.jsontokotlin (3.7.4)
am...@google.com <am...@google.com> #36
We still have an issue with this in a newer version of Android Studio > Dolphin
Can you please share the stacktrace you're hitting in Jellyfish?
Was this fixed or not?
The problem should have been fixed, yes. However, you might be hitting a different, but similar, problem. Can you please share more details about it, so we can investigate it further? Thanks!
mo...@rikstv.no <mo...@rikstv.no> #37
fr...@gmail.com <fr...@gmail.com> #38
Sorry I missed your message. This isn't an issue any more in the newest version Ladybug.
Description
Jetpack Compose component used: Any
Android Studio Build: Bumblebee Patch 2
Kotlin version: 1.6.10
Steps to Reproduce or Code Sample to Reproduce:
1. Create an Android project set up to use Jetpack Compose.
2. Create a library module, add a simple composable and add a preview to this library module.
3. Observe preview will not render.
Stack trace (if applicable):
java.lang.ClassNotFoundException: androidx.customview.poolingcontainer.R$id
at com.android.tools.idea.rendering.classloading.loaders.DelegatingClassLoader.findClass(DelegatingClassLoader.kt:81)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at com.android.tools.idea.rendering.classloading.loaders.DelegatingClassLoader.loadClass(DelegatingClassLoader.kt:65)
at androidx.customview.poolingcontainer.PoolingContainer.<clinit>(PoolingContainer.kt:121)
at androidx.compose.ui.platform.ViewCompositionStrategy$DisposeOnDetachedFromWindowIfNotInPoolingContainer.installFor(ViewCompositionStrategy.android.kt:97)
at androidx.compose.ui.platform.AbstractComposeView.<init>(ComposeView.android.kt:123)
at androidx.compose.ui.platform.ComposeView.<init>(ComposeView.android.kt:392)
at androidx.compose.ui.platform.ComposeView.<init>(ComposeView.android.kt:388)
at androidx.compose.ui.tooling.ComposeViewAdapter.<init>(ComposeViewAdapter.kt:131)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.jetbrains.android.uipreview.ViewLoader.createNewInstance(ViewLoader.java:352)
at org.jetbrains.android.uipreview.ViewLoader.loadClass(ViewLoader.java:189)
at org.jetbrains.android.uipreview.ViewLoader.loadView(ViewLoader.java:149)
at com.android.tools.idea.rendering.LayoutlibCallbackImpl.loadView(LayoutlibCallbackImpl.java:301)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:417)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:428)
at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:332)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
at android.view.LayoutInflater.inflate(LayoutInflater.java:663)
at android.view.LayoutInflater.inflate(LayoutInflater.java:505)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:361)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:436)
at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:121)
at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:736)
at com.android.tools.idea.rendering.RenderTask.lambda$inflate$7(RenderTask.java:892)
at com.android.tools.idea.rendering.RenderExecutor$runAsyncActionWithTimeout$2.run(RenderExecutor.kt:187)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)