Files
cleveragents-core/benchmarks/bench_sandbox_strategy.py
T
freemo c65e8a5285
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 16s
CI / lint (pull_request) Successful in 17s
CI / quality (pull_request) Successful in 29s
CI / typecheck (pull_request) Successful in 59s
CI / security (pull_request) Successful in 59s
CI / unit_tests (pull_request) Successful in 3m9s
CI / integration_tests (pull_request) Successful in 3m34s
CI / e2e_tests (pull_request) Successful in 3m54s
CI / docker (pull_request) Successful in 55s
CI / coverage (pull_request) Successful in 6m1s
CI / build (push) Successful in 15s
CI / lint (push) Successful in 16s
CI / quality (push) Successful in 27s
CI / typecheck (push) Successful in 38s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 48s
CI / unit_tests (push) Successful in 3m14s
CI / integration_tests (push) Successful in 3m30s
CI / docker (push) Successful in 56s
CI / e2e_tests (push) Successful in 4m43s
CI / coverage (push) Successful in 6m1s
CI / benchmark-publish (push) Successful in 19m50s
CI / benchmark-regression (pull_request) Successful in 37m17s
feat(resource): add cloud infrastructure resources
Implement cloud resource types (aws, gcp, azure) with credential
fields, region/tenant metadata, and stubbed sandbox strategies.
Credential resolution uses environment variables and profile names
with no secrets logged.

Key changes:
- Add CloudResourceHandler with aws/gcp/azure type definitions
- Add credential resolution from env vars and profile names
- Add stubbed sandbox strategies (validate config, raise NotImplementedError)
- Register cloud types in bootstrap_builtin_types
- Credential masking via existing redaction patterns
- Add Behave BDD tests, Robot integration tests, ASV benchmarks

ISSUES CLOSED: #343
2026-03-17 13:14:37 -04:00

245 lines
6.9 KiB
Python

