2d-inc / Flare-Flutter

Load and get full control of your Rive files in a Flutter project using this library.
https://rive.app/
MIT License
2.55k stars 470 forks source link

OOM when loading three Rive assets #238

Open jkurtw opened 4 years ago

jkurtw commented 4 years ago

We have three Rive assets that need to be loaded into memory, which is causing an OOM condition. It seems each individual animation occurs a large ~60M initialization cost.

Can this be reduced? Would combining these assets into one artboard help? These were converted from Lottie. Would it be better to reexport from AE directly to .flr?

jkurtw commented 4 years ago

cc/ @kf6gpe

luigi-rosso commented 4 years ago

Hey @jkurtw, are you seeing the memory usage in terms of Skia cache size or just raw Dart heap?

If you're using a device memory profiler, it may not make the distinction. The Flutter dev tools should tell you the actual Dart heap size, which can help determine if the file is somehow allocating a lot of data to initialize in Dar or if Skia is doing the allocation behind the scenes for rendering.

We've run into issues like this before where Skia requires large GPU memory caches for certain animations. Usually changing the on-screen size of the animation helps, sometimes disabling anti-aliasing can help too.

Issue where we've seen something like this before: https://github.com/2d-inc/Flare-Flutter/issues/99

etenoch commented 4 years ago

Hi Luigi, i'm working with Kurt on this issue,

We're seeing large spikes in memory usage when our FlareActors are first rendered. We load 3 different animation files (all less than ~30kb) in FlareActors with BoxFit.contain and customs FlareControllers. All 3 animations are wrapped in Opacity widgets (initially) set to 0 and are all in a Stack.

When these widgets first render, we see a large spike that returns to normal after a couple seconds. The memory usage always returns to roughly the previous usage even though the FlareActors are still in the tree.

These are from Dart dev tools with our app running in debug in a simulator. image image image

When the animations are shown (opacity -> 1) and the animation is actually started, the memory usage does not increase.

From #99, wrapping the FlareActor in a FractionallySizedBox with factors set to 1.0 doesn't seem to make a difference. How would i go about disabling anti-aliasing?

luigi-rosso commented 4 years ago

Regarding anti-aliasing, @umberto-sonnino can help point you in the right direction. I'm not sure if we got that feature published yet, but we have a new feature that lets you toggle anti-aliasing on/off.

We don't clear out any memory or do any extra allocation during initialization. Whatever is allocated during initialization from the Dart side persists until the FlareActor (or instance of) is completely disposed of.

I do wonder if this is related to some initialization Skia does internally. Interesting that the spike seems to be Dart heap (light blue in that graph, if I remember correctly). That would suggest it is something in Dart land. Is there any change to the memory spike if you remove the Opacity widget? I think that's probably introducing an extra layer, which depending on the size of the animation on screen could be taking up a lot of memory, but again it's weird that it would later clear out.

Any chance you could share the three animations (maybe through a private channel if you prefer, you can email them to luigi@rive.app) and the version of Flutter are you testing on?

umberto-sonnino commented 4 years ago

Regarding anti-aliasing, there's this PR from the antialiasing_flag branch that adds a boolean toggle for the FlareActor widget. The example app in the /simple folder within that branch shows how to use it.

etenoch commented 4 years ago

I've been able to repro the issue with a flutter app in a non-google build environment in an android emulator with Dart SDK 2.7.0 and Flutter 1.12.13+hotfix.8.

I've confirmed that this issue is specific to our 3 lottie-converted assets. I downloaded a couple random assets from rive.app and swapped them out and i don't observed the same memory spike. I will share the test flutter project (which includes our problematic assets) with you via email.

luigi-rosso commented 4 years ago

Thanks @etenoch. Are you only seeing this issue on Android? I tried it on an iOS simulator and got an 18MB spike which doesn't go back down. 18MB does seem a little high to me for those animations but considering it's also including GPU buffers allocated, it makes more sense than 60MB.

image

We'll try with Android shortly. In the meantime, to help us debug this, can you see if putting the animations in a smaller screen space affects memory usage on Android? Something like:

Container(width:10, height:10, child:Animations())

This made a small difference on iOS, brought it down 15.5MB, which means at least ~4MB of the 18MB are used by the GPU. Widget dimensions don't have any impact on the memory we allocate in Dart, Skia handles that part so it's a good tell of how much of that memory is coming from where.

etenoch commented 4 years ago

In the process of setting up my mac to run on ios. Will update with those findings today. That said, our app is only targeting Android and another platform (but not ios).

I have also noticed, on android, that the memory usage doesn't also go back down. I had thought that might just be a dart dev tools glitch since I've seen the memory graph glitch in similar ways. In most cases, the usage drops back down right away.

I tried wrapping it on Container(width:10, height:10, ...). It might have a small effect, but nothing significant. Probably within the margin of error on repeated runs.

etenoch commented 4 years ago

iOS 13.3 in Simulator. Seeing similar memory deltas as you. Adding the Container(width:10, height:10, ...) does seem to shave ~4mb off the top.

image

ravenblackx commented 4 years ago

Re the question about Opacity widgets, those widgets are only using opacity 1 or 0 without interpolation, which according to the Flutter documentation is supposed to mean they won't be allocating an extra buffer.

luigi-rosso commented 4 years ago

That sounds good @ravenblackx, it shouldn't be using any layers for that. @etenoch do you notice a difference on Android in release/profile mode?

etenoch commented 4 years ago

Yes, running in profile on an Android phone, the issue is not reproducible. I can still repro in debug on the real phone.

I'll follow up with you via email about why this is still an issue for us, even though its fine on profile/release on android.

kf6gpe commented 4 years ago

@luigi-rosso,we're seeing some similar memory issues we've traced back down to some RIve assets as well, on another project --- have you had a chance to look at this any further? I can probably coordinate with you by email to get you the assets, but they'd be under NDA; they're for an internal Google effort.