expo: [expo-image] When many image is rendered RAM usage goes over 2000mb and app crashes
Minimal reproducible example
https://github.com/Miigaarino/expo-image-memory-issue
Summary
Example below is after rendering images on newly created application. To test:
- Clone the repo
- Start expo
- Go to tab two on app
https://github.com/expo/expo/assets/48021917/95e53d6f-1cac-4f84-b77d-092457b9c03d
Environment
expo-env-info 1.2.0 environment info:
System:
OS: macOS 14.0
Shell: 5.9 - /bin/zsh
Binaries:
Node: 18.18.0 - /opt/homebrew/opt/node@18/bin/node
npm: 9.8.1 - /opt/homebrew/opt/node@18/bin/npm
Managers:
CocoaPods: 1.12.1 - /opt/homebrew/lib/ruby/gems/3.1.0/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 23.2, iOS 17.2, macOS 14.2, tvOS 17.2, watchOS 10.2
IDEs:
Android Studio: 2022.3 AI-223.8836.35.2231.10671973
Xcode: 15.1/15C65 - /usr/bin/xcodebuild
npmPackages:
expo: ~50.0.4 => 50.0.4
expo-router: ~3.4.6 => 3.4.6
react: 18.2.0 => 18.2.0
react-dom: 18.2.0 => 18.2.0
react-native: 0.73.2 => 0.73.2
react-native-web: ~0.19.6 => 0.19.10
npmGlobalPackages:
eas-cli: 5.2.0
expo-cli: 6.3.10
Expo Workflow: managed
About this issue
- Original URL
- State: open
- Created 5 months ago
- Reactions: 6
- Comments: 19 (4 by maintainers)
i spoke with @tsapeta about this and he went through the trouble of looking at the images to determine if they could be the cause, he found some that are extremely large and would cause this issue, eg: https://assets-us-01.kc-usercontent.com/6c08ae22-aaba-00c5-2884-7221a976fac0/16abfdeb-34a3-4f47-9764-b72409d9ea44/Innovation Experts.jpg - this is a 1.9mb image (reasonable) but its dimensions are 22433 × 6125 (not reasonable). i would suggest ensuring that you use appropriately sized images for the device.
we have a couple ideas to help here:
dangerouslyRenderOversizedImageswhich could default tofalsein dev and then warn when image dimensions exceed something like thedevice width x 5/device height x 5(5 being an arbitrary number that i’ve selected as an example of a possible threshold for warning). you could then choose to enable this prop if you OK with the memory usage implications of this.allowDownscalingwhich would increase memory consumption but likely not by as much, however it would be consistent rather than a spikeNo, this issue is being ignored for some reason…
Thanks to everyone who trying to help with this 😇 Thank you guys @brentvatne, @tsapeta i really appreciate it. Maybe I will find a lot of new stuff exploring this issue.
@GeorgeHop Would you be able to provide a simple reproducible example? It looks like your use case (and repro) might be different than the one provided in this issue.
In the provided example, the problem is that the exact same image (22433 × 6125) is downloaded at least three times from different URLs. The URL is the cache key, so they are basically stored on the disc and memory separately.
The overall Increased memory consumption with
allowDownscaling={false}is expected and it shows that you’re definitely using too big images. Keep in mind that the memory needed for the device to render the image is not the same as the file size which is compressed. This really big image is about 2mb in compressed form, but uncompressed (bitmap) it’s about 420mb.Besides using too big images, the problem in expo-image I do see here is the spike for a short period of time when the images are being downscaled.
It can be flatlist or flash list with 100+ items that use same images… If you will render many lists in horizontal scrollview with paging and each page will render 100 same images you will see significant drop in performance… Currently I don’t recommend to show images in lists using this lib. use simple react-native Image component. I tried many props described it the docs and nothing seems to resolve this issue.
@Miigaarino - you could use an image cdn to process the images and serve them if you don’t control the source. you could serve a device appropriate sized image and the user would not need to use as much data or memory. if each of those images averages to 500kb and you load 175 then that would be 87.5mb, you could reduce that significantly by serving an image tailored for the device. https://web.dev/articles/image-cdns
So I sent mail to @brentvatne and here is his response:
hey george,
could you copy all of those images directly to the repository that you shared there so we can inspect them more easily?
best, brent
@Miigaarino can you do this?
@brentvatne can you help us please?
Any info on this issue so far?
Yeah, for some reason simple image from react-native has issues with prefetch on iOS for example. Waiting when expo will fix issue with RAM because it crashes the app in production 😑
Thx for the warning. Was looking at this since expo 50 broke react-native image for me. I guess I need to debug it more 😃