"""Measure JSON validation, input normalization and strict XML construction separately. Run from the repository root with its Python environment; artifacts are ignored. """ import json from pathlib import Path from statistics import median from time import perf_counter_ns from app.main import ReactFlowProjectPayload, build_reactflow_system_xml from app.project_parameters import prepare_project def measure(fn, repeat=200): for _ in range(10): fn() samples = [] for _ in range(repeat): start = perf_counter_ns() fn() samples.append((perf_counter_ns() - start) / 1e6) samples.sort() return {"medianMs": median(samples), "p95Ms": samples[int(.95 * len(samples))], "samples": repeat} def main(): source = Path("tests/data/test-mql-8-corrected.json") raw = json.loads(source.read_text(encoding="utf-8")) current = ReactFlowProjectPayload.model_validate(raw) old = current.model_copy(deep=True) for node in old.nodes: node.data.modelVersion = "0.0.1" normalized, _ = prepare_project(current) metrics = { "source": str(source), "nodes": len(current.nodes), "parameters": sum(len(n.data.parameters) for n in current.nodes), "pydanticInput": measure(lambda: ReactFlowProjectPayload.model_validate(raw)), "prepareCurrent": measure(lambda: prepare_project(current)), "prepareAllOld": measure(lambda: prepare_project(old)), "strictXmlAfterPreparation": measure(lambda: build_reactflow_system_xml(normalized)), "notes": "prepare includes a defensive copy, parameter/expression/unit conversion, version comparison and simulation time normalization; not version checking alone.", } destination = Path("test/project-contract-20260912/backend-input-timing.json") destination.parent.mkdir(parents=True, exist_ok=True) destination.write_text(json.dumps(metrics, indent=2), encoding="utf-8") print(json.dumps(metrics, indent=2)) if __name__ == "__main__": main()