Commit c5ca470
Fix malloc counters during GC
ruby#16919 changed malloc counters to be
reset in `gc_sweep_finish`. However, this introduced two problems:
1. If a GC is triggered due to the `malloc_limit` being hit, then it would
run a GC with lazy sweeping, during lazy sweeping Ruby code could call
`xmalloc`, which would immediately finish sweeping by calling `gc_rest`
because the `malloc_increase` is not reset.
2. When `gc_rest` is called, it immediately completes sweeping. However,
all of the counters for the freed memory is lost because `malloc_increase`
is reset at the end. Previously, lazy sweeping would be interleaved
with Ruby code execution, meaning `xfree` was interleaved with `xmalloc`,
allowing for more memory to be allocated before `malloc_increase` hits
`malloc_limit`.
The issue can be reproduced by this script:
live = []
500.times do
live << Array.new(200) { String.new(capacity: 64 * 1024) }
end
puts GC.stat
Before:
{count: 235, ..., minor_gc_count: 196, major_gc_count: 39}
After:
{count: 196, ..., minor_gc_count: 153, major_gc_count: 43}1 parent ad06e4a commit c5ca470
1 file changed
Lines changed: 3 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4023 | 4023 | | |
4024 | 4024 | | |
4025 | 4025 | | |
4026 | | - | |
4027 | | - | |
4028 | | - | |
4029 | | - | |
4030 | | - | |
4031 | | - | |
4032 | | - | |
4033 | 4026 | | |
4034 | 4027 | | |
4035 | 4028 | | |
| |||
6464 | 6457 | | |
6465 | 6458 | | |
6466 | 6459 | | |
| 6460 | + | |
6467 | 6461 | | |
6468 | 6462 | | |
6469 | 6463 | | |
| |||
6519 | 6513 | | |
6520 | 6514 | | |
6521 | 6515 | | |
| 6516 | + | |
| 6517 | + | |
6522 | 6518 | | |
6523 | 6519 | | |
6524 | 6520 | | |
| |||
0 commit comments