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] Local image sources exhibit excessive memory usage compared to remote, with the same images #2529

Closed
jsierles opened this issue Sep 2, 2015 · 10 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@jsierles
Copy link
Contributor

jsierles commented Sep 2, 2015

Loading PNGs for display using a local URI exhibits excessive memory usage in my project, compared with loading the same images from the network, using RN 0.10. The images themselves are transparent PNGs around 40-80k each, and 750x750px. This behavior is causing the app to crash, and even reboot the phone.

Video: http://quick.as/06LqfrykO
Test project: https://github.com/jsierles/ImageMemoryTest

The video shows the app running on a real Iphone 6 with instruments enabled. The first few actions load images from the filesystem, and "persistent bytes" shows consistent growth without releasing memory. The network loads seem to keep memory usage flat.

This behavior doesn't make sense to me, since it looks like RN is using UIImage.imageWithContentsOfFile, which should set references in the default autorelease pool. Any help appreciated!

The test project contains the same images as are loaded from the network.

@brentvatne
Copy link
Collaborator

@jsierles and I discussed this in length on Slack and learned this:

  • We are currently actually using UIImage imageNamed: for these images in the local bundle even though they are not in Images.xcassets
  • UIImage imageNamed: has benefits but it can cause bad times.
  • So, we want to distinguish between the two local images that use the file scheme: those in xcassets and those that are just bundled elsewhere. We can do this by just checking that the path is prefixed by /. By doing this, images in xcassets can be loaded with UIImage imageNamed: (it seems like they have to be) and others can use UIImage imageWithContentsOfFile:
  • This solution still sucks because it makes no sense to somebody who hasn't looked into this. But the fix suggested is a good stopgap.

@brentvatne
Copy link
Collaborator

cc @tadeuzagallo @nicklockwood

@brentvatne brentvatne changed the title Local image sources exhibit excessive memory usage compared to remote, with the same images [Image] Local image sources exhibit excessive memory usage compared to remote, with the same images Sep 6, 2015
@nicklockwood
Copy link
Contributor

@a2 recently did some work on the image pipeline to change how we handle local image sources.

I'm not sure if this is fixed in all cases now, but it's definitely the intended behavior that imageNamed: should only be used for XCAssets.

@nicklockwood
Copy link
Contributor

Another difference is that we automatically resize images downloaded from the network, but not ones loaded locally (the assumption being you'll have stored them at the correct size), but perhaps we should revisit that decision.

@jsierles
Copy link
Contributor Author

jsierles commented Sep 6, 2015

Thanks for checking this out @brentvatne!

Should we wait for this or submit a PR with a small fix, using the path name to determine if the source uses xcassets?

I think optionally resizing local images is a great idea. In my case, I have quite a lot of local images, and storing them at all resolutions bloats the app size, so I store only the largest resolution. While in some cases resizing is costly, that decision should be up to the developer. Also, it looks like the resizing does good things for memory usage.

@ide
Copy link
Contributor

ide commented Sep 6, 2015

storing them at all resolutions bloats the app size, so I store only the largest resolution

Once Xcode 7 GM lands you'll be able to submit apps with App Slicing enabled so that users download only the 2x or 3x assets.

@jsierles
Copy link
Contributor Author

jsierles commented Sep 6, 2015

App slicing looks cool, didn't know about it!

Only issue there is you're still required to use asset catalogs, and I'd guess this bug would still persist. Even with the smaller resolution images, 4-5MB per image is allocated and never released.

@jsierles
Copy link
Contributor Author

jsierles commented Sep 6, 2015

The latest changes in master won't allow the above fix: xcassets and non-xcassets images in the resource bundle all contain the resource bundle prefix. The network downloader image handler will only use imageWithContentsOfFile for files not stored in the asset bundle.

https://github.com/facebook/react-native/blob/master/Libraries/Image/RCTImageDownloader.m#L39

Given there are legitimate use cases (memory efficiency) for wanting to load bundled assets using imageWithContentsOfFile, one solution is adding a prop meaning 'don't use imageNamed' for asset bundle file loading.

@jsierles
Copy link
Contributor Author

jsierles commented Sep 6, 2015

Another solution that might work is giving the download handler the ability to load from the main bundle, but also allow specifying it as higher priority. This is my temporary solution now, and it drastically reduces the app memory footprint.

- (float)imageLoaderPriority;

@mkonicek
Copy link
Contributor

Hi there! This issue is being closed because it has been inactive for a while.

But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/image-local-image-sources-exhibit-excessive-memory-usage-compared-to-remote-with-the-same-images

ProductPains helps the community prioritize the most important issues thanks to its voting feature.
It is easy to use - just login with GitHub.

Also, if this issue is a bug, please consider sending a PR with a fix. We rely on the community to provide
bugfixes as the core team is heavily focused working on performance.

@facebook facebook locked as resolved and limited conversation to collaborators Jul 21, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

6 participants