Using penguin.flr to hello_flutter increases overall memory usage by 80M
mehmetf opened this issue · 7 comments
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: #238.
#228 is not submitted yet so I could not test turning off AA.
Is there any path here to reducing the Flare memory usage?
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.
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.
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.
The linked engine PR lowers memory consumption by the penguin animation by about 4 or 5 megabytes locally for me.
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.
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?