Skip to content

Draft: Run GC.compact before forking Puma workers

Matthias Käppler requested to merge 288042-gc-compact-before-fork into master

What does this MR do?

We recently looked into the new GC compaction feature of Ruby 2.7: https://gitlab.com/gitlab-org/memory-team/memory-team-2gb-week/-/issues/1

The conclusion is that there is a noticeable improvement in shared memory use right after forking Puma workers, however, this effect deteriorates over time to approach a memory layout similar to what we would see without compaction.

On the other hand, moving used objects slots together increases the likelihood of free pages, which when in excess can be released back to the OS. Along with tuning GC and malloc over time this will benefit overall memory use going forward.

Compaction requires a full re-org of the Ruby heap, i.e. it's expensive, but not prohibitively so. On my Core i9 it adds a little under 1s:

Cold start:

{"severity":"INFO","time":"2020-11-30T15:16:29.631Z","correlation_id":null,"message":"Heap compaction finished","duration_ms":993.3959369991499,"pid":6}

After SIGUSR2:

{"severity":"INFO","time":"2020-11-30T15:18:38.347Z","correlation_id":null,"message":"Heap compaction finished","duration_ms":934.2203660016821,"pid":6}

It won't run when bouncing individual workers, since that will not result in a before_fork event.

For now I have put this change behind an environment variable. We cannot use feature toggles here since we cannot rely on a DB connection to have been set up at this point during boot.

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Related to #288042 (closed)

Edited by Matthias Käppler

Merge request reports