-
-
Notifications
You must be signed in to change notification settings - Fork 418
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
Avoid clearing chunks at start of GC #4143
Conversation
Prior to this commit, at the start of GC, the heap clears all `chunks` by setting them all to `empty` in `ponyint_heap_startgc`. This is an expensive operation as it requires visiting all `chunks` and updating their `chunk->slots` and `chunk->shallow` values regardless of whether they are still in use or not. `chunk->shallow` is only ever used as part of the GC process. This commit uses the `chunk->shallow` with a `sentinel` value to avoid clearing chunks for every sizeclass except for sizeclass 0 which is still cleared and makes sure that the mark and sweep steps clear the chunk if `chunk->shallow` has the `sentinel` value and needs to be cleared. Additionally, `ponyint_heap_ismarked` is removed as it is not used.
Im not particularly familiar with this section of the code. It's been a long time. Why was it clearing all the chunks before? Is there some case where that is needed? Did there used to be? |
Clearing chunks is absolutely essential for the heap GC process to function correctly. The current logic is:
The new logic in this PR is:
The misnamed ponyc/test/libponyrt/mem/heap.cc Lines 9 to 82 in bca5a30
|
If I don't beat you to it, can you add that awesome explanation to the first comment on this PR so I can copy all of it easily when I squash and make it the commit comment? With a bit of editing to make it flow so it's not a response to someone but just general information on the commit. |
I'm torn on if this should get a change log entry. It's likely to have a performance impact but I don't want to devise a bs benchmark to be able to quantify. I'm marking this as getting a changelog entry and release notes. If anyone disagrees, please let me know before this gets merged. For the release notes, I think it should be a short entry that basically says we made the gc process more efficient without going into much technical detail. |
Hi @dipinhora, The changelog - added label was added to this pull request; all PRs with a changelog label need to have release notes included as part of the PR. If you haven't added release notes already, please do. Release notes are added by creating a uniquely named file in the The basic format of the release notes (using markdown) should be:
Thanks. |
i've updated the first comment of this PR and added release notes.. |
As part of ponylang#4143, the logic was changed to avoid clearing chunks at the start of GC (except for sizeclass 0) by using a sentinel value in the `chunk->shallow` field. This commit, changes the implementation to rely on pointer tagging of the `chunk->m` field using the lowest bit to track whether a chunk needs to be cleared or not. The sentinel in the `chunk->shallow` is no longer needed/used allowing for this optimization to work for all sizeclasses (including the previously exclude sizeclass 0). All accesses to the `chunk->m` field now go through the utility function `get_m` to clear out the tagged bit first.
As part of ponylang#4143, the logic was changed to avoid clearing chunks at the start of GC (except for sizeclass 0) by using a sentinel value in the `chunk->shallow` field. This commit, changes the implementation to rely on pointer tagging of the `chunk->m` field using the lowest bit to track whether a chunk needs to be cleared or not. The sentinel in the `chunk->shallow` is no longer needed/used allowing for this optimization to work for all sizeclasses (including the previously excluded sizeclass 0). All accesses to the `chunk->m` field now go through the utility function `get_m` to clear out the tagged bit first.
As part of #4143, the logic was changed to avoid clearing chunks at the start of GC (except for sizeclass 0) by using a sentinel value in the `chunk->shallow` field. This commit, changes the implementation to rely on pointer tagging of the `chunk->m` field using the lowest bit to track whether a chunk needs to be cleared or not. The sentinel in the `chunk->shallow` is no longer needed/used allowing for this optimization to work for all sizeclasses (including the previously excluded sizeclass 0). All accesses to the `chunk->m` field now go through the utility function `get_m` to clear out the tagged bit first.
Prior to this commit, at the start of GC, the heap clears all
chunks
by setting them all toempty
inponyint_heap_startgc
.This is an expensive operation as it requires visiting all
chunks
and updating theirchunk->slots
andchunk->shallow
values regardless of whether they are still in use or not.
chunk->shallow
is only ever used as part of the GC process.The old logic for heap GC was:
clear chunks
)This commit uses the
chunk->shallow
with asentinel
value to avoid clearing chunks for every sizeclass except
for sizeclass 0 which is still cleared and makes sure that
the mark and sweep steps clear the chunk if
chunk->shallow
has thesentinel
value and needs to becleared. Additionally,
ponyint_heap_ismarked
is removedas it is not used.
The new logic for heap GC is:
clear chunks
)chunk->shallow
set to asentinel
value to indicate that they need to be cleared as part of trace/sweepchunk->shallow
has thesentinel
value (to preserve the illusion that the chunk was cleared before GC was started) before proceeding with normal marking logicchunk->shallow
has thesentinel
value (to preserve the illusion that the chunk was cleared before GC was started) before proceeding with normal sweeping logicchunk->shallow
to thesentinel
value in prep for the next GC iterationponyint_heap_alloc*
functions to setchunk->shallow
to thesentinel
value in prep for the next GC iteration for all newly allocated chunks