Skip to content

Instantly share code, notes, and snippets.

@damiendoligez
Created July 16, 2024 08:46
Show Gist options
  • Save damiendoligez/a7f2c93e92469d6adb74ac687fd3bfdc to your computer and use it in GitHub Desktop.
Save damiendoligez/a7f2c93e92469d6adb74ac687fd3bfdc to your computer and use it in GitHub Desktop.
OCaml GC pacing, continued

[1] https://gist.github.com/stedolan/52c13d6b1a30276db31ca98683c8db16

Stephen Dolan suggested that we count only live data as sweeping work for the purpose of GC pacing. In other words, the work counter for sweeping is only incremented when we sweep a live block, not when we sweep a free block or a garbage block.

This is to improve the stability of the system by removing a feedback loop. If we count the whole heap size as sweeping work, then the GC speed depends on the heap size, which itself depends on the GC speed (if the GC is slow, heap size will increase).

Then the formulas found in [1] are modified as follows:

A major GC cycle

Allocated data at cycle start:

L + Lg

Allocated data at the end of marking:

L + Lg + L/m

Allocated data at the end of sweeping, assuming that we also sweep all the data allocated during sweeping (which is all live, as far as this cycle is concerned):

L + L/m + (L + L/m) / s + (L + L/m) / s^2 + ...
= (L + L/m) s / (s - 1)

This is: what was live at cycle start (L), plus what was allocated during marking (L/m), plus what was allocated during sweeping of the (L + L/m) that are live at the beginning of sweeping ((L + L/m) / s), plus what was allocated during the sweeping of these allocations, etc.

Steady-state and stability

L + L g' = (L + L/m) s / (s - 1)
1 + g' = (1 + 1/m) s / (s - 1)
g' = (s/m + 1) / (s - 1) = 1/m + 1/(s-1) + 1/m(s-1)

There is no linear recurrence anymore, but the stability condition is still the same: s > 1.

the overhead o = g + 1/m is now:

o = 2/m + 1/(s-1) + 1/m(s-1)

Choosing m and s

Still taking

λ = m/s
m = λs

We now have

o = 2/λs + 1/(s-1) + 1/λs(s-1)
oλs^2 - (oλ + λ + 2)s + 1 = 0

Solving for s, we get two solutions, using μ = 1 + 2/λ to make it more readable:

s1 = 1/2 + (μ + sqrt(o^2 + μ^2)) / 2o
s2 = 1/2 + (μ - sqrt(o^2 + μ^2)) / 2o

s2 is less than 1, so our solution is s1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment