Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OOM when snapshotting multiple lottie files #1669

Open
jamesrapadmi opened this issue Oct 31, 2024 · 4 comments
Open

OOM when snapshotting multiple lottie files #1669

jamesrapadmi opened this issue Oct 31, 2024 · 4 comments
Labels
bug Something isn't working waiting on user Waiting on information from OP

Comments

@jamesrapadmi
Copy link

Description
I have a project with a lot of screenshots (2000+). One series of the tests are now failing with an OOM. This is caused by Canvas.getMatrix() on the NopCanvas returning an erroneous matrix of Matrix{[8.6342721E14, 1.85162577E15, 1.9006225E20][-3.56884751E15, 1.66418037E15, 1.17585415E20][0.0, 0.0, 1.0]} this then causes lottie to attempt to allocate a max size bitmap which causes the crash. (Issue occurs on this line)

java.lang.OutOfMemoryError
	at android.graphics.Bitmap.nativeCreate(Native Method)
	at android.graphics.Bitmap.createBitmap(Bitmap.java:1206)
	at android.graphics.Bitmap.createBitmap(Bitmap.java:1163)
	at android.graphics.Bitmap.createBitmap(Bitmap.java:1111)
	at android.graphics.Bitmap.createBitmap(Bitmap.java:1070)
	at com.airbnb.lottie.LottieDrawable.ensureSoftwareRenderingBitmap(LottieDrawable.java:1812)
	at com.airbnb.lottie.LottieDrawable.renderAndDrawAsBitmap(LottieDrawable.java:1765)
	at com.airbnb.lottie.LottieDrawable.draw(LottieDrawable.java:772)
	at com.airbnb.lottie.compose.LottieAnimationKt$LottieAnimation$2.invoke(LottieAnimation.kt:143)
	at com.airbnb.lottie.compose.LottieAnimationKt$LottieAnimation$2.invoke(LottieAnimation.kt:106)
	at androidx.compose.ui.draw.DrawBackgroundModifier.draw(DrawModifier.kt:127)
	at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-eZhPAX0$ui_release(LayoutNodeDrawScope.kt:110)
	at androidx.compose.ui.node.LayoutNodeDrawScope.draw-eZhPAX0$ui_release(LayoutNodeDrawScope.kt:89)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:450)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:280)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:280)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:280)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:280)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:1000)
	at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:196)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:280)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:1000)
	at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:196)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:58)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1$1.invoke(NodeCoordinator.kt:469)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1$1.invoke(NodeCoordinator.kt:468)
	at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:503)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:502)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:258)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1.invoke(NodeCoordinator.kt:468)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1.invoke(NodeCoordinator.kt:466)
	at androidx.compose.ui.platform.GraphicsLayerOwnerLayer.drawLayer(GraphicsLayerOwnerLayer.android.kt:271)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:434)
	at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:280)
	at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:68)
	at androidx.compose.foundation.BackgroundNode.draw(Background.kt:163)
	at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-eZhPAX0$ui_release(LayoutNodeDrawScope.kt:110)
	at androidx.compose.ui.node.LayoutNodeDrawScope.draw-eZhPAX0$ui_release(LayoutNodeDrawScope.kt:89)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:450)
	at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:58)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1$1.invoke(NodeCoordinator.kt:469)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1$1.invoke(NodeCoordinator.kt:468)
	at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2441)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:502)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:258)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1.invoke(NodeCoordinator.kt:468)
	at androidx.compose.ui.node.NodeCoordinator$drawBlock$1.invoke(NodeCoordinator.kt:466)
	at androidx.compose.ui.platform.GraphicsLayerOwnerLayer.drawLayer(GraphicsLayerOwnerLayer.android.kt:271)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:434)
	at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:1000)
	at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:196)
	at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:447)
	at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:439)
	at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:1000)
	at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1564)
	at android.view.View.draw_Original(View.java:23892)
	at android.view.View_Delegate.draw(View_Delegate.java:56)
	at android.view.View.draw(View.java:23862)
	at android.view.View.draw_Original(View.java:23762)
	at android.view.View_Delegate.draw(View_Delegate.java:68)
	at android.view.View.draw(View.java:23540)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
	at android.view.View.draw_Original(View.java:23760)
	at android.view.View_Delegate.draw(View_Delegate.java:68)
	at android.view.View.draw(View.java:23540)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
	at android.view.View.draw_Original(View.java:23760)
	at android.view.View_Delegate.draw(View_Delegate.java:68)
	at android.view.View.draw(View.java:23540)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
	at android.view.View.draw_Original(View.java:23760)
	at android.view.View_Delegate.draw(View_Delegate.java:68)
	at android.view.View.draw(View.java:23540)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
	at android.view.View.draw_Original(View.java:23760)
	at android.view.View_Delegate.draw(View_Delegate.java:68)
	at android.view.View.draw(View.java:23540)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
	at android.view.View.draw_Original(View.java:23892)
	at android.view.View_Delegate.draw(View_Delegate.java:56)
	at android.view.View.draw(View.java:23862)
	at com.android.layoutlib.bridge.impl.RenderSessionImpl.renderAndBuildResult(RenderSessionImpl.java:558)
	at com.android.layoutlib.bridge.impl.RenderSessionImpl.render(RenderSessionImpl.java:445)
	at app.cash.paparazzi.PaparazziSdk$takeSnapshots$3.invoke(PaparazziSdk.kt:289)
	at app.cash.paparazzi.PaparazziSdk$takeSnapshots$3.invoke(PaparazziSdk.kt:288)
	at app.cash.paparazzi.PaparazziSdk.withTime(PaparazziSdk.kt:340)
	at app.cash.paparazzi.PaparazziSdk.takeSnapshots(PaparazziSdk.kt:288)
	at app.cash.paparazzi.PaparazziSdk.snapshot(PaparazziSdk.kt:179)
	at app.cash.paparazzi.PaparazziSdk.snapshot$default(PaparazziSdk.kt:178)
	at app.cash.paparazzi.PaparazziSdk.snapshot(PaparazziSdk.kt:174)
	at app.cash.paparazzi.Paparazzi.snapshot(Paparazzi.kt:103)
	at app.cash.paparazzi.Paparazzi.snapshot$default(Paparazzi.kt:100)
	at MY_PACKAGE_NAME.screenshots.PaparazziScreenshotTest.previewTests(PaparazziScreenshotTest.kt:69)
	at jdk.internal.reflect.GeneratedMethodAccessor22.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at com.google.testing.junit.testparameterinjector.PluggableTestRunner$2.evaluate(PluggableTestRunner.java:249)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at app.cash.paparazzi.Paparazzi$apply$1.evaluate(Paparazzi.kt:79)
	at com.google.testing.junit.testparameterinjector.PluggableTestRunner$ContextMethodRule$1.evaluate(PluggableTestRunner.java:433)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:54)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:53)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
	at jdk.proxy1/jdk.proxy1.$Proxy4.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:183)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

