Files

175 lines
6.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Unit tests for the cost model — trivial-glue tier and long-pole detection."""
from nix_estimator import costmodel, schedule
from nix_estimator.estimate import _recommend
def test_glue_derivations_are_trivial():
# NixOS assembly glue must not be costed like a real compile.
for name in [
"unit-dbus-broker.service",
"X-Restart-Triggers-dbus-broker",
"user-units",
"etc",
"activate",
"system-path",
"nixos-system-emmett-26.11",
"dbus-1",
"sshd.service",
]:
assert costmodel.is_trivial(name), name
mins, _ = costmodel.cost(f"/nix/store/hash-{name}.drv")
assert mins <= 0.1, (name, mins)
def test_real_packages_are_not_trivial():
for name in [
"onnxruntime-1.17.0",
"hello-2.12",
"openssl-3.0.0",
"python3.13-numpy-2.0",
]:
assert not costmodel.is_trivial(name), name
def test_glue_chain_does_not_dominate_span():
# A 100-deep glue chain used to fabricate a ~100-min span at DEFAULT=1min.
names = [f"unit-svc{i}.service" for i in range(100)]
dur = {n: costmodel.cost(f"/nix/store/h-{n}.drv")[0] for n in names}
preds = {n: ([names[i - 1]] if i else []) for i, n in enumerate(names)}
span, _ = schedule.critical_path(dur, preds)
assert span < 10.0 # 100 × 0.05 == 5 min, not 100
def _cost(name):
return costmodel.cost(f"/nix/store/hash-{name}.drv")
def test_heavy_substring_does_not_over_fire():
# Substring keys used to inflate ordinary libs/wrappers to HEAVY (issue #6).
for name in [
"python3.12-requests-2.31.0", # "python3" is a substring, not the pname
"util-linux-2.39", # "linux-" is a substring, not the pname
"gcc-wrapper-13", # toolchain shim
"rustc-wrapper", # toolchain shim
"clang-wrapper-16",
"grpcio-1.62", # not grpc
]:
mins, _ = _cost(name)
assert mins <= costmodel.DEFAULT[0], (name, mins)
def test_heavy_real_pnames_still_fire():
# Genuine heavy derivations must still hit the HEAVY table.
expected = {
"llvm-15.0.7": costmodel.HEAVY["llvm"],
"onnxruntime-1.16.0": costmodel.HEAVY["onnxruntime"],
"ghc-9.4.8": costmodel.HEAVY["ghc"],
"rustc-1.75.0": costmodel.HEAVY["rustc"], # the real compiler
"python3-3.12.7": costmodel.HEAVY["python3"], # the interpreter
"gcc-13.2.0": costmodel.HEAVY["gcc"],
"linux-6.6.30": costmodel.HEAVY["linux-"], # the kernel
}
for name, val in expected.items():
assert _cost(name) == val, name
def test_history_longest_prefix_wins_regardless_of_order():
# Overlapping prefixes must resolve deterministically to the longest match.
drv = "/nix/store/hash-gcc-13.2.0.drv"
for hist in (
{"gcc": 40.0, "gcc-13": 5.0},
{"gcc-13": 5.0, "gcc": 40.0},
):
mins, _ = costmodel.cost(drv, history=hist)
assert mins == 5.0, hist
def test_history_exact_name_wins_first():
drv = "/nix/store/hash-gcc-13.2.0.drv"
hist = {"gcc-13.2.0": 7.0, "gcc-13": 5.0, "gcc": 40.0}
mins, _ = costmodel.cost(drv, history=hist)
assert mins == 7.0
def test_default_min_override_only_moves_default_bucket():
# A DEFAULT-bucket lib picks up the override...
lib = "/nix/store/hash-somelib-1.2.3.drv"
assert costmodel.cost(lib)[0] == costmodel.DEFAULT[0]
mins, scaling = costmodel.cost(lib, default_min=3.0)
assert mins == 3.0
assert scaling == 0.30
# ...but HEAVY, fixed-output, trivial and history results are untouched.
heavy = "/nix/store/hash-llvm-15.0.7.drv"
assert costmodel.cost(heavy, default_min=3.0) == costmodel.HEAVY["llvm"]
fetch = "/nix/store/hash-source.drv"
fo_drv = {"outputs": {"out": {"hash": "abc", "hashAlgo": "sha256"}}}
assert costmodel.cost(fetch, drv=fo_drv, default_min=3.0) == costmodel.FIXED_OUTPUT
glue = "/nix/store/hash-unit-sshd.service.drv"
assert costmodel.cost(glue, default_min=3.0) == costmodel.TRIVIAL
hist_mins, _ = costmodel.cost(lib, history={"somelib-1.2.3": 9.0}, default_min=3.0)
assert hist_mins == 9.0
def test_fit_defaults_per_bucket_medians():
closure = {
# HEAVY — must be excluded from the DEFAULT median despite a history entry.
"/nix/store/h-llvm-15.0.7.drv": {},
# fixed-output fetch.
"/nix/store/h-mysource-1.0.drv": {
"outputs": {"out": {"hash": "z", "hashAlgo": "sha256"}}
},
# trivial glue.
"/nix/store/h-unit-foo.service.drv": {},
# DEFAULT libs (odd count -> exact median).
"/nix/store/h-liba-1.drv": {},
"/nix/store/h-libb-1.drv": {},
"/nix/store/h-libc-1.drv": {},
}
history = {
"llvm-15.0.7": 200.0, # HEAVY, excluded
"mysource-1.0": 0.5,
"unit-foo.service": 0.02,
"liba-1": 2.0,
"libb-1": 6.0,
"libc-1": 10.0,
}
out = costmodel.fit_defaults(history, closure)
assert out["default_min"] == 6.0 # median(2,6,10), llvm excluded
assert out["n_default"] == 3
assert out["fixed_output_min"] == 0.5
assert out["n_fixed_output"] == 1
assert out["trivial_min"] == 0.02
assert out["n_trivial"] == 1
def test_fit_defaults_empty_bucket_reports_none():
closure = {"/nix/store/h-liba-1.drv": {}, "/nix/store/h-libb-1.drv": {}}
history = {"liba-1": 4.0, "libb-1": 8.0} # no fetch/glue measured
out = costmodel.fit_defaults(history, closure)
assert out["default_min"] == 6.0 # median(4,8) even count -> mean of middle two
assert out["n_default"] == 2
assert out["fixed_output_min"] is None
assert out["n_fixed_output"] == 0
assert out["trivial_min"] is None
assert out["n_trivial"] == 0
def test_recommendation_note_branches_on_dominator():
grid = {
(1, 8): 40.0,
(1, 16): 30.0,
(1, 32): 25.0,
(2, 8): 40.0,
(2, 16): 30.0,
(2, 32): 25.0,
}
heavy = _recommend(grid, 4, (8, 16, 32), (1, 2), 0.12, span_dominator_frac=0.8)
assert "one heavy derivation" in heavy["note"]
chain = _recommend(grid, 4, (8, 16, 32), (1, 2), 0.12, span_dominator_frac=0.05)
assert "long chain of small derivations" in chain["note"]