Files
cleveragents-core/benchmarks/project_repository_bench.py
freemo ca1c341b18
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / build (pull_request) Successful in 17s
CI / quality (pull_request) Successful in 19s
CI / security (pull_request) Successful in 28s
CI / typecheck (pull_request) Successful in 32s
CI / integration_tests (pull_request) Successful in 2m39s
CI / unit_tests (pull_request) Successful in 5m22s
CI / docker (pull_request) Successful in 38s
CI / benchmark-regression (pull_request) Successful in 17m47s
CI / coverage (pull_request) Successful in 19m6s
CI / lint (push) Successful in 14s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 20s
CI / security (push) Successful in 29s
CI / typecheck (push) Successful in 36s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 3m23s
CI / unit_tests (push) Successful in 9m12s
CI / docker (push) Successful in 16s
CI / benchmark-publish (push) Successful in 10m4s
CI / coverage (push) Successful in 19m27s
Tests: Significantly improved coverage of the unit tests
2026-02-22 00:43:08 -05:00

141 lines
4.9 KiB
Python

"""ASV benchmarks for project repository operations.
Measures:
- NamespacedProjectRepository create/get/list throughput
- ProjectResourceLinkRepository create_link/list_links throughput
"""
from __future__ import annotations
from datetime import UTC, datetime
from sqlalchemy import create_engine, event, text
from sqlalchemy.orm import sessionmaker
from cleveragents.domain.models.core.project import NamespacedProject
from cleveragents.infrastructure.database.models import (
Base,
ResourceModel,
ResourceTypeModel,
)
from cleveragents.infrastructure.database.repositories import (
NamespacedProjectRepository,
ProjectResourceLinkRepository,
)
def _now_iso() -> str:
return datetime.now(tz=UTC).isoformat()
def _set_sqlite_pragma(dbapi_conn: object, _connection_record: object) -> None:
cursor = dbapi_conn.cursor() # type: ignore[union-attr]
cursor.execute("PRAGMA foreign_keys = ON")
cursor.close()
class ProjectRepositoryCRUD:
"""Benchmark project repository CRUD operations."""
def setup(self) -> None:
self.engine = create_engine("sqlite:///:memory:")
event.listen(self.engine, "connect", _set_sqlite_pragma)
with self.engine.connect() as conn:
conn.execute(text("PRAGMA foreign_keys = ON"))
conn.commit()
Base.metadata.create_all(self.engine)
self.sf = sessionmaker(bind=self.engine)
def teardown(self) -> None:
self.engine.dispose()
def time_create_and_get_project(self) -> None:
repo = NamespacedProjectRepository(session_factory=self.sf)
session = self.sf()
project = NamespacedProject(name="bench-proj", namespace="bench")
repo.create(project)
session.commit()
repo.get("bench/bench-proj")
repo.delete("bench/bench-proj")
session.commit()
def time_list_50_projects(self) -> None:
repo = NamespacedProjectRepository(session_factory=self.sf)
session = self.sf()
for i in range(50):
repo.create(NamespacedProject(name=f"proj-{i}", namespace="bench"))
session.commit()
repo.list_projects(namespace="bench", limit=50)
for i in range(50):
repo.delete(f"bench/proj-{i}")
session.commit()
class LinkRepositoryCRUD:
"""Benchmark link repository operations."""
def setup(self) -> None:
self.engine = create_engine("sqlite:///:memory:")
event.listen(self.engine, "connect", _set_sqlite_pragma)
with self.engine.connect() as conn:
conn.execute(text("PRAGMA foreign_keys = ON"))
conn.commit()
Base.metadata.create_all(self.engine)
# Use a single session for all setup operations so FK
# relationships are visible within the same transaction.
self._setup_session = sessionmaker(bind=self.engine)()
self.sf = sessionmaker(bind=self.engine)
session = self._setup_session
# Resource type
rt = ResourceTypeModel()
rt.name = "bench/git-checkout" # type: ignore[assignment]
rt.namespace = "bench" # type: ignore[assignment]
rt.resource_kind = "physical" # type: ignore[assignment]
rt.user_addable = True # type: ignore[assignment]
rt.created_at = _now_iso() # type: ignore[assignment]
rt.updated_at = _now_iso() # type: ignore[assignment]
session.add(rt)
session.commit()
# Project — use the same session so the commit is on the same
# connection that created the resource type.
project_repo = NamespacedProjectRepository(
session_factory=lambda: session,
)
project_repo.create(NamespacedProject(name="link-bench", namespace="bench"))
session.commit()
# Resources
for i in range(30):
r = ResourceModel()
r.resource_id = str(i).zfill(26) # type: ignore[assignment]
r.type_name = "bench/git-checkout" # type: ignore[assignment]
r.resource_kind = "physical" # type: ignore[assignment]
r.created_at = _now_iso() # type: ignore[assignment]
r.updated_at = _now_iso() # type: ignore[assignment]
session.add(r)
session.commit()
def teardown(self) -> None:
self.engine.dispose()
def time_create_and_list_30_links(self) -> None:
# Use a scoped session so create_link and remove_link share state.
session = self.sf()
link_repo = ProjectResourceLinkRepository(session_factory=lambda: session)
link_ids: list[str] = []
for i in range(30):
link = link_repo.create_link(
project_name="bench/link-bench",
resource_id=str(i).zfill(26),
)
session.commit()
link_ids.append(str(link.link_id))
link_repo.list_links("bench/link-bench")
for lid in link_ids:
link_repo.remove_link(lid)
session.commit()
session.close()