"""ASV benchmarks for Skill Registry persistence operations. Measures the performance of: - SkillModel.from_domain() construction - SkillModel.to_domain() reconstruction - SkillRepository CRUD operations (in-memory SQLite) - SkillRegistryService list operations """ from __future__ import annotations import sys import uuid from pathlib import Path try: from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from cleveragents.domain.models.core.skill import Skill from cleveragents.infrastructure.database.models import Base, SkillModel from cleveragents.infrastructure.database.repositories import ( SkillRepository, ) except ModuleNotFoundError: sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from cleveragents.domain.models.core.skill import Skill from cleveragents.infrastructure.database.models import Base, SkillModel from cleveragents.infrastructure.database.repositories import ( SkillRepository, ) def _make_skill(name: str = "bench/skill-test") -> Skill: """Create a minimal Skill domain object for benchmarks.""" return Skill( name=name, description=f"Benchmark skill {name}", tool_refs=["local/tool-a", "local/tool-b"], ) class SkillModelConstruction: """Benchmark SkillModel.from_domain() construction.""" def setup(self) -> None: self.skill = _make_skill() def time_from_domain(self) -> None: SkillModel.from_domain(self.skill) class SkillModelReconstruction: """Benchmark SkillModel.to_domain() reconstruction.""" def setup(self) -> None: self.model = SkillModel.from_domain(_make_skill()) def time_to_domain(self) -> None: self.model.to_domain() class SkillRepositoryCRUD: """Benchmark SkillRepository CRUD with in-memory SQLite.""" timeout = 60.0 def setup(self) -> None: self.engine = create_engine("sqlite:///:memory:", echo=False) Base.metadata.create_all(self.engine) self.factory = sessionmaker(bind=self.engine) self.repo = SkillRepository(session_factory=self.factory) def teardown(self) -> None: self.engine.dispose() def time_create_skill(self) -> None: skill = _make_skill(f"bench/{uuid.uuid4().hex[:8]}") self.repo.create(skill) # Commit via the same session-factory the repo uses internally session = self.factory() try: session.commit() finally: session.close() def time_get_skill(self) -> None: self.repo.get_by_name("bench/nonexistent") def time_list_all(self) -> None: self.repo.list_all() def time_list_namespace(self) -> None: self.repo.list_all(namespace="bench") class SkillRegistryListPerformance: """Benchmark listing performance with many skills.""" timeout = 120.0 def setup(self) -> None: self.engine = create_engine("sqlite:///:memory:", echo=False) Base.metadata.create_all(self.engine) self.factory = sessionmaker(bind=self.engine) self.repo = SkillRepository(session_factory=self.factory) # Insert 100 skills and commit via the same session-factory for i in range(100): skill = _make_skill(f"bench/skill-{i:04d}") self.repo.create(skill) session = self.factory() try: session.commit() finally: session.close() def teardown(self) -> None: self.engine.dispose() def time_list_100_skills(self) -> None: self.repo.list_all() def time_list_100_skills_filtered(self) -> None: self.repo.list_all(namespace="bench")