gh-155811: Add a seqcount to gc_stats to prevent torn reads - #155828
Conversation
|
I'm concerned that we now need to read memory three times with this approach: If What do you think? |
|
@sergey-miryanov I'd push back. :-) is around ~200KHz. I'm not sure if there's a guarantee about copy-order and monotonicity of Also, assuming these guarantees,
|
|
Yes, my variant will not work, I thought more about it - so drop it :) |
|
What if:
Reader:
|
|
Even better, we could pack both counters into a single 32-bit integer — using the lower 16 bits for What do you think? |
|
@sergey-miryanov The latter requires a full atomic snapshot read of the whole struct. Otherwise there's a race risk? Atomicity is not guaranteed: The former (ie: Perhaps we could do _Py_RemoteDebug_BatchedReadRemoteMemory, since iovec provides such guarantee:
That said,
To be honest, I don't think that one additional syscall is that bad. Measured 200KHz is solid (way more than gcmon needs), it's not a hot path, and is trivial to wrap one's head around. In practice (implementation detail), I remember measuring it and small reads are much faster. I also added The thing that I think is worth measuring - and I'm not an expert here - is the probability of collision. What's the maximum observable GC? The Sorry for so much text :) I keep posting essays here but wanted to explain myself, since maybe I'm making a fatal blunder here. Does it make sense to you? |
|
I tested on this script: Average duration for Average duration of I don't think we can achieve 100Khz rate for gc.collect :) |
|
@colesbury I know that we've just removed |
I mean one more try if we fail on the first attempt. @maurycy, would you mind adding a single retry pass? |
@sergey-miryanov It introduces some complexity. Do you think it could be avoided with gcmon retrying? |
|
@maurycy It seems cheaper to do the retry inside the call rather than from gcmon. A |
|
That was faster than light. Thank you, @pablogsal. 🖤 |
|
Thanks @maurycy for the PR, and @pablogsal for merging it 🌮🎉.. I'm working now to backport this PR to: 3.15. |
|
Sorry, @maurycy and @pablogsal, I could not cleanly backport this to Please backport manually with cherry_picker, see the devguide for more information. |
|
Thanks all! |
|
@maurycy Do you want to take a look at the backport? If not, I can handle it myself. |
|
GH-158829 is a backport of this pull request to the 3.15 branch. |
|
GH-158829 is a backport of this pull request to the 3.15 branch. |
…H-155828) (#158829) * update_seq * no need for XCHGL, MOVL is enough? * gh-155811: Retry an inconsistent GC snapshot once --------- (cherry picked from commit 5fecd44) Co-authored-by: Pablo Galindo Salgado <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]>
See #155811 for the context.
tl;dr
get_gc_statsreads the stats without pausing the target (by design), so it can return torn data.The PR adds a seqcount to
gc_statsatomically increased by the writer around the stats update on every collection, where odd means it's in progress.gcmon is the main consumer.
There's no retry, as per #155811 (comment). It's not needed.
gc.collect()does not happen that often:For:
I'm not sure what's optimal non-hacky test. We haven't had one in #152448. To be honest, it's implicitly tested by the current happy-path tests in
test_gc_stats.