apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

reading from InMemoryCache causes memory leak (in React Native)

Open DanijelBojcic opened this issue 2 years ago • 6 comments

Intended outcome:

Calling readFragment/writeFragment should not increase memory usage at all.

Actual outcome:

Callling readFreagment and then writeFragment repeatedly will increase the memory usage. Calling only readFragment without writeFragment will only increase the memory once, which I guess is some caching to avoid unnecessary reads?

How to reproduce the issue:

I have created a simple app with reproduction: apollo-memory-leak

Versions

  System:
    OS: macOS 11.5.2
  Binaries:
    Node: 14.16.0 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.11 - /usr/local/bin/npm
  Browsers:
    Chrome: 94.0.4606.71
    Safari: 15.0
  npmPackages:
    @apollo/client: ^3.4.16 => 3.4.16 

DanijelBojcic avatar Oct 07 '21 10:10 DanijelBojcic

Don't know if it's the same issue, but I've also noticed a possible memory leak regression related to cache after upgrading from 3.4.10 to 3.4.16

Unfortunately I can't attach the full allocation sampling file as it contains proprietary code but here are some screenshots which might help:

Screen Shot 2021-10-13 at 9 13 58 Screen Shot 2021-10-13 at 9 16 08

oferitz avatar Oct 13 '21 06:10 oferitz

@DanijelBojcic Hey Daniel! Thanks for opening this issue. I tried running your reproduction, but did not notice any memory leaks against the latest apollo client. Screen Shot 2021-10-18 at 1 02 14 PM

Calling readFragment/writeFragment should not increase memory usage at all.

Unfortunately, this might not be possible with JavaScript. Engines will analyze JavaScript as it runs, and the results of this analysis are stored on the heap. In the Chrome V8 panel, this is the (compiled code) row in the panel. Other confounding factors are that your example appends periods to the phone field in writeFragment(). If you keep running your callback function, the Chrome heap seems to level out around 15-20mb for your example.

Also, one note for people doing memory analysis. Chrome 94 seems to have a bug which crashes when using profiles, so the only way I can get the memory snapshots right now is to run the browser in Incognito mode.

@oferitz I would expect the opposite to be true. Later versions should have better memory performance than earlier versions, because we’ve disabled “canonization” in the latest Apollo Client version. I’m not sure if I’ll be able to figure out what’s going on by screenshots alone, but if you run the application with the unminified version of Apollo Client that might be helpful.

I’m not denying the existence of memory leaks, and I’m sorry if you’re experiencing them as a result of using Apollo Client! I just need more information to help out.

brainkim avatar Oct 18 '21 17:10 brainkim

@brainkim React really seems to level out at ~15 MB. The issue is originally coming from a big react-native project I'm working on, its a lon running application and its crashing due to memory leak after 1 day. I made the reproduction in react only because it's easier to kickstart.

Here's a React-Native reproduction app: RN-apollo-memory-leak

When I profile the apps memory usage in Android Studio it starts around 140 MB. After triggering the read/write cycle once its 185 MB, triggering it again and its 205MB. Calling the garage collector will only release around 10 MB.

Screenshot 2021-10-19 at 06 23 15

Versions:

Android
"@apollo/client": "3.4.16"
"graphql": "15.6.1"
"react": "17.0.2"
"react-native": "0.66.0"

DanijelBojcic avatar Oct 19 '21 05:10 DanijelBojcic

@DanijelBojcic Oh yes, I can’t vouch for Apollo Client’s memory safety in React Native. Thanks for the update and reproduction. I’ll take a look when I can, though I’m not too sure about how to debug React Native memory usage yet.

brainkim avatar Oct 19 '21 05:10 brainkim

@oferitz If you’d like, please create a new issue with a description of your memory leak! Just so I can keep these issues tidy and focused.

brainkim avatar Oct 19 '21 05:10 brainkim

@brainkim Thanks for update. Sure.

oferitz avatar Oct 19 '21 05:10 oferitz

We've recently released Apollo Client 3.9 which should solve this problem in most cases. (See this blog post)

In React Native, we cannot completely solve it as they lack support for WeakRef and FinalizationRegistry, but the problem should be more manageable now due to a lot fixes included in that version. We also added a lot of configuration options to allow you to tweak a lot of different cache sizes, so you should be able to optimize your application further now.

As there is nothing more we can do on our side, I'm going to close this issue. As soon as React Native adds the missing capabilities, the code will automatically pick them up and work even better.

phryneas avatar Feb 06 '24 10:02 phryneas

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.

github-actions[bot] avatar Feb 06 '24 10:02 github-actions[bot]

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. For general questions, we recommend using StackOverflow or our discord server.

github-actions[bot] avatar Mar 09 '24 00:03 github-actions[bot]