From bf496b3b24bdc543b108334be70edeeaf7a6fc05 Mon Sep 17 00:00:00 2001 From: deucalioncodes Date: Wed, 16 Sep 2026 18:16:56 +0200 Subject: [PATCH] bench: measure list-shaped reads (load_page_50, instances_all, instances_sparse) The suite only covered single-entity operations, so the range-paging change in 0.12.0 (#14) was invisible to it. Add three cases: - load_page_50: cold load_some(1, 50) - instances_all: cold instances() with every id present - instances_sparse: cold instances() after deleting every other id Measured on a local replica with the Basilisk 0.15.0 template, v0.11.0 vs v0.12.0 (instructions, db=500 entity pairs): instances_all 700.6M -> 488.3M (-30%) instances_sparse 416.7M -> 246.1M (-41%) load_page_50 66.9M -> 47.4M (-29%) load 1.18M -> 1.04M (-12%) Remaining cost is ~0.95M instructions per hydrated entity (JSON decode + Entity construction), which is the next target. Co-authored-by: Cursor --- tests/entrypoint_benchmark.py | 3 +++ tests/src/tests/test_benchmark.py | 37 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/tests/entrypoint_benchmark.py b/tests/entrypoint_benchmark.py index b73c342..c39c6cc 100644 --- a/tests/entrypoint_benchmark.py +++ b/tests/entrypoint_benchmark.py @@ -17,6 +17,9 @@ "load_level1", "load_level3", "serialize", + "load_page_50", + "instances_all", + "instances_sparse", "deserialize_new_level1", "deserialize_new_level3", "deserialize_existing_level1", diff --git a/tests/src/tests/test_benchmark.py b/tests/src/tests/test_benchmark.py index f02380c..94b8f43 100644 --- a/tests/src/tests/test_benchmark.py +++ b/tests/src/tests/test_benchmark.py @@ -93,6 +93,43 @@ def load_level3(self, count: str): ic.print(f"BENCH_RESULT:load_level3:{count}:{cost}") return cost + def load_page_50(self, count: str): + """Measure cost of a cold load_some(1, 50) page at given DB size.""" + self._clear() + count = int(count) + _seed_entities(count) + Database.get_instance().clear_registry() + cost, _ = _measure(lambda: BenchZone.load_some(1, 50)) + ic.print(f"BENCH_RESULT:load_page_50:{count}:{cost}") + return cost + + def instances_all(self, count: str): + """Measure cost of a cold instances() scan with every id present.""" + self._clear() + count = int(count) + _seed_entities(count) + Database.get_instance().clear_registry() + cost, _ = _measure(lambda: BenchZone.instances()) + ic.print(f"BENCH_RESULT:instances_all:{count}:{cost}") + return cost + + def instances_sparse(self, count: str): + """Measure cost of a cold instances() scan after deleting every other zone. + + With per-id probing every deleted id still costs a storage read; with a + range read deleted ids cost nothing. + """ + self._clear() + count = int(count) + _seed_entities(count) + for zone in BenchZone.load_some(1, max(count, 1)): + if int(zone._id) % 2 == 0: + zone.delete() + Database.get_instance().clear_registry() + cost, _ = _measure(lambda: BenchZone.instances()) + ic.print(f"BENCH_RESULT:instances_sparse:{count}:{cost}") + return cost + def deserialize_new_level1(self, count: str): """Measure cost of deserialize (new entity) with level=1 at given DB size.""" self._clear()