Files
openswarm/docs/perf/winv2/measure_vite.py
T
Eric 24a767eec9 [eric] perf: winv2 windows startup + app builder profiling, tracking doc, graphs
- warm boot floor 8256ms -> 857ms; app builder download + create breakdown measured

- harnesses, csv, dependency-free svg graphs, per-step savings table, #9 plan
2026-06-16 21:58:39 -07:00

71 lines
2.5 KiB
Python

"""Vite-bind-only measurement (winv2 Task #3, part 2).
Split out from measure_appbuilder.py because Python's tarfile gzip of a full
node_modules is pathologically slow and was eating the time budget before the
vite phases ran. This does ONLY the two vite binds (cold vite cache = first app
ever; warm shared cache = subsequent apps) and APPENDS to appbuilder_breakdown.csv.
No tar, no npm. Run unbuffered.
"""
import asyncio
import os
import shutil
import tempfile
import time
from backend.apps.outputs import view_builder_templates as vt
from backend.apps.outputs.runtime_proc import _find_free_port
from backend.apps.outputs.runtime import AppRuntime
HERE = os.path.dirname(os.path.abspath(__file__))
CSV = os.path.join(HERE, "appbuilder_breakdown.csv")
TMP = tempfile.mkdtemp(prefix="ab-vite-")
VITE_DEADLINE = 100
def record(name, ms, note=""):
print(f"{ms:8d} ms {name}" + (f" ({note})" if note else ""), flush=True)
with open(CSV, "a", encoding="utf-8") as f:
f.write(f'"{name}",{ms},"{note}"\n')
f.flush()
async def bind_once(label, vite_cache_dir):
ws = os.path.join(TMP, f"ws-{label.replace(' ', '_')}")
vt.seed_webapp_template_workspace(ws, _find_free_port())
if not os.path.exists(os.path.join(ws, "frontend", "node_modules")):
record(f"vite bind ({label})", -1, "no node_modules linked")
return
if vite_cache_dir:
os.environ["OPENSWARM_VITE_CACHE_DIR"] = vite_cache_dir
else:
os.environ.pop("OPENSWARM_VITE_CACHE_DIR", None)
rt = AppRuntime(f"ws-{label}", ws)
t = time.perf_counter()
await rt.start()
deadline = time.perf_counter() + VITE_DEADLINE
while rt.frontend_url is None and time.perf_counter() < deadline:
await asyncio.sleep(0.1)
bound = rt.frontend_url is not None
ms = round((time.perf_counter() - t) * 1000) if bound else -1
try:
await rt.stop()
except Exception:
pass
record(f"vite bind ({label})", ms, "bound" if bound else f"TIMEOUT {VITE_DEADLINE}s")
async def main():
print(f"temp: {TMP}", flush=True)
for label, cache in (("cold vite cache", os.path.join(TMP, "vite_cold")),
("warm shared cache", None)):
try:
await bind_once(label, cache)
except Exception as e:
record(f"vite bind ({label})", -1, f"ERR {type(e).__name__}: {e}")
print("done", flush=True)
shutil.rmtree(TMP, ignore_errors=True)
if __name__ == "__main__":
asyncio.run(main())