Files
cleveragents-core/benchmarks/plan_phase_migration_bench.py
T
CoreRasurae 946933139c
CI / lint (pull_request) Successful in 18s
CI / typecheck (pull_request) Successful in 34s
CI / security (pull_request) Successful in 24s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 4m56s
CI / build (pull_request) Successful in 15s
CI / unit_tests (pull_request) Successful in 14m48s
CI / docker (pull_request) Successful in 9s
CI / coverage (pull_request) Has been cancelled
fix(bench): Benchmark tests database issues on concurrent test calls
2026-02-16 23:13:08 +00:00

173 lines
5.4 KiB
Python

"""ASV benchmarks for plan phase rebaseline migration (a5_005).
Measures:
- Schema creation time with rebaselined constraints
- Plan insert throughput with Action phase
- Plan insert throughput with Apply terminal states
"""
from __future__ import annotations
import threading
from datetime import UTC, datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from cleveragents.infrastructure.database.models import (
Base,
LifecycleActionModel,
LifecyclePlanModel,
)
# Thread-safe counter so repeated ASV iterations never collide on IDs.
_iter_lock = threading.Lock()
_iter_counter = 0
def _next_iter() -> int:
"""Return a monotonically increasing iteration number."""
global _iter_counter
with _iter_lock:
_iter_counter += 1
return _iter_counter
def _now_iso() -> str:
return datetime.now(tz=UTC).isoformat()
def _make_ulid(n: int) -> str:
return str(n).zfill(26)
class SchemaCreationWithRebaseline:
"""Benchmark schema creation including rebaselined v3_plans constraints."""
def time_create_all_tables(self) -> None:
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
engine.dispose()
class PlanInsertActionPhase:
"""Benchmark inserting plans with phase='action' (new phase)."""
def setup(self) -> None:
self.engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(self.engine)
self.session_factory = sessionmaker(bind=self.engine)
# Create parent action
session = self.session_factory()
action = LifecycleActionModel()
action.namespaced_name = "bench/phase-action"
action.namespace = "bench"
action.name = "phase-action"
action.description = "Benchmark action"
action.definition_of_done = "Done"
action.strategy_actor = "bench/s"
action.execution_actor = "bench/e"
action.state = "available"
action.tags_json = "[]"
action.created_at = _now_iso()
action.updated_at = _now_iso()
session.add(action)
session.commit()
session.close()
def teardown(self) -> None:
self.engine.dispose()
def time_insert_100_action_phase_plans(self) -> None:
it = _next_iter()
base = it * 10000
session = self.session_factory()
now = _now_iso()
for i in range(100):
plan = LifecyclePlanModel()
plan.plan_id = _make_ulid(base + i)
plan.action_name = "bench/phase-action"
plan.namespaced_name = f"bench/plan-{it}-{i}"
plan.namespace = "bench"
plan.phase = "action"
plan.processing_state = "queued"
plan.description = f"Benchmark plan {i}"
plan.tags_json = "[]"
plan.created_at = now
plan.updated_at = now
session.add(plan)
session.commit()
session.close()
class PlanInsertApplyTerminalStates:
"""Benchmark inserting plans with Apply terminal states."""
def setup(self) -> None:
self.engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(self.engine)
self.session_factory = sessionmaker(bind=self.engine)
session = self.session_factory()
action = LifecycleActionModel()
action.namespaced_name = "bench/terminal-action"
action.namespace = "bench"
action.name = "terminal-action"
action.description = "Benchmark terminal action"
action.definition_of_done = "Done"
action.strategy_actor = "bench/s"
action.execution_actor = "bench/e"
action.state = "available"
action.tags_json = "[]"
action.created_at = _now_iso()
action.updated_at = _now_iso()
session.add(action)
session.commit()
session.close()
def teardown(self) -> None:
self.engine.dispose()
def time_insert_50_applied_plans(self) -> None:
it = _next_iter()
base = it * 10000
session = self.session_factory()
now = _now_iso()
for i in range(50):
plan = LifecyclePlanModel()
plan.plan_id = _make_ulid(base + i)
plan.action_name = "bench/terminal-action"
plan.namespaced_name = f"bench/applied-{it}-{i}"
plan.namespace = "bench"
plan.phase = "apply"
plan.processing_state = "applied"
plan.description = f"Applied plan {i}"
plan.tags_json = "[]"
plan.created_at = now
plan.updated_at = now
session.add(plan)
session.commit()
session.close()
def time_insert_50_constrained_plans(self) -> None:
it = _next_iter()
base = it * 10000
session = self.session_factory()
now = _now_iso()
for i in range(50):
plan = LifecyclePlanModel()
plan.plan_id = _make_ulid(base + i)
plan.action_name = "bench/terminal-action"
plan.namespaced_name = f"bench/constrained-{it}-{i}"
plan.namespace = "bench"
plan.phase = "apply"
plan.processing_state = "constrained"
plan.description = f"Constrained plan {i}"
plan.tags_json = "[]"
plan.created_at = now
plan.updated_at = now
session.add(plan)
session.commit()
session.close()