[pull] master from ruby:master - #1332
Merged
Merged
Conversation
A port's queue lives in the receiving Ractor's table keyed by the port id, so
nothing ties it to the Ractor::Port object: when the port becomes unreachable
the queue stays, and so does every message left in it. Nobody can receive
them -- receiving needs the port -- but they are still GC roots.
A message reaching a Ractor makes that permanent. Port#<< of a port is the
natural shape of a credit token, and a token nobody takes holds the sender's
port, which marks the sender's Ractor object, which keeps its objspace in
zombie_objspaces for the life of the process:
200.times { port = Ractor::Port.new
Ractor.new(port) { |p| p << Ractor::Port.new; nil }.join }
6.times { GC.start }
ObjectSpace.each_object(Ractor).count # 201 before, 1 after
Mark and sweep the table itself. ractor_port_mark notes the ids a reachable
port still carries, and rb_ractor_finish_marking drops the queues nobody
noted, which is where the ractor-local keys are already reaped for the same
reason. Both run only where an unmarked port really is dead: after a mark
that covered every objspace -- a global GC or a full single-objspace one --
which is also when the world is stopped enough to read the table without the
owner's lock. Hence the new argument to rb_ractor_finish_marking: a minor
mark leaves live old objects unmarked.
The single-objspace question is asked first because mmtk marks from its GC
worker threads, which cannot reach the VM to answer the other one. Those
threads race on the flag, but they all store the same value and the reap
reads it once marking is over.
A queue starts alive so that one created between its port being marked and
the reap, which incremental marking allows, is not taken for an orphan. It
costs the queue one more cycle before it goes.
2000 rounds, dropping one message each, KB of RSS retained per round:
payload before after
Integer 13.0 13.3
Ractor::Port leaks 14.3
shareable 10KB 89.1 62.5
The last row is not retention: the payload is collected (0 of 500 strings
survive), but the reap only runs in a global GC, so between two of them the
dropped messages hold pages. Collecting every 20 rounds instead brings it to
1.5 KB.
The reap runs from rb_ractor_finish_marking, which only the default GC calls
-- mmtk has never called it, so the ractor-local keys it also frees are not
freed there either. Under mmtk a dropped message still holds its port, so
the test for that is a test-all case that omits itself, next to the other
tests for per-Ractor objspace semantics.
ractor-pipeline, which sends credit tokens this way, over 60 pipelines:
455MB growing by 5.6MB each to 272MB growing by 1.5MB, with the library
unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follow-up to 64b9d2f. The commit removed the check completely, because the conditions were incorrect, but there are in fact situations where the instruction is unpredictable, namely when the pre/post index update the same register as the one to be stored, e.g. `stp x0, x1, [x0, #0x10]!`. Corroborating the spec, our disassembler refuses to decode these instructions. Add condition for unpredictability as written in https://support.arm.com/documentation/ddi0602/2026-06/Base-Instructions/STP--Store-pair-of-registers-
We can use a special value of 0 in source_hash to denote that it does not have source_hash. This removes the has_source_hash field which saves us 8 bytes per iseq.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )