"""ASV benchmarks for plan diff rendering overhead. Measures the performance of: - Diff rendering in rich format - Diff rendering in plain format - Diff rendering in JSON format - Artifacts summary building - Empty changeset guard check """ from __future__ import annotations import importlib import sys from pathlib import Path # Ensure the local *source* tree is importable even when ASV has an # older build of the package installed. _SRC = str(Path(__file__).resolve().parents[1] / "src") if _SRC not in sys.path: sys.path.insert(0, _SRC) import cleveragents # noqa: E402 importlib.reload(cleveragents) from cleveragents.application.services.plan_apply_service import ( # noqa: E402 PlanApplyService, _render_diff_json, _render_diff_plain, _render_diff_rich, ) from cleveragents.application.services.plan_lifecycle_service import ( # noqa: E402 PlanLifecycleService, ) from cleveragents.config.settings import Settings # noqa: E402 from cleveragents.domain.models.core.change import ( # noqa: E402 ChangeEntry, ChangeOperation, InMemoryChangeSetStore, SpecChangeSet, ) from cleveragents.domain.models.core.plan import PlanPhase # noqa: E402 def _build_changeset(plan_id: str, n_entries: int = 10) -> SpecChangeSet: """Build a SpecChangeSet with *n_entries* for benchmarking.""" entries = [] ops = [ChangeOperation.CREATE, ChangeOperation.MODIFY, ChangeOperation.DELETE] for i in range(n_entries): entries.append( ChangeEntry( plan_id=plan_id, resource_id=f"res-{i:04d}", tool_name="file-write", operation=ops[i % len(ops)], path=f"src/module_{i:04d}.py", before_hash=f"before{i:08x}" if i % 3 != 0 else None, after_hash=f"after{i:08x}" if i % 3 != 2 else None, ) ) return SpecChangeSet( changeset_id="bench-cs-001", plan_id=plan_id, entries=entries, ) def _create_plan_and_service() -> tuple[str, PlanApplyService, InMemoryChangeSetStore]: """Create a lifecycle service, plan, and apply service.""" settings = Settings() lifecycle = PlanLifecycleService(settings=settings) store = InMemoryChangeSetStore() apply_svc = PlanApplyService(lifecycle_service=lifecycle, changeset_store=store) lifecycle.create_action( name="local/bench-diff", description="Benchmark diff", definition_of_done="Benchmarks pass", strategy_actor="local/planner", execution_actor="local/executor", ) plan = lifecycle.use_action(action_name="local/bench-diff") plan_id = plan.identity.plan_id lifecycle.start_strategize(plan_id) lifecycle.complete_strategize(plan_id) plan = lifecycle.get_plan(plan_id) if plan.phase == PlanPhase.STRATEGIZE: lifecycle.execute_plan(plan_id) plan = lifecycle.get_plan(plan_id) if plan.phase == PlanPhase.EXECUTE: lifecycle.start_execute(plan_id) lifecycle.complete_execute(plan_id) cs = _build_changeset(plan_id, 20) store._store[cs.changeset_id] = cs plan = lifecycle.get_plan(plan_id) plan.changeset_id = cs.changeset_id plan.sandbox_refs = ["sandbox-bench-001"] lifecycle._commit_plan(plan) return plan_id, apply_svc, store class DiffRenderingSuite: """Benchmark suite for diff rendering in various formats.""" def setup(self) -> None: self.plan_id, self.apply_svc, self.store = _create_plan_and_service() def time_diff_rich(self) -> None: self.apply_svc.diff(self.plan_id, fmt="rich") def time_diff_plain(self) -> None: self.apply_svc.diff(self.plan_id, fmt="plain") def time_diff_json(self) -> None: self.apply_svc.diff(self.plan_id, fmt="json") def time_diff_yaml(self) -> None: self.apply_svc.diff(self.plan_id, fmt="yaml") class ArtifactsSuite: """Benchmark suite for artifacts rendering.""" def setup(self) -> None: self.plan_id, self.apply_svc, self.store = _create_plan_and_service() def time_artifacts_json(self) -> None: self.apply_svc.artifacts(self.plan_id, fmt="json") def time_artifacts_plain(self) -> None: self.apply_svc.artifacts(self.plan_id, fmt="plain") class GuardSuite: """Benchmark suite for empty changeset guard.""" def setup(self) -> None: self.plan_id, self.apply_svc, self.store = _create_plan_and_service() def time_guard_non_empty(self) -> None: self.apply_svc.guard_empty_changeset(self.plan_id) class HelperFunctionsSuite: """Benchmark suite for low-level rendering helpers.""" def setup(self) -> None: self.changeset = _build_changeset("bench-plan-001", 50) def time_render_diff_plain(self) -> None: _render_diff_plain(self.changeset) def time_render_diff_rich(self) -> None: _render_diff_rich(self.changeset) def time_render_diff_json(self) -> None: _render_diff_json(self.changeset)