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

Using penguin.flr to hello_flutter increases overall memory usage by 80M #249

Open mehmetf opened 4 years ago

mehmetf commented 4 years ago

We are debugging memory problems of some of our key customers in Google. As part of that, we are trying to see which assets end up consuming the most memory.

As a first data point, loading penguin.flr from a sample app into a simple hello_flutter app bumps memory usage by nearly 80M.

Before Flare:

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     1664
         Native Heap:    10300
                Code:     8416
               Stack:       60
            Graphics:    54964
       Private Other:     5456
              System:     3907

               TOTAL:    84767       TOTAL SWAP PSS:       66

After Flare:

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     1836
         Native Heap:    33440
                Code:     9476
               Stack:       60
            Graphics:    94916
       Private Other:    19316
              System:     3947

               TOTAL:   162991       TOTAL SWAP PSS:       62

A sizable increase is observed in native heap (+23M), graphics (+30M) and dart heap (+15M).

If the FlareActor is paused, the usage drops dramatically but is still 13M higher than baseline.

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     1652
         Native Heap:    14152
                Code:     9372
               Stack:       60
            Graphics:    61220
       Private Other:     6800
              System:     3900

               TOTAL:    97156       TOTAL SWAP PSS:       62

With animation looping and size reduced to 10x10:

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     1832
         Native Heap:    16208
                Code:     9496
               Stack:       60
            Graphics:    78860
       Private Other:    18836
              System:     3987

               TOTAL:   129279       TOTAL SWAP PSS:       62

Code:

return Scaffold(
      appBar: AppBar(title: Text('Title')),
      body: Center(
        child: Container(
          width: 10,
          height: 10,
          child: FlareActor(
            "assets/Penguin.flr",
            alignment: Alignment.center,
            //isPaused: true,
            fit: BoxFit.cover,
            animation: "walk",
          ),
        ),
      ),
    );

I have been getting these memory dumps in release mode using adb shell dumpsys meminfo.

Similar to issue: https://github.com/2d-inc/Flare-Flutter/issues/238.

https://github.com/2d-inc/Flare-Flutter/pull/228 is not submitted yet so I could not test turning off AA.

Is there any path here to reducing the Flare memory usage?

mehmetf commented 4 years ago

Tried adding another penguin actor with a different animation full size in a column. The memory usage does not increase for that:

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     1880
         Native Heap:    33900
                Code:     9496
               Stack:       60
            Graphics:    91796
       Private Other:    19524
              System:     4005

               TOTAL:   160661       TOTAL SWAP PSS:       62
body: Column(
        mainAxisSize: MainAxisSize.max,
        children: [
          Expanded(
            child: FlareActor(
              "assets/Penguin.flr",
              alignment: Alignment.center,
              //isPaused: true,
              fit: BoxFit.cover,
              animation: "walk",
            ),
          ),
          Expanded(
            child: FlareActor(
              "assets/Penguin.flr",
              alignment: Alignment.center,
              //isPaused: true,
              fit: BoxFit.cover,
              animation: "music_walk",
            ),
          ),
        ],
      ),

Loading an entirely different (but much simpler) animation together with penguin also does not affect the memory significantly.

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     1780
         Native Heap:    35532
                Code:     9504
               Stack:       60
            Graphics:    91656
       Private Other:    19924
              System:     4018

               TOTAL:   162474       TOTAL SWAP PSS:       63

However, it is interesting to note that native heap is the only dimension that goes up with a different animation.

mehmetf commented 4 years ago

Replacing both animations with the simple animation also results in same memory profile. The new animation is mostly white with small balloons and confetti floating around periodically. I would have expected the graphics memory to be lower for this kind of setup.

dnfield commented 4 years ago

I commented on this elsewhere to you, but what happens if you reduce the resource cache using the Skia system channel?

I suspect that the animation is gobbling up available resource cache space from Skia, and that's what's causing this.

mehmetf commented 4 years ago

@jacob314 FYI

dnfield commented 4 years ago

The linked engine PR lowers memory consumption by the penguin animation by about 4 or 5 megabytes locally for me.

luigi-rosso commented 4 years ago

That's really interesting because the penguin animation doesn't use any vertices (unless something it uses allocates vertices under the hood). That's a vector-only animation, flare_flutter will only directly allocate and draw vertices when it has raster content.

luigi-rosso commented 4 years ago

The issue generally addressed by that PR does sound like it would help with other Skia objects too. For example, we'll regenerate paths which animate each frame. This causes Skia to use up more cache bytes. It doesn't recoup those until the animation loop's been idle for some amount of time (I think it was 15 seconds). Skia has a way to mark Paths that animate often as volatile which may help in cases like this. Maybe the ability to set this flag could be bubbled up to the app layer in Flutter?