From f5dccb5e1c312121f1af63780162f593d9363b98 Mon Sep 17 00:00:00 2001 From: Andraxion Date: Wed, 29 Jul 2026 13:00:35 -0400 Subject: [PATCH] Gate production projection worker memory --- tools/milestone3_benchmark.py | 81 ++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 15 deletions(-) diff --git a/tools/milestone3_benchmark.py b/tools/milestone3_benchmark.py index f67688c..6da6fe9 100644 --- a/tools/milestone3_benchmark.py +++ b/tools/milestone3_benchmark.py @@ -416,11 +416,51 @@ def _prepared_summary(value: object) -> Mapping[str, object]: } +def _prepared_child_peak(prepared: PreparedRender) -> int: + receipt = prepared.projection_receipt + if not isinstance(receipt, Mapping): + raise RuntimeError("Production detached render did not return a projection receipt") + peak = receipt.get("peak_memory_bytes") + if type(peak) is not int or peak < 1: + raise RuntimeError("Production detached render did not report valid child peak memory") + if peak > MAX_CHILD_PEAK_BYTES: + raise RuntimeError( + f"Production detached worker peak memory {peak} exceeds {MAX_CHILD_PEAK_BYTES} bytes" + ) + return peak + + def _prepared_response_size(value: object) -> int: prepared = cast(PreparedRender, value) return _compact_size(prepared.projection_receipt) +def _prepared_measurement( + operation: Callable[[], PreparedRender], + *, + samples: int, + p95_limit_ms: float, +) -> tuple[dict[str, object], PreparedRender]: + child_peaks: list[int] = [] + + def observed_operation() -> PreparedRender: + prepared = operation() + child_peaks.append(_prepared_child_peak(prepared)) + return prepared + + measurement, value = _measure( + observed_operation, + samples=samples, + p95_limit_ms=p95_limit_ms, + response_limit_bytes=MAX_RECEIPT_BYTES, + summary=_prepared_summary, + response_size=_prepared_response_size, + ) + measurement["maximum_child_peak_bytes"] = max(child_peaks) + measurement["child_peak_limit_bytes"] = MAX_CHILD_PEAK_BYTES + return measurement, cast(PreparedRender, value) + + def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: project = Project.open(root) snapshot = project.load() @@ -600,7 +640,7 @@ def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: manual_view = render_config.views[0] template_bytes = manual_view.template_path.read_bytes() production_renderer = GenericHtmlRenderer() - operations["manual_incremental_cold"], cold_prepared = _measure( + operations["manual_incremental_cold"], cold_prepared = _prepared_measurement( lambda: production_renderer.prepare( snapshot, manual_view, @@ -609,11 +649,8 @@ def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: ), samples=1, p95_limit_ms=20_000, - response_limit_bytes=MAX_RECEIPT_BYTES, - summary=_prepared_summary, - response_size=_prepared_response_size, ) - operations["manual_incremental_warm"], warm_prepared = _measure( + operations["manual_incremental_warm"], warm_prepared = _prepared_measurement( lambda: production_renderer.prepare( snapshot, manual_view, @@ -622,11 +659,8 @@ def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: ), samples=samples, p95_limit_ms=20_000, - response_limit_bytes=MAX_RECEIPT_BYTES, - summary=_prepared_summary, - response_size=_prepared_response_size, ) - operations["manual_forced_full"], forced_prepared = _measure( + operations["manual_forced_full"], forced_prepared = _prepared_measurement( lambda: GenericHtmlRenderer(incremental=False).prepare( snapshot, manual_view, @@ -635,13 +669,8 @@ def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: ), samples=samples, p95_limit_ms=20_000, - response_limit_bytes=MAX_RECEIPT_BYTES, - summary=_prepared_summary, - response_size=_prepared_response_size, - ) - production_values = tuple( - cast(PreparedRender, value) for value in (cold_prepared, warm_prepared, forced_prepared) ) + production_values = (cold_prepared, warm_prepared, forced_prepared) if len({value.output for value in production_values}) != 1: raise RuntimeError("Production cold, warm, and forced-full manual output differs") @@ -688,6 +717,7 @@ def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: ), } variant_equivalence: dict[str, bool] = {} + variant_child_peaks: list[int] = [] for name, variant in variants.items(): incremental = GenericHtmlRenderer().prepare( variant, @@ -701,6 +731,12 @@ def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: template_bytes, changeset_hash=None, ) + variant_child_peaks.extend( + ( + _prepared_child_peak(incremental), + _prepared_child_peak(full), + ) + ) variant_equivalence[name] = incremental.output == full.output if not all(variant_equivalence.values()): raise RuntimeError("Production incremental mutation output differs from forced full") @@ -776,6 +812,21 @@ def _benchmark(root: Path, node_count: int, samples: int) -> dict[str, object]: "memory": { "process_peak_rss_kib": int(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss), "manual_worker_peak_bytes": manual_worker_peak, + "manual_production_worker_peak_bytes": max( + cast( + int, + operations["manual_incremental_cold"]["maximum_child_peak_bytes"], + ), + cast( + int, + operations["manual_incremental_warm"]["maximum_child_peak_bytes"], + ), + cast( + int, + operations["manual_forced_full"]["maximum_child_peak_bytes"], + ), + *variant_child_peaks, + ), "portable_graph_worker_peak_bytes": graph_worker_peak, }, }