"""ASV benchmarks for custom sandbox strategy registration.
Measures the performance of:
- SandboxRef creation
- DiffView / DiffEntry model creation
- SandboxStrategyRegistry registration and lookup
- BuiltInSandboxStrategyAdapter create/write/read cycle
- Protocol runtime checking via isinstance
"""
from __future__ import annotations
import importlib
import os
import sys
import tempfile
from datetime import datetime
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)
# Force-reload so ASV picks up the source tree version.
import cleveragents # noqa: E402
importlib.reload(cleveragents)
from cleveragents.domain.models.core.resource import ( # noqa: E402
PhysVirt,
Resource,
ResourceCapabilities,
)
from cleveragents.domain.models.core.resource import ( # noqa: E402
SandboxStrategy as SandboxStrategyEnum,
)
from cleveragents.domain.models.core.sandbox_strategy import ( # noqa: E402
DiffEntry,
DiffView,
SandboxRef,
SandboxStrategyProtocol,
)
from cleveragents.infrastructure.sandbox.strategy_adapter import ( # noqa: E402
BuiltInSandboxStrategyAdapter,
)
from cleveragents.infrastructure.sandbox.strategy_registry import ( # noqa: E402
SandboxStrategyRegistry,
)
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
_COUNTER = 0
def _ulid(name: str) -> str:
global _COUNTER
_COUNTER += 1
base = abs(hash(name)) % (10**20)
raw = f"{_COUNTER:06d}{base:020d}"
charset = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
result = ""
for ch in raw:
result += charset[int(ch)]
return (result + "0" * 26)[:26]
class _MockStrategy:
"""Minimal strategy satisfying the Protocol for benchmarking."""
def create(self, plan_id, resource):
return None
def read(self, ref, path):
return b""
def write(self, ref, path, content):
return None
def diff(self, ref):
return None
def commit(self, ref):
pass
def rollback(self, ref):
pass
def checkpoint(self, ref, checkpoint_id):
pass
def restore_checkpoint(self, ref, checkpoint_id):
pass
def cleanup(self, ref):
pass
# ---------------------------------------------------------------------------
# SandboxRef benchmarks
# ---------------------------------------------------------------------------
class TimeSandboxRef:
"""Benchmark SandboxRef creation."""
def time_create_ref(self) -> None:
SandboxRef(
sandbox_id="bench-ref",
plan_id="bench-plan",
resource_id="bench-res",
created_at=datetime.now(),
)
def time_create_ref_with_metadata(self) -> None:
SandboxRef(
sandbox_id="bench-ref-meta",
plan_id="bench-plan",
resource_id="bench-res",
created_at=datetime.now(),
metadata={"key": "value", "num": 42},
)
# ---------------------------------------------------------------------------
# DiffEntry / DiffView benchmarks
# ---------------------------------------------------------------------------
class TimeDiffModels:
"""Benchmark DiffEntry and DiffView creation."""
def time_create_diff_entry(self) -> None:
DiffEntry(path="bench.txt", operation="modified")
def time_create_diff_entry_with_content(self) -> None:
DiffEntry(
path="bench.txt",
operation="modified",
before=b"old",
after=b"new",
)
def time_create_diff_view_10_entries(self) -> None:
entries = [
DiffEntry(path=f"file{i}.txt", operation="modified") for i in range(10)
]
DiffView(sandbox_id="bench-dv", entries=entries)
# ---------------------------------------------------------------------------
# Protocol checking benchmarks
# ---------------------------------------------------------------------------
class TimeProtocolCheck:
"""Benchmark SandboxStrategyProtocol isinstance checks."""
def setup(self) -> None:
self.good = _MockStrategy()
def time_isinstance_check_pass(self) -> None:
isinstance(self.good, SandboxStrategyProtocol)
def time_isinstance_check_fail(self) -> None:
isinstance("not a strategy", SandboxStrategyProtocol)
# ---------------------------------------------------------------------------
# SandboxStrategyRegistry benchmarks
# ---------------------------------------------------------------------------
class TimeStrategyRegistry:
"""Benchmark registry operations."""
def setup(self) -> None:
self.registry = SandboxStrategyRegistry(
allowed_prefixes=("cleveragents.",),
)
self.registry.register(
"bench_adapter",
"cleveragents.infrastructure.sandbox.strategy_adapter",
"BuiltInSandboxStrategyAdapter",
)
def time_lookup_hit(self) -> None:
self.registry.get("bench_adapter")
def time_lookup_miss(self) -> None:
self.registry.get("nonexistent")
def time_has_check(self) -> None:
self.registry.has("bench_adapter")
def time_list_strategies(self) -> None:
self.registry.list_strategies()
# ---------------------------------------------------------------------------
# BuiltInSandboxStrategyAdapter benchmarks
# ---------------------------------------------------------------------------
class TimeAdapterLifecycle:
"""Benchmark adapter create/write/read cycle."""
def setup(self) -> None:
self.tmpdir = tempfile.mkdtemp(prefix="ca-bench-adapter-")
with open(os.path.join(self.tmpdir, "seed.txt"), "w") as f:
f.write("seed")
self.adapter = BuiltInSandboxStrategyAdapter(strategy_name="copy_on_write")
self.resource = Resource(
resource_id=_ulid("bench-adapter"),
name="bench-adapter",
resource_type_name="fs-directory",
classification=PhysVirt.PHYSICAL,
sandbox_strategy=SandboxStrategyEnum.COPY_ON_WRITE,
location=self.tmpdir,
capabilities=ResourceCapabilities(
readable=True,
writable=True,
sandboxable=True,
checkpointable=False,
),
)
def time_create_and_cleanup(self) -> None:
ref = self.adapter.create("bench-plan", self.resource)
self.adapter.cleanup(ref)
def time_write_read_cycle(self) -> None:
ref = self.adapter.create("bench-plan-wr", self.resource)
self.adapter.write(ref, "bench.txt", b"bench content")
self.adapter.read(ref, "bench.txt")
self.adapter.cleanup(ref)
def teardown(self) -> None:
import shutil
shutil.rmtree(self.tmpdir, ignore_errors=True)