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

Image widget can use large memory and never released #62107

Closed
Gorniv opened this issue Jul 23, 2020 · 66 comments · Fixed by #122787
Closed

Image widget can use large memory and never released #62107

Gorniv opened this issue Jul 23, 2020 · 66 comments · Fixed by #122787
Assignees
Labels
a: images Loading, displaying, rendering images c: performance Relates to speed or footprint issues (see "perf:" labels) customer: crowd Affects or could affect many people, though not necessarily a specific customer. d: api docs Issues with https://api.flutter.dev/ found in release: 1.17 Found to occur in 1.17 found in release: 1.21 Found to occur in 1.21 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list perf: memory Performance issues related to memory r: fixed Issue is closed as already fixed in a newer version

Comments

@Gorniv
Copy link

Gorniv commented Jul 23, 2020

Details

Image.asset use from 100 to 240 Mb for One image:

Image.asset(
          'assets/icon_app/meows_splash.png', 
          fit: BoxFit.cover,
          width: width,
          height: width,
        )
Image for test ![meows_splash](https://user-images.githubusercontent.com/963316/88263474-c5aeff00-ccd2-11ea-8208-566e4209cffe.png)

I tested on ios physical device with Profile mode.

Run flutter app without Image.asset:
Run flutter app without image.

Run with Image on 1.17.5 :
Screenshot 2020-07-22 at 08 42 29

Run with Image on 1.21.0-2.0.pre94:
Screenshot 2020-07-22 at 08 52 49

I found workaround - use cacheWidth

Image.asset(
          'assets/icon_app/meows_splash.png', 
          fit: BoxFit.cover,
          width: width,
          height: width,
          cacheWidth: width ~/ 1,
          cacheHeight: width  ~/ 1,
        )

Run workaround:
Screenshot 2020-07-22 at 09 55 23

@Gorniv Gorniv added the from: performance template Issues created via a performance issue template label Jul 23, 2020
@TahaTesser TahaTesser removed the from: performance template Issues created via a performance issue template label Jul 23, 2020
@TahaTesser
Copy link
Member

Hi @Gorniv
I can reproduce this issue using using this image

Code Sample
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Material App Bar'),
        ),
        body: Center(
          child: Image.asset('assets/test_image.png'),
        ),
      ),
    );
  }
}

flutter doctor -v
[✓] Flutter (Channel dev, 1.21.0-1.0.pre, on Mac OS X 10.15.6 19G73, locale en-GB)
    • Flutter version 1.21.0-1.0.pre at /Users/tahatesser/Code/flutter_dev
    • Framework revision f25bd9c55c (8 days ago), 2020-07-14 20:26:01 -0400
    • Engine revision 99c2b3a245
    • Dart version 2.9.0 (build 2.9.0-21.0.dev 20bf2fcf56)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at /Users/tahatesser/Code/sdk
    • Platform android-30, build-tools 30.0.1
    • ANDROID_HOME = /Users/tahatesser/Code/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.6)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.6, Build version 11E708
    • CocoaPods version 1.9.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 47.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.47.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.12.2

[✓] Connected device (5 available)
    • SM M305F (mobile)      • 32003c30dc19668f          • android-arm64  • Android 10 (API 29)
    • Taha’s iPhone (mobile) • 00008020-001059882212002E • ios            • iOS 13.6
    • macOS (desktop)        • macos                     • darwin-x64     • Mac OS X 10.15.6 19G73
    • Web Server (web)       • web-server                • web-javascript • Flutter Tools
    • Chrome (web)           • chrome                    • web-javascript • Google Chrome 84.0.4147.89

• No issues found!
flutter doctor -v
[✓] Flutter (Channel stable, v1.17.5, on Mac OS X 10.15.6 19G73, locale en-GB)
    • Flutter version 1.17.5 at /Users/tahatesser/Code/flutter_stable
    • Framework revision 8af6b2f038 (3 weeks ago), 2020-06-30 12:53:55 -0700
    • Engine revision ee76268252
    • Dart version 2.8.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at /Users/tahatesser/Code/sdk
    • Platform android-30, build-tools 30.0.1
    • ANDROID_HOME = /Users/tahatesser/Code/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.6)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.6, Build version 11E708
    • CocoaPods version 1.9.3

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 47.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.47.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.12.2

 
[✓] Connected device (2 available)            
    • SM M305F      • 32003c30dc19668f          • android-arm64 • Android 10 (API 29)
    • Taha’s iPhone • 00008020-001059882212002E • ios           • iOS 13.6

• No issues found!

Thanks for reporting

@TahaTesser TahaTesser changed the title Image.asset can use large memory Image widget can use large memory and never released Jul 23, 2020
@TahaTesser TahaTesser added a: images Loading, displaying, rendering images found in release: 1.17 Found to occur in 1.17 found in release: 1.21 Found to occur in 1.21 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on perf: memory Performance issues related to memory c: performance Relates to speed or footprint issues (see "perf:" labels) labels Jul 23, 2020
@goderbauer
Copy link
Member