Steps to Reproduce
Am struggling to reproduce this outside of my massive project, but it's something to do with reusing the canvas a lot (I can see that mNativeCanvasWrapper is the same across all the screenshots). The tests that are failing here pass if run by themselves, but not if I runn all the paparazzi tests.

Expected behavior
Screenshot should be generated, and test should not crash.

Additional information:

  • Paparazzi Version: 1.3.4
  • OS: Mac Os Sonoma 14.5
  • Compile SDK: 34
  • Gradle Version: 8.10.2
  • Android Gradle Plugin Version: 8.7.0
@jamesrapadmi jamesrapadmi added the bug Something isn't working label Oct 31, 2024
@TWiStErRob
Copy link
Contributor

You could try to create a repro where you take one test that you know is affected and parameterize it to run 2000 times?

@jamesrapadmi
Copy link
Author

We've managed to resolve the issue by using hardware acceleration within the stuff we're screenshotting. But I'm still not sure why

@geoff-powell
Copy link
Collaborator

Do you mind providing a repro project? @jamesrapadmi
Glad you fixed your issue but it would be helpful to see if the issue is related to paparazzi.

@geoff-powell geoff-powell added the waiting on user Waiting on information from OP label Nov 7, 2024
@jamesrapadmi
Copy link
Author

I can try to, but I'll likely struggle to find time to do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working waiting on user Waiting on information from OP
Projects
None yet
Development

No branches or pull requests

3 participants