Files
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

68 lines
2.8 KiB
Python

"""Per-phase + per-SubApp-lifespan boot profiler (winv2).
Warm import is ~1.3s but backend-http-ready is ~9-10s, so the gap is the
lifespan startup (SubApp lifespans are entered sequentially in config/Apps.py
before uvicorn serves). This times each one to find what blocks the HTTP bind.
Run with the bundled interpreter from the resources dir, e.g.:
python-env/python.exe docs/perf/winv2/profile_boot.py
It spawns the same subprocesses a real boot does (9router etc.); the
AsyncExitStack unwinds at the end. Kill any straggler node/9router after.
"""
import asyncio
import os
import time
os.environ.setdefault("OPENSWARM_AUTH_TOKEN", "x")
_t0 = time.perf_counter()
import backend.main # noqa: F401 (builds main_app; full import tree)
_import_ms = (time.perf_counter() - _t0) * 1000
from contextlib import AsyncExitStack # noqa: E402
from backend.apps.health.health import health # noqa: E402
from backend.apps.agents.agents import agents # noqa: E402
from backend.apps.skills.skills import skills # noqa: E402
from backend.apps.tools_lib.tools_lib import tools_lib # noqa: E402
from backend.apps.modes.modes import modes # noqa: E402
from backend.apps.settings.settings import settings # noqa: E402
from backend.apps.mcp_registry.mcp_registry import mcp_registry # noqa: E402
from backend.apps.skill_registry.skill_registry import skill_registry # noqa: E402
from backend.apps.outputs.outputs import outputs # noqa: E402
from backend.apps.dashboards.dashboards import dashboards # noqa: E402
from backend.apps.swarm.swarm import swarm # noqa: E402
from backend.apps.service.service import service # noqa: E402
from backend.apps.subscription.router import subscription # noqa: E402
from backend.apps.auth.router import auth # noqa: E402
from backend.apps.web.web import web # noqa: E402
from backend.apps.agents.proxy.anthropic_proxy import anthropic_proxy # noqa: E402
SUBS = [health, agents, skills, tools_lib, modes, settings, mcp_registry,
skill_registry, outputs, dashboards, swarm, service, subscription,
auth, web, anthropic_proxy]
async def main():
print(f"{_import_ms:8.0f} ms import backend.main (full tree)")
print("-" * 48)
total = 0.0
async with AsyncExitStack() as stack:
for s in SUBS:
t = time.perf_counter()
try:
await asyncio.wait_for(stack.enter_async_context(s.lifespan()), timeout=60)
except Exception as e:
print(f" ERR lifespan {s.name}: {type(e).__name__}")
continue
dt = (time.perf_counter() - t) * 1000
total += dt
print(f"{dt:8.0f} ms lifespan {s.name}")
print("-" * 48)
print(f"{total:8.0f} ms all lifespans")
print(f"{_import_ms + total:8.0f} ms import + lifespans (approx backend-ready floor)")
if __name__ == "__main__":
asyncio.run(main())