"""ASV benchmarks for ChangeSet capture overhead. Measures the cost of creating entries, recording to a store, computing summaries, and wrapping file tools with capture. """ import hashlib import tempfile from typing import ClassVar from cleveragents.domain.models.core.change import ( ChangeEntry, ChangeOperation, InMemoryChangeSetStore, SpecChangeSet, ) from cleveragents.tool.builtins.changeset import ( ChangeSetCapture, ) from cleveragents.tool.builtins.file_tools import ( FILE_WRITE_SPEC, ) class ChangeEntryCreation: """Benchmark ChangeEntry instantiation.""" def setup(self): self.kwargs = { "plan_id": "plan-bench", "resource_id": "res-bench", "tool_name": "builtin/file-write", "operation": ChangeOperation.CREATE, "path": "bench/file.py", "after_hash": hashlib.sha256(b"content").hexdigest(), } def time_create_entry(self): ChangeEntry(**self.kwargs) class SpecChangeSetSummary: """Benchmark SpecChangeSet summary computation.""" params: ClassVar[list[int]] = [10, 100, 1000] param_names: ClassVar[list[str]] = ["num_entries"] def setup(self, num_entries): entries = [] ops = list(ChangeOperation) for i in range(num_entries): entries.append( ChangeEntry( plan_id="plan-bench", resource_id=f"res-{i % 5}", tool_name="builtin/file-write", operation=ops[i % len(ops)], path=f"file_{i}.py", ) ) self.cs = SpecChangeSet(plan_id="plan-bench", entries=entries) def time_summary(self, num_entries): self.cs.summary() def time_paths_changed(self, num_entries): _ = self.cs.paths_changed def time_resources_involved(self, num_entries): _ = self.cs.resources_involved class InMemoryStoreRecording: """Benchmark InMemoryChangeSetStore operations.""" params: ClassVar[list[int]] = [10, 100, 1000] param_names: ClassVar[list[str]] = ["num_entries"] def setup(self, num_entries): self.store = InMemoryChangeSetStore() self.cs_id = self.store.start("plan-bench") self.entries = [ ChangeEntry( plan_id="plan-bench", resource_id="res-1", tool_name="builtin/file-write", operation=ChangeOperation.CREATE, path=f"file_{i}.py", ) for i in range(num_entries) ] def time_record_entries(self, num_entries): store = InMemoryChangeSetStore() cs_id = store.start("plan-bench") for entry in self.entries: store.record(cs_id, entry) def time_summarize(self, num_entries): self.store.summarize(self.cs_id) class CaptureWrapOverhead: """Benchmark wrapping a tool with capture.""" def setup(self): self.tmpdir = tempfile.mkdtemp() self.capture = ChangeSetCapture( plan_id="plan-bench", resource_id="res-bench", sandbox_root=self.tmpdir, ) def time_wrap_tool(self): self.capture.wrap_tool(FILE_WRITE_SPEC) def time_wrapped_execution(self): wrapped = self.capture.wrap_tool(FILE_WRITE_SPEC) wrapped.handler( { "path": "bench_out.txt", "content": "benchmark", "sandbox_root": self.tmpdir, } ) self.capture.clear()