-
Notifications
You must be signed in to change notification settings - Fork 24.3k
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
Severe memory leak affecting fetch(), iOS Release Mode 0.59.0-rc.3, 0.58.6, 0.57.8 #23801
Comments
This has some similarities to other issues: |
@zhongwuzw yes I mentioned that in both the title and the body of the issue. Thank you for replying though! |
@jonathangreco no idea, I'd suggest profiling the memory. If it spikes massively before it crashes then it would make sense - if you are downloading something as large as a film through the fetch API and if this memory leak is not just me doing something silly it's likely. |
what is the most recent release where this did not occur for you? |
I haven't had time to go back and trianglulate the release the caused it, not sure.
|
This seemed to fix the blob type requests: However now that I'm trying out just hitting a regular content-type: "application/json" based response the memory usage issue is still there. I'm currently debugging that use case (which I think is far more common for apps in general) and I'll update my fork with anything I find. Since this is my first deep dive into RN networking internals, anyone with some experience please feel free to point out where I should be looking. |
OK so this is a bit of a strange one with regards to solution design. The issue as I understand it is that the The problem is that So So I think the approach to resolving this memory consumption issue would be to tell PR coming soon after I run some more tests. |
Do non-blob responses such as JSON also use the blob manager?
On Sun, Mar 10, 2019 at 18:24 Tim ***@***.***> wrote:
OK so this is a bit of a strange one with regards to solution design. The
issue as I understand it is that the RCTBlobManager isn't necessarily at
fault here as I first thought. I realised that the first attempt at a fix
wasn't right - even though it solved the use case in this issue.
The problem is that whatwg-fetch isn't necessarily concerned with what
happens to the data from a request after that request is "finished".
So RCTBlobManager keeps hold of all data from your various fetch
operations in your app. It references data via a HashMap with a blobId as
the key. The "bug" is that this data is not removed by the standard fetch
APIs. Now that's not fetch's fault, it's not RCTBlobManager's fault - it
just is :)
So I think the approach to resolving this memory consumption issue would
be to tell RCTBlobManager to release it's data after it receives a "read"
request on that data. By that point it will return the data back over the
bridge to fetch in whatever encoding the programmer has asked for it. I
am making an assumption here in saying that once a programmer has read the
data in JS then they probably won't be referencing that data in
RCTBlobManager again, and it would be safe to release it. The APIs aren't
even there (as far as I can tell) for the programmer to even go get it
again via a blobId - further reason to think this would be the safest
approach.
PR coming soon after I run some more tests.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#23801 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAjh8jUrAsqZYPn_klVMVo00kX_q6odiks5vVYYPgaJpZM4biYsr>
.
--
Chris Roth
cjroth.com <http://www.cjroth.com>
|
Yep. Looks like it. I altered your demo to use my fork of RN, please have a look. |
@timsawtell seems to be crashing when I run it - here's a screenshot. |
RN is supposed to use a forked version of whatwg-fetch that doesn’t use blobs by default to work around this issue. Maybe this is not working anymore for some reason? |
Seems we never remove blob data from native @timsawtell Hi, I see your commit, I think it may break the |
Sorry I haven’t replied on this in a while - it looks like either solution (deleting from blob manager on read, or adding a new method to do the same job) brings in implied behavior vs explicit behavior. (zhongwuzw’s solution is the explicit option). I’m in favor of the explicit behavior even if it adds a new API binding that’s only going to be used by the iOS implementation. Anyone from the core team have any guidance? |
How can We solve this problem...? |
Summary: Our Blob implementation was very problematic because it didn't release its underlying resource when the JS instance was dealocated. The main issue is that the fetch polyfill uses blobs by default if the module is available, which causes large memory leaks. This fixes it by using the new jsi infra to attach a `jsi::HostObject` (`BlobCollector`) to `Blob` instances. This way when the `Blob` is collected, the `BlobCollector` also gets collected. Using the `jsi::HostObject` dtor we can schedule the cleanup of native resources. This is definitely not the ideal solution but otherwise it would require rewriting the whole module using TurboModules + jsi. Fixes #23801, #20352, #21092 [General] [Fixed] - [Blob] Release underlying resources when JS instance in GC'ed Pull Request resolved: #24745 Reviewed By: fkgozali Differential Revision: D15248848 Pulled By: hramos fbshipit-source-id: 1da835cc935dfbf4e7bb6fbf2aea29bfdc9bd6fa
My Team recently upgraded to "0.57.2" and have noticed a significant memory leak when making Fetch() requests. Has this been resolved? |
No @mtpjr88 this was still in place after the PR which closed this issue and appears to be a long standing bug. We had to switch to Swift and build natively. |
Tried out @zhongwuzw's fix as a patch, and it appears to work on iOS @ RN 0.61.5. Not sure if this matches fetch's spec - but can confirm some of the functionality. See before/after with the same user behavior. We repeatedly poll and endpoint which generated a lot of unused (but unleaked) memory. |
🐛 Bug Report
Every call to
fetch()
uses memory and does not release it. The larger the fetch response, the more memory leaked.node-fetch
andwhatwg-fetch
and it happens using both libraries.response.blob()
. It affects all types of responses.XMLHttpRequest
as well asfetch
.Comparing memory snapshots in Safari found no difference in size even while the Chrome/Xcode memory profiles showed dramatic increases in memory. I'm not great at debugging memory leaks so I could be wrong but I suspect that means it might be on the native side and not on the JS side.
To Reproduce
I've created an example repo to reproduce the error in 0.59.0-rc.3: https://github.com/cjroth/react-native-fetch-memory-leak. You can copy the App.js and see that it happens in previous versions as well.
Expected Behavior
After each fetch() call that is no longer referenced, the memory should return to what it was previously.
Code Example
https://github.com/cjroth/react-native-fetch-memory-leak
Environment
The text was updated successfully, but these errors were encountered: