Skip to content

Commit 9aabc85

Browse files
committed
tests : drive the started-slot trim from the prompt lengths instead of the host's speed
1 parent 6d62ad7 commit 9aabc85

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

tools/server/tests/unit/test_preempt.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ def _wait_processing(slot_ids, timeout: float = 30.0):
100100
pytest.fail(f"slots {slot_ids} never showed as processing")
101101

102102

103+
def _wait_preempted(timeout: float = 30.0) -> bool:
104+
"""True once some slot is parked: its cells are in host RAM and it wants them back."""
105+
deadline = time.time() + timeout
106+
while time.time() < deadline:
107+
slots = server.make_request("GET", "/slots").body
108+
if any(s["is_preempted"] for s in slots):
109+
return True
110+
time.sleep(0.005)
111+
return False
112+
113+
103114
def _prompt_of(n_tokens: int, text: str) -> list:
104115
"""A prompt of exactly n_tokens tokens, as ids: no BOS is added to one of those."""
105116
base = server.make_request("POST", "/tokenize", data={"content": text}).body["tokens"]
@@ -412,22 +423,27 @@ def test_cancel_while_a_copy_is_in_flight_frees_the_slot():
412423

413424
def test_a_started_slot_is_counted_by_the_cells_it_holds_not_by_the_prompt_it_keeps():
414425
# the last request waits for slot 0 and is started on it holding the first request's cells; counted by the prompt it keeps instead, the pool looks free and a parked slot is restored into cells that are still taken
415-
_start(n_ctx=256, n_slots=3)
426+
_start(n_ctx=1024, n_slots=3)
427+
428+
# the lengths, not the host's speed, decide who is parked: the three prompts (500 + 200 + 200) fit the 1024 cells, so both of the others are parked holding at least their whole prompt once slot 0 grows into the rest, and slot 0 is the largest slot throughout, which the planner never picks as a victim. Slot 0 ends holding 960 of the 1024 cells, too few left for either parked slot to come back
429+
ids = _prompt_of(500, _PROMPT_C)
416430

417-
# queued behind a busy slot 0, so it starts on the cells the first request keeps while the two long ones still want the pool; polling for a busy slot 0 with all four in flight missed a short first request on a Windows runner and sent the follower into an idle pool
418-
with ThreadPoolExecutor(3) as pool:
419-
long_ones = [pool.submit(_complete, 200, _PROMPT_A, 1), pool.submit(_complete, 200, _PROMPT_B, 2)]
420-
_wait_processing([1, 2])
421-
first = pool.submit(_complete, 100, _prompt_of(115, _PROMPT_C), 0)
431+
with ThreadPoolExecutor(4) as pool:
432+
first = pool.submit(_complete, 460, ids, 0)
422433
_wait_processing([0])
423-
follower = _complete(8, _PROMPT_C, 0)
424-
results = [first.result(), long_ones[0].result(), long_ones[1].result(), follower]
434+
# queued behind slot 0 whatever the host's speed, and a real prefix of what slot 0 holds: it starts on 960 cells while keeping 8 of them
435+
follower = pool.submit(_complete, 8, ids[:8], 0)
436+
long_ones = [pool.submit(_complete, 400, _prompt_of(200, _PROMPT_A), 1),
437+
pool.submit(_complete, 400, _prompt_of(200, _PROMPT_B), 2)]
438+
parked = _wait_preempted()
439+
results = [first.result(), follower.result(), long_ones[0].result(), long_ones[1].result()]
425440

426441
text = _log()
442+
assert parked, "the pool never came under pressure, so no slot was waiting for the cells slot 0 keeps"
427443
assert "trimmed to the" in text, "the started slot kept the cells of the request before it"
428444
assert "resume failed" not in text
429445
assert "Context size has been exceeded" not in text
430-
for res, n_predict in zip(results, (100, 200, 200, 8)):
446+
for res, n_predict in zip(results, (460, 8, 400, 400)):
431447
assert res.status_code == 200, res.body
432448
assert res.body["timings"]["predicted_n"] == n_predict
433449

0 commit comments

Comments
 (0)