apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.38k stars 2.66k forks source link

`executeSelectionSize` cache default size is misdocumented #12011

Closed CamJohnson26 closed 3 months ago

CamJohnson26 commented 3 months ago

Issue Description

The code comments claim that executeSelectionSize has a 10,000 max size default, but the actual default is 50,000 at the bottom of the same file: https://github.com/apollographql/apollo-client/blob/bcedcad8539ab6bade93f79972387984768b6544/src/utilities/caching/sizes.ts#L255

This could also use more explanation, since it's currently not clear what unit these defaults are or what the implications are of increasing them. Our app slows down significantly when we exceed the limit, but not sure how safe it is to increase it.

Link to Reproduction

https://github.com/apollographql/apollo-client/blob/bcedcad8539ab6bade93f79972387984768b6544/src/utilities/caching/sizes.ts#L255

Reproduction Steps

Not applicable, documentation

@apollo/client version

^3.11

jerelmiller commented 3 months ago

Hey @CamJohnson26 👋

You're right! I updated the defaults in https://github.com/apollographql/apollo-client/pull/11495 but forgot to come back to those comments and update them. Good catch!

As for what these caches do, check out this doc which contains some valuable information on how we use those caches internally to the client and some tips about adjusting those sizes to fit your application.

These values are absolutely safe to modify. The defaults we chose were a "should fit most" approach but understood that these may not be sufficient for some of the larger apps out there, hence why we allow you to change these values.

Hope this helps! Let me know if you have any other questions.

CamJohnson26 commented 3 months ago

Awesome thanks, yeah we read through that document pretty carefully, I'll try to dig through some of this source code too.

While I have you, I assume the tradeoff of increasing this value is more RAM usage on the Browser? Any quick advice about how to derisk that?

jerelmiller commented 3 months ago

Ok great! Is there anything in that doc that could use some clarity?

I assume the tradeoff of increasing this value is more RAM usage on the Browser?

Correct, Larger cache size = more objects the cache will hold before it starts evicting values from the cache.

Let me tag @phryneas since he is a bit more familiar with this particular internal cache to see if he has any advice for helping keep the size reasonable.

CamJohnson26 commented 3 months ago

I think the main thing that's confusing is what does 50,000 mean, I'm assuming it's the number of allowed cache keys, but unclear if it's related to the size of the cached objects or not.

Also would be helpful to know what happens when the limit is exceeded if possible.

phryneas commented 3 months ago

These limits are memoization limits - 50.000 means that we save the last 50.000 results of calling executeSelectionSet with different arguments internally.

When the limit is reached, the method results that have not been used for the longest amount of time will be dropped from the cache, and the calculation has to be done again the next time executeSelectionSet is called with these arguments.

executeSelectionSet in this case is called for each parent object with a selection set - so if you had something like

query AuthorsAndBooks {
  author {
    name
    books {
      name
      isbn
      comments {
        username
        content
      }
    }
   }
}

and you got 3 authors back, 5 books per author, and 10 comments per book, you would look at more or less

So in total, you'd need a cache size of 169 to select this one query from the cache.

Since these calls might happen a lot, it's important to keep the cache size so big that the cache can always fit every selection you currently are subscribed to, otherwise new caclulations need to be made and run the risk of kicking other calculations out of the cache that then also have to be made again.

On the other hand, you probably don't want to make the cache size so big that it keeps all calculations made for the last 20 pages your user was visiting around, since that would be a waste of memory.

A good rule of thumb would probably be to go to the page in your app that displays the most data, reloading so that only that page's calculations are in the cache, look at the cache size and then maybe double that value just to be sure.

CamJohnson26 commented 3 months ago

Thanks so much @phryneas and @jerelmiller , that's really helpful and I think we should be able to optimize based on this info.

jerelmiller commented 3 months ago

Great! I'll go ahead and close this issue. Let us know if you need anything else!

github-actions[bot] commented 3 months ago

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] commented 2 months ago

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.