-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Do not use global cache for createCache() to avoid memory leaks #3110
base: main
Are you sure you want to change the base?
Conversation
We are never using the accessor function that is returned. In the code base later we access it like this: `serverStylisCache[name]` and not like this `serverStylisCache(name)` While we could change the access, I'm not sure how we would write to the cache. So I think we can just directly return the cache object.
Currently we share caches even for multiple createCache() calls. So if you have an SSR app that reates a cache on the server like this: const cache = createCache({ key: 'custom' }); and you do this (like recommended) on every request, you still share a cache between all requests. I also think this is currently a memory leak. If you have a big application and maybe even lots of dynamic styles the cache can get quite big and will never be garbage collected.
🦋 Changeset detectedLatest commit: c417aac The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit c417aac:
|
Codecov Report
|
My coworker hunted down a memory leak in our application to this same location. He found that if we downgrade We believe it's because the Since the only purpose for the cache is SSR and you're moving any potential caching benefit into a method that would result in never being able to benefit from the cache, I think the best option would be to remove the caching concept entirely. Coming across your PR has helped us to confirm our suspicions and we really appreciate your taking the time to do this! |
@functino This is a great find! As @jrosspaperless mentioned, we had a similar issue with Emotion during SSR, and have found that providing our own After debugging further, we found that an even simpler solution within the Emotion
And then delete this line entirely since this variable will no longer be used. This way, the The root issue seems to be that the current Edit: I do also want to mention that our proposed "fixes" for this issue do call into question the usefulness of the |
What's next ? It would be great if this PR was merged |
Could somebody familiar with the issue describe step by step how the leak is created here? I admittedly haven't looked into this code yet, a concise description of the problem would help me though |
@Andarist I have some details in my comment above, but the root issue seems to be that the current When Emotion consumers do not create their own cache, or create a custom cache without specifying custom |
Hi @Andarist thanks for looking into it. The issue is that regardless how often you call
Then the cache will be shared between all those requests AND it will constantly increase in size without ever getting garbage collected. |
What:
Currently
createCache()
seems to use a global cache that is reused even if you create multiple caches. In an SSR scenario this means that even if you follow the recommendations to create a cache per render you will end up having a shared cache.Also currently an accessor function is returned from
getServerStylisCache
But later it is just used as if it would be an object
Why:
I think the current approach can cause memory-leaks in bigger applications. Since we additionally just use the
serverStylisCache
as an object, I think the cached values will never be garbage collected. This causes issues in apps that have a lot of css and/or use a lot of dynamic styles.How:
I want to change the return type of
getServerStylisCache
to a simple cache object. This is how it is already used. We could also try to use theaccessor
function. But I wouldn't know how to write to the cache then.Also I want to move the call to
getServerStylisCache
inside the function body ofcreateCache
. This way we will get a new instance of the cache for every request.I'm not sure how to add tests for this. And I'm also not sure if my assessment of what the current code is doing is correct. Maybe someone can help to shed some light on it.
Checklist: