-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
perf: Freeze GC before forking Gunicorn workers #21474
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
github-actions
bot
added
the
add-test-cases
Add test case to validate fix or enhancement
label
Jun 24, 2023
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## develop #21474 +/- ##
========================================
Coverage 63.85% 63.85%
========================================
Files 766 766
Lines 69436 69440 +4
Branches 6276 6276
========================================
+ Hits 44337 44343 +6
+ Misses 21514 21512 -2
Partials 3585 3585
Flags with carried forward coverage won't be shown. Click here to find out more. |
This is disabled on 99%+ sites, still incurs 3-4MB of memory hit on import of ldap3.
This reverts commit 71b44ef. This gets frequently imported from one place or another. Since with gc.freeze we can mostly reuse the import from parent, let's just leave it here.
This has overall 1-2% CPU usage reduction for little to no costs. Benefits increase when doing bulk processing with lots of objects.
BG worker forks are not CoW friendly. Freezing right before we start worker should lessen overall memory usage. Though this isn't useful much because at max you're sharing with 2 processes - master and horse. WorkerPool can improve this benefit a lot by forking each worker from master process and horse from forked processes. TBD when WorkerPool is out of beta.
This was referenced Jun 24, 2023
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Both Gunicorn and RQ use forking to spawn workers. In an ideal world, the fork should be sharing most of the memory if there are no writes made to data because of Copy on Write, however, python's GC is not CoW friendly and writes to data even if user-code doesn't. Specifically, the generational GC which stores and mutates every python object:
PyGC_Head
This can be avoided by doing
gc.freeze()
pre-fork to freeze all current objects and move them permanently to the last generation of generational gc.Reference:
This is behind an environment variable for now, enable by setting
FRAPPE_TUNE_GC
to any truthy value.Preliminary numbers
PS: measuring benefit of this is kinda hard as memory usage depends on usage, without freeze most shared memory would become unshared over time.
TODO:
Apply the same logic to background jobs.Not possible, we right now create duplicate processes instead of forking from one master process. RQ is inefficient for this, though something like workerpool or https://github.com/ankush/rq_orchestrator/ can solve this.Should close #18927
Continues #21473, #21467