/cc @dnfield

@dnfield
Copy link
Contributor

dnfield commented Jul 29, 2020

I'm not clear that this is a bug. If you have a large image and decode it at full resolution it will use a lot of memory.

I recently added functionality to let you press I (uppercase i) in the terminal to highlight images that are larger than what you're painting. You can try this to identify images you may be decoding at too large a size, and either downsize them or use the cache width/Height params.

Please feel free to add more details if something is missing here.

@dnfield dnfield closed this as completed Jul 29, 2020
@sojazvn
Copy link

sojazvn commented Jul 30, 2020

I ran into that issue also.

When I loaded and image with Image widget the memory increase then I push to the new screen with pushAndRemoveUntil. The memory still stored in External Memory not release when GC is executed.

The memory will stack to 1000mb then crash on iPhone X if we load more images on a first page then Navigate to the new page leaves the app running the memory still not release in External Memory.

This issue is easy to reproduce:
Create ListView.builder load a list of images then clear the image list, set it null if needed then navigate to the new page. standstill the memory never release from the External Memory.

@Gorniv
Copy link
Author

Gorniv commented Jul 30, 2020

@dnfield image size is 749 614 bytes (754 KB on disk) and use more 100 MB when I use ONE Image.asset with width == device-width of iPhone 11.

@dnfield
Copy link
Contributor

dnfield commented Jul 30, 2020

What matters is it's decode size (roughly width x height x 4.3), not it's compressed size on disk

@Gorniv
Copy link
Author

Gorniv commented Jul 31, 2020

I and all the developers with whom I spoke on this issue did not expect this behaviour from this widget. Its documentation and options are not intuitive.

@dnfield
Copy link
Contributor

dnfield commented Jul 31, 2020

I'll reopen this to track updating docs

@dnfield dnfield reopened this Jul 31, 2020
@dnfield dnfield added d: api docs Issues with https://api.flutter.dev/ documentation labels Jul 31, 2020
@Jorjatorz
Copy link

Jorjatorz commented Aug 7, 2020

Answered at: #60160

I have come with a similar error while using Image.memory() inside a SliverGrid. In my app, I have a Listview with several profiles (Cards) and when clicked a new page (Navigator.pushNamed()) is opened, displaying the SliverGrid with the images of the profile (up to 6 are displayed simultaneously, the rest need to be scrolled to be displayed). These images are stored in a database blob and I am using Image.memory() to display them inside the SliverGrid.

I have noticed that if I open (and close) the images page my external memory increases and is never released. If I open and close the page several times the external memory keeps increasing considerably and is never released. I am attaching a spreadsheet with the outputs of the memory snapshot.
image

This small table shows the largest objects of the external memory at the init of the app, after opening for the first time the page with the images and after opening and closing the page ten and fifteen times (in total). I haven't manually run the GC but it is evident that what makes the memory increase is _Int64List, which increases after each opening and ends up filling the 74.71% of the total allocated external memory.

I made an extensive study with my code and came to the conclusion that it is Image.memory() the one causing the memory issue. It is not a memory leak from other parts of my code and this problem is fixed if instead I use Image.network() or Image.asset(). Hence that is why I am confident to say that the error is coming from Image.memory(). I have also tried to run the GC and call imageCache.clear() without success.

I hope this gives you enough insights. I will be happy to answer any further question or give more details.

SliverGrid code

return SliverGrid(
      gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 200.0,
      ),
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          var mq = MediaQuery.of(context);
          return Container(
              key: ValueKey<String>(_profile.posts[index].id),
              alignment: Alignment.center,
              padding: const EdgeInsets.all(2.0),
              child: GestureDetector(
                  onTap: () => Navigator.pushNamed(
                      context, PostMediaPage.routeName,
                      arguments: _profile.posts[index]),
                  child: Stack(children: <Widget>[
                    Container(
                        child: _profile.posts[index] is FetchedPost
                            ? Image.memory(
                                (_profile.posts[index] as FetchedPost)
                                    .thumbnailImage,
                                fit: BoxFit.cover, frameBuilder: (context,
                                    child, frame, wasSynchronouslyLoaded) {
                                if (wasSynchronouslyLoaded) return child;
                                return AnimatedSwitcher(
                                    duration: Duration(milliseconds: 700),
                                    child: frame == null
                                        ? Container(
                                            constraints: BoxConstraints(
                                                maxHeight: mq.size.height,
                                                maxWidth: mq.size.width),
                                            child: FlareActor(
                                              "assets/loading-eye-big.flr",
                                              animation: "intro",
                                            ),
                                          )
                                        : Container(child: child));
                              })
                            : SizedBox()),
                    _profile.posts[index] is FetchedPost
                        ? _getPostTypeLogo(_profile.posts[index])
                        : SizedBox()
                  ])));
        },
        childCount: _profile.posts.length,
      ),
    );

@wasabia
Copy link

wasabia commented Aug 15, 2020

same issue
use Image widget display webp image
memory leak on iOS

Flutter (Channel dev, 1.21.0-9.0.pre, on Mac OS X 10.15.6 19G73, locale zh-Hans-CN

@Bedroome
Copy link

I have the same issue. If the picture is a moving picture, it will keep going up when the app is on.
channel master

@wuchangfeng
Copy link

same issue

@FroseMan97
Copy link

same

@vanlooverenkoen
Copy link
Contributor

#65834 Could be related

@Tom3652
Copy link

Tom3652 commented Sep 2, 2022

PaintingBinding.instance!.imageCache!.maximumSizeBytes = 1024 * 1024 * 50; // 50MB

This workaround doesn't work anymore from flutter 3.0.+ ... I have again OOM in my app when scrolling infinite list of photos :(
The imageCache is actually set to this value but the memory consumption is only rising and never released

@sailexx
Copy link

sailexx commented Sep 13, 2022

The temporary solution I used is to clear the cache if image cache memory exceeds a specific range. Still, after clearing the cache, it seems the image will take some time to reload. My app has about 500 images now and is expected to increase to 10000, Hope this issue will be solved soon.

class TempImageCache extends ImageCache {
    @override
    ImageStreamCompleter? putIfAbsent(
        Object key, ImageStreamCompleter Function() loader,
        {ImageErrorListener? onError}) {
        if (imageCache.currentSizeBytes > 50 * 1024 * 1024) {
          imageCache.clear();
          imageCache.clearLiveImages();
      }
      return super.putIfAbsent(key, loader, onError: onError);
  }

  @override
  void clear() {
    print("clear image cache is called");
    super.clear();
  }
}

class TempWidgetsBinding extends WidgetsFlutterBinding {
  @override
  ImageCache createImageCache() {
    return TempImageCache();
  }
}

void main() {
  TempWidgetsBinding();
  return runApp(const MyApp());
}

@dnfield
Copy link
Contributor

dnfield commented Sep 13, 2022

@sailexx why not just set the maxSizeBytes on the image cache, which should be doing that for you?

Also, clearing live images is almost never the right thing to do, since those are in memory somewhere else anyway...

@Tom3652
Copy link

Tom3652 commented Sep 13, 2022

It is not working well from flutter 3.3 unfortunately #110847, but this was the workaround i was using.

@sailexx
Copy link

sailexx commented Sep 14, 2022

Thank you for the response,

Also, clearing live images is almost never the right thing to do, since those are in memory somewhere else anyway...

If I remove the imageCache.clearLiveImages(); the memory didn't get clear.
if I were to use imageCache.clearLiveImages, will it have any side effects?

why not just set the maxSizeBytes on the image cache, which should be doing that for you?

I did add maxSizeBytes to 25MB but the memory uses still goes up to 1GB for me. I'm using flutter 3.3.0, it didn't work for me in the previous version too.

Screenshot 2022-09-14 at 11 11 28 AM

And also I do see a bunch of logs

I/zygote  (13578): Explicit concurrent copying GC freed 3526(159KB) AllocSpace objects, 1(20KB) LOS objects, 55% free, 1239KB/2MB, paused 270us total 29.976ms

But the memory use doesn't decrease,

@antelopeventures
Copy link

I switched to use extended_image and memory issues went away https://pub.dev/packages/extended_image/example

@YDA93
Copy link

YDA93 commented Sep 26, 2022

I switched to use extended_image and memory issues went away https://pub.dev/packages/extended_image/example

I confirm since I been using this package for about 10 months, the OOM issue went away for me too.

@Stitch-Taotao
Copy link
Contributor

I switched to use extended_image and memory issues went away https://pub.dev/packages/extended_image/example

So ,Is that mean It's the question of CacheNetWorkImage not flutter's ?

@bugrevealingbme
Copy link

same

@Hixie Hixie self-assigned this Mar 16, 2023
@Hixie Hixie added the waiting for PR to land (fixed) A fix is in flight label Mar 16, 2023
Hixie added a commit to Hixie/flutter that referenced this issue Mar 17, 2023
@danagbemava-nc danagbemava-nc added r: fixed Issue is closed as already fixed in a newer version has reproducible steps The issue has been confirmed reproducible and is ready to work on and removed has reproducible steps The issue has been confirmed reproducible and is ready to work on waiting for PR to land (fixed) A fix is in flight labels Mar 23, 2023
@github-actions
Copy link

github-actions bot commented Apr 6, 2023

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: images Loading, displaying, rendering images c: performance Relates to speed or footprint issues (see "perf:" labels) customer: crowd Affects or could affect many people, though not necessarily a specific customer. d: api docs Issues with https://api.flutter.dev/ found in release: 1.17 Found to occur in 1.17 found in release: 1.21 Found to occur in 1.21 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list perf: memory Performance issues related to memory r: fixed Issue is closed as already fixed in a newer version
Projects
None yet
Development

Successfully merging a pull request may close this issue.