diff --git a/skills/kvb-org-queue/SKILL.md b/skills/kvb-org-queue/SKILL.md index 12370f1..bc3a3cf 100644 --- a/skills/kvb-org-queue/SKILL.md +++ b/skills/kvb-org-queue/SKILL.md @@ -58,8 +58,7 @@ From the last 30 days, once 5 runs exist: - per signature, the disk need is p90 disk taken plus 1 GB; - per kind, the slot limit is how many p90 RAM and CPU shares fit between the median load at the grant and `load_limits`, at least 1; -- per job, the footprint is the larger p90 share of its kind and of its - signature, else the largest of its kind. +- per job, the footprint is its signature's p90 share, else its kind's. Until then the seeds hold: `slot_need_gb[kind]` for disk, 1 slot per kind, the whole budget as footprint: it runs alone. diff --git a/skills/kvb-org-queue/scripts/history.py b/skills/kvb-org-queue/scripts/history.py index 5eca130..6326053 100644 --- a/skills/kvb-org-queue/scripts/history.py +++ b/skills/kvb-org-queue/scripts/history.py @@ -212,21 +212,14 @@ def footprint(kind: str, name: str, signatures: dict[str, dict], kinds: dict[str kinds: the kind map of learn(). Returns: - {ram, cpu}: the larger of the kind's p90 share and the signature's, at - least MIN_SHARE_PERCENT; a signature not learned yet takes the largest - learned share of its kind. None while the kind is not learned yet. + {ram, cpu}: the signature's p90 share once learned, else the kind's, at + least MIN_SHARE_PERCENT. None while the kind is not learned yet. """ if kind not in kinds or kinds[kind]["ram_share"] is None: return None - own_kind = kinds[kind] - if name in signatures and signatures[name]["ram_share"] is not None: - peers = [signatures[name]] - else: - peers = [s for s in signatures.values() if kind in s["kinds"] and s["ram_share"] is not None] - return { - resource: max([MIN_SHARE_PERCENT, own_kind[f"{resource}_share"], *(peer[f"{resource}_share"] for peer in peers)]) - for resource in RESOURCES - } + own = signatures.get(name) + source = own if own and own["ram_share"] is not None else kinds[kind] + return {resource: max(MIN_SHARE_PERCENT, source[f"{resource}_share"]) for resource in RESOURCES} def seed_ram(kinds: dict[str, dict]) -> float: diff --git a/tests/test_queue.py b/tests/test_queue.py index f969485..7e817b9 100644 --- a/tests/test_queue.py +++ b/tests/test_queue.py @@ -308,7 +308,17 @@ class TestHistory(unittest.TestCase): crowded = [history_row(n, mem_before=90, mem_max=95) for n in range(5)] self.assertEqual(self.learn(crowded)[1]["test"]["limit"], 1) - def test_footprint_takes_the_larger_of_kind_and_signature_at_least_the_minimum_and_none_for_a_new_kind(self): + def test_a_light_command_of_a_heavy_kind_and_an_unlearned_one_are_not_booked_at_the_heaviest_share(self): + signatures = { + "skills: make test": {"ram_share": 3.3, "cpu_share": 4, "kinds": {"test"}}, + "gate.py hold": {"ram_share": 42.6, "cpu_share": 93.5, "kinds": {"test", "test-nostack"}}, + } + kinds = {"test": {"ram_share": 35.2, "cpu_share": 83.6}, "test-nostack": {"ram_share": 5.6, "cpu_share": 73.8}} + footprint = self.history.footprint + self.assertEqual(footprint("test", "skills: make test", signatures, kinds), {"ram": 3.3, "cpu": 4}) + self.assertEqual(footprint("test-nostack", "core: docker build", signatures, kinds), {"ram": 5.6, "cpu": 73.8}) + + def test_footprint_takes_the_learned_signature_else_the_kind_at_least_the_minimum_and_none_for_a_new_kind(self): small = [history_row(n, signature="make test", mem_max=25, cpu_max=20) for n in range(5)] big = [ history_row(n + 5, kind="quality-high", signature="make verify-test", mem_max=80, cpu_max=90)