jonahwilliams/flutter_shaders

Memory leaks on Android

feduke-nukem opened this issue ยท 16 comments

Similar to #17.

I have good performance on the iOS Simulator and iPhone 7 (physical device).

However, profiling both the Huawei Mate 20 lite and the default Pixel 6 API 33 emulator (ARM) is leading to memory leaks.
I assume that this is happening due to frequent rebuilds and the use of scene.toImageSync. Link

Screen.Recording.2023-06-04.at.05.27.06.mov
video_2023-06-04_05-18-21.mp4
shader_memory.mov

However, if I use a raw ui.Image with CustomPaint, which is not desired because it won't reflect the provided widget changes, the performance is fine since there are no frequent imageSync calls. Link

Do you have any ideas on how to prevent such behavior?

You could try the branch at #20 to see if that helps. I haven't had the time this week to dig in much deeper, but you're not the only one to report this issue

You could try the branch at #20 to see if that helps. I haven't had the time this week to dig in much deeper, but you're not the only one to report this issue

I have tried, but it didn't help.

Good to know. FWIW while I'll land the PR I linked sometime this next week I don't plan to work on this further as I'm busy at work. If you investigate further and find a way to fix this I'm happy to accept the contribution.

I'm going to need more details on how to reproduce this. With the basic sample in the repo, I'm unable to reproduce any significant memory leakage. @feduke-nukem if you're able to narrow this down to a smaller reproduction that would be helpful.

From what I can see locally, nothing in the AnimatedSampler is retaining the ui.Image or ui.Picture, so beyond a bug in dart:ui itself I don't know what it could be.

I'm going to need more details on how to reproduce this. With the basic sample in the repo, I'm unable to reproduce any significant memory leakage. @feduke-nukem if you're able to narrow this down to a smaller reproduction that would be helpful.

From what I can see locally, nothing in the AnimatedSampler is retaining the ui.Image or ui.Picture, so beyond a bug in dart:ui itself I don't know what it could be.

Okay, I will do it later

I'm going to need more details on how to reproduce this. With the basic sample in the repo, I'm unable to reproduce any significant memory leakage. @feduke-nukem if you're able to narrow this down to a smaller reproduction that would be helpful.

From what I can see locally, nothing in the AnimatedSampler is retaining the ui.Image or ui.Picture, so beyond a bug in dart:ui itself I don't know what it could be.

Here's repo

I am testing on physical Android Huawei Mate 20 lite and Emulator (default Pixel 33 API)
image

Also, I've noticed that the scene object used to produce the picture isn't disposed, but it doesn't help either (I've checked that).

Thanks, I will take a look this week!

I can run this sample locally on a Pixel 6 and confirm that both the Dart image object and the native image wrapper are disposed, and there is no gradual memory increase in either the Dart or native heap.

(I'll try on an emulator later)

What I suspect you may be seeing is that the native resources are only disposed at a minimum every n MS (where N is some fairly large number like 30 or 40). This may be more pronounced on an emulator because its not a real GPU backend and must do more expensive emulation.

What I suspect you may be seeing is that the native resources are only disposed at a minimum every n MS (where N is some fairly large number like 30 or 40). This may be more pronounced on an emulator because its not a real GPU backend and must do more expensive emulation.

The problem is that this issue also occurs on a real device. The very first video in this conversation demonstrates a drop in FPS, and after some time, the application freezes and crashes (similar to the system killing the process).

It works just fine on iOS physical devices (iPhone 7 e.g. 60 fps stable) and some other Androids.

What I suspect you may be seeing is that the native resources are only disposed at a minimum every n MS (where N is some fairly large number like 30 or 40). This may be more pronounced on an emulator because its not a real GPU backend and must do more expensive emulation.

I assume that my phone is an old, outdated device, and maybe this is the real problem, idk.

It doesn't really make any sense that the behavior you're observing varies by manufacturer though. its not like the flutter engine works differently on older phones.

It doesn't really make any sense that the behavior you're observing varies by manufacturer though. its not like the flutter engine works differently on older phones.

By "old," I mean that it is simply a performance-related issue. My Android device experiences a default drop in FPS whenever there are animations, but in this case, it is critical.

Well, that's weird anyway.

@jonahwilliams I tried replacing the approach of creating an image for a shader from the 'Scene' to using 'RepaintBoundary,' and I can confirm that the problem is gone when I use the toImage method instead of toImageSync.
I don't have a real understanding of why, but it works. Maybe this information will be helpful somehow.

It's clear that this is a bug in flutter. The flutter team seems to be on the case now at least :) We'll just have to wait patiently until they fix it.