Skip to content

feat(memory): Badness-score abort victim selection in SharedArbitrator#9

Open
jaylisde wants to merge 1 commit into
mainfrom
feat/memory-arbitration-abort-scoring
Open

feat(memory): Badness-score abort victim selection in SharedArbitrator#9
jaylisde wants to merge 1 commit into
mainfrom
feat/memory-arbitration-abort-scoring

Conversation

@jaylisde

@jaylisde jaylisde commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Motivation

Today's abort victim selection is lexicographic: priority first, then capacity bucket, then age. Priority acts as a hard wall — no amount of capacity difference can override even a 1-step priority gap. This change converts a priority step into a bytes-equivalent and adds it to capacity, so a large enough capacity difference can punch through a small priority gap. The weight knob controls how hard the wall is: a large weight keeps priority dominant, a small weight lets capacity matter.

Problem

With the current hard-wall ordering, three issues arise when capacity is unevenly distributed:

  1. Any priority gap gives absolute protection. A large query with even 1 step higher priority is completely shielded from abort, regardless of how much memory it holds. The capacity difference is ignored because priority dominates unconditionally.

  2. Wasted aborts that don't satisfy the reclaim target. The arbitrator kills lower-priority queries one by one. If each is smaller than the target, no single abort satisfies the request — so the cascade continues until enough queries are dead.

  3. Excessive collateral damage. Multiple small queries are killed when a single large query could satisfy the reclaim target in one abort — but is never considered because of its priority.

Implementation

Replace the legacy lexicographic victim selection with a single badness-score mechanism:

score = currentCapacity + priority * (priorityWeightPct * arbitratorCapacity)
  • Capacity term uses currentCapacity (abort frees the whole pool).
  • Priority weight (abort-priority-weight-pct, default 1.0) is the exchange rate between priority and capacity — how many bytes one priority step is worth, expressed as a fraction of arbitrator capacity. This keeps the config portable across deployment sizes.

Default behavior: the default weight (1.0) preserves priority dominance — a higher-priority query will not be aborted before lower-priority ones. Lowering the weight (e.g. 6.25%) lets capacity override small priority gaps across groups.

Behavioral difference from legacy within the same priority group: scoring picks the strictly largest candidate first, with age as tie-break when capacity is equal (younger aborted first). Legacy used capacity bucketing which could skip larger candidates in favor of younger ones within the same bucket. The largest candidate is always considered first, reducing the number of abort rounds needed.

Before vs After

Setup: 1 GB pool, 6 queries, arbitrator needs to reclaim 300 MB. big_etl (priority=1, 600 MB) is only 1 priority step above 5 small queries (all priority=2, totaling 340 MB).

Results:

Before (legacy) After (scoring, weight=6.25%)
Victim selection priority=1 absolutely protected 600 MB capacity outweighs 1-step gap
Aborts to satisfy 300 MB 5 1
Queries surviving 1/6 5/6
MB reclaimed per abort 68 avg 600

Scoring breaks the absolute priority shield, eliminates wasted cascade aborts, and reduces collateral from 5 killed queries to 1.

@jaylisde
jaylisde force-pushed the feat/memory-arbitration-abort-scoring branch from 1fc190e to e92a2e6 Compare June 7, 2026 22:57
@jaylisde jaylisde closed this Jun 7, 2026
@jaylisde jaylisde reopened this Jun 7, 2026
@jaylisde
jaylisde force-pushed the feat/memory-arbitration-abort-scoring branch 8 times, most recently from 4916733 to 0569b0e Compare June 8, 2026 00:32
@jaylisde
jaylisde force-pushed the feat/memory-arbitration-abort-scoring branch from 65921e0 to 98df931 Compare June 18, 2026 07:07
@jaylisde
jaylisde force-pushed the feat/memory-arbitration-abort-scoring branch 6 times, most recently from 37d9a8f to e7faec4 Compare June 19, 2026 16:03
Replace the legacy lexicographic abort victim selection (priority, then
capacity bucket, then age) with a single badness-score mechanism:

  score = currentCapacity + priority * (abort-priority-weight-pct * capacity)

The weight knob (default 1.0) controls how strongly priority dominates.
A large weight keeps priority dominant; a small weight lets capacity
matter — so a large enough capacity difference can punch through a small
priority gap.

Within the same score, the younger participant is aborted first.

Benchmark (6 queries, 1 GB, reclaim 300 MB, weight=6.25%):
  Before: 5 aborts, 1/6 surviving
  After:  1 abort,  5/6 surviving
@jaylisde
jaylisde force-pushed the feat/memory-arbitration-abort-scoring branch from e7faec4 to 2794bd1 Compare June 19, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant