Keep every placement a broken pool would have lost, and drop the pin cliff - #51
Open
fpedd wants to merge 1 commit into
Open
Keep every placement a broken pool would have lost, and drop the pin cliff#51fpedd wants to merge 1 commit into
fpedd wants to merge 1 commit into
Conversation
…cliff A worker dying abruptly breaks the whole executor, so every future still in flight fails with it: `allocate_parallel` was catching that per variant and finding nothing left, turning one OOM kill into "Every allocator variant failed". The variants a broken pool stranded never ran at all, so they are retried one pool each -- never in the calling process, where whatever killed the worker would kill the caller, and never sharing a pool, where the same variant would strand them again. The thread ceiling lives in native process-global state, which a forked worker inherits and a spawned one does not, so the cap was silently absent inside every pool worker off Linux. Pools hand it down explicitly now, split by the worker count: the ceiling covers the product, not each level of it. `stack_around_pins` fell off its linear path the moment a single pin existed, rescanning every occupied range per item and inserting into it: 20k allocations went from 9ms to 14.9s, and the naive allocator is the linear baseline. Claims only ever shrink a free range from below and never split one, so the range count is fixed at what the pins leave and a max tree over the capacities answers each first fit in O(log n). The adjacency ceiling counts 4 bytes per directed edge, but the placers took their rows through `ConflictIndices`, widening every one to size_t behind a per-row vector. They walk the CSR rows in place now, so the accounting is the whole cost rather than a stage of it, and the type is gone. TwoPlusTwoSource truncated its last group below four allocations, handing back a linearizable instance from a source that promises the opposite; it refuses the count instead. Validating a Memory directly no longer names it twice, and `available_cores` reports the benchmark environment's core count rather than being unused beside `os.cpu_count`.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
A worker dying abruptly breaks the whole executor, so every future still in
flight fails with it:
allocate_parallelwas catching that per variant andfinding nothing left, turning one OOM kill into "Every allocator variant
failed". The variants a broken pool stranded never ran at all, so they are
retried one pool each -- never in the calling process, where whatever killed
the worker would kill the caller, and never sharing a pool, where the same
variant would strand them again.
The thread ceiling lives in native process-global state, which a forked
worker inherits and a spawned one does not, so the cap was silently absent
inside every pool worker off Linux. Pools hand it down explicitly now, split
by the worker count: the ceiling covers the product, not each level of it.
stack_around_pinsfell off its linear path the moment a single pinexisted, rescanning every occupied range per item and inserting into it:
20k allocations went from 9ms to 14.9s, and the naive allocator is the
linear baseline. Claims only ever shrink a free range from below and never
split one, so the range count is fixed at what the pins leave and a max tree
over the capacities answers each first fit in O(log n).
The adjacency ceiling counts 4 bytes per directed edge, but the placers took
their rows through
ConflictIndices, widening every one to size_t behind aper-row vector. They walk the CSR rows in place now, so the accounting is
the whole cost rather than a stage of it, and the type is gone.
TwoPlusTwoSource truncated its last group below four allocations, handing
back a linearizable instance from a source that promises the opposite; it
refuses the count instead. Validating a Memory directly no longer names it
twice, and
available_coresreports the benchmark environment's core countrather than being unused beside
os.cpu_count.