95b6ed57c2
ISSUES CLOSED: #303
199 lines
6.2 KiB
Python
199 lines
6.2 KiB
Python
"""ASV benchmarks for diff review artifact building and serialization.
|
|
|
|
Measures the performance of:
|
|
- DiffBuilder.build() with various changeset sizes
|
|
- DiffSerializer.to_plain() / to_json() / to_rich()
|
|
- Rename detection with content hash matching
|
|
- ReviewArtifact and DiffEntry construction
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from cleveragents.domain.models.core.change import (
|
|
ChangeEntry,
|
|
ChangeOperation,
|
|
SpecChangeSet,
|
|
)
|
|
from cleveragents.domain.models.core.diff_review import (
|
|
DiffBuilder,
|
|
DiffEntry,
|
|
DiffSerializer,
|
|
ResourceDiffGroup,
|
|
ReviewArtifact,
|
|
)
|
|
except ModuleNotFoundError:
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
from cleveragents.domain.models.core.change import (
|
|
ChangeEntry,
|
|
ChangeOperation,
|
|
SpecChangeSet,
|
|
)
|
|
from cleveragents.domain.models.core.diff_review import (
|
|
DiffBuilder,
|
|
DiffEntry,
|
|
DiffSerializer,
|
|
ResourceDiffGroup,
|
|
ReviewArtifact,
|
|
)
|
|
|
|
|
|
def _make_changeset(
|
|
n_entries: int = 10,
|
|
) -> tuple[SpecChangeSet, dict[str, str], dict[str, str]]:
|
|
"""Create a changeset with n_entries MODIFY entries and content maps."""
|
|
cs = SpecChangeSet(plan_id="BENCH-PLAN")
|
|
before_map: dict[str, str] = {}
|
|
after_map: dict[str, str] = {}
|
|
for i in range(n_entries):
|
|
path = f"src/module_{i:04d}.py"
|
|
cs.add_change(
|
|
ChangeEntry(
|
|
plan_id="BENCH-PLAN",
|
|
resource_id=f"RES{i % 5:03d}",
|
|
tool_name="builtin/bench-tool",
|
|
operation=ChangeOperation.MODIFY,
|
|
path=path,
|
|
before_hash=f"before-{i}",
|
|
after_hash=f"after-{i}",
|
|
)
|
|
)
|
|
before_map[path] = f"# module {i}\nx = {i}\n"
|
|
after_map[path] = f"# module {i}\nx = {i + 1}\ny = {i}\n"
|
|
return cs, before_map, after_map
|
|
|
|
|
|
class DiffBuildSuite:
|
|
"""Benchmark DiffBuilder.build() with various changeset sizes."""
|
|
|
|
def setup(self) -> None:
|
|
"""Prepare changesets of different sizes."""
|
|
self.builder = DiffBuilder()
|
|
self.cs_small, self.bm_small, self.am_small = _make_changeset(5)
|
|
self.cs_medium, self.bm_medium, self.am_medium = _make_changeset(50)
|
|
self.cs_large, self.bm_large, self.am_large = _make_changeset(200)
|
|
|
|
def time_build_small(self) -> None:
|
|
"""Benchmark building artifact from 5-entry changeset."""
|
|
self.builder.build(
|
|
self.cs_small,
|
|
before_contents=self.bm_small,
|
|
after_contents=self.am_small,
|
|
)
|
|
|
|
def time_build_medium(self) -> None:
|
|
"""Benchmark building artifact from 50-entry changeset."""
|
|
self.builder.build(
|
|
self.cs_medium,
|
|
before_contents=self.bm_medium,
|
|
after_contents=self.am_medium,
|
|
)
|
|
|
|
def time_build_large(self) -> None:
|
|
"""Benchmark building artifact from 200-entry changeset."""
|
|
self.builder.build(
|
|
self.cs_large,
|
|
before_contents=self.bm_large,
|
|
after_contents=self.am_large,
|
|
)
|
|
|
|
|
|
class DiffSerializationSuite:
|
|
"""Benchmark DiffSerializer output formats."""
|
|
|
|
def setup(self) -> None:
|
|
"""Build an artifact to serialize."""
|
|
cs, bm, am = _make_changeset(20)
|
|
builder = DiffBuilder()
|
|
self.artifact = builder.build(cs, before_contents=bm, after_contents=am)
|
|
|
|
def time_to_plain(self) -> None:
|
|
"""Benchmark plain text serialization."""
|
|
DiffSerializer.to_plain(self.artifact)
|
|
|
|
def time_to_json(self) -> None:
|
|
"""Benchmark JSON serialization."""
|
|
DiffSerializer.to_json(self.artifact)
|
|
|
|
def time_to_rich(self) -> None:
|
|
"""Benchmark rich text serialization."""
|
|
DiffSerializer.to_rich(self.artifact)
|
|
|
|
|
|
class DiffRenameSuite:
|
|
"""Benchmark rename detection with content hash matching."""
|
|
|
|
def setup(self) -> None:
|
|
"""Prepare a changeset with rename pairs."""
|
|
self.builder = DiffBuilder()
|
|
self.cs = SpecChangeSet(plan_id="BENCH-PLAN")
|
|
for i in range(20):
|
|
self.cs.add_change(
|
|
ChangeEntry(
|
|
plan_id="BENCH-PLAN",
|
|
resource_id="RES001",
|
|
tool_name="builtin/bench-tool",
|
|
operation=ChangeOperation.DELETE,
|
|
path=f"old/module_{i:04d}.py",
|
|
before_hash=f"hash-{i}",
|
|
)
|
|
)
|
|
self.cs.add_change(
|
|
ChangeEntry(
|
|
plan_id="BENCH-PLAN",
|
|
resource_id="RES001",
|
|
tool_name="builtin/bench-tool",
|
|
operation=ChangeOperation.CREATE,
|
|
path=f"new/module_{i:04d}.py",
|
|
after_hash=f"hash-{i}",
|
|
)
|
|
)
|
|
|
|
def time_rename_detection(self) -> None:
|
|
"""Benchmark rename detection for 20 pairs."""
|
|
self.builder.build(self.cs)
|
|
|
|
|
|
class DiffModelSuite:
|
|
"""Benchmark DiffEntry and ReviewArtifact construction."""
|
|
|
|
def time_diff_entry_construction(self) -> None:
|
|
"""Benchmark creating a DiffEntry."""
|
|
DiffEntry(
|
|
resource_id="RES001",
|
|
resource_name="test-resource",
|
|
path="src/main.py",
|
|
change_type="modify",
|
|
diff_text="--- a/src/main.py\n+++ b/src/main.py\n",
|
|
)
|
|
|
|
def time_resource_diff_group_construction(self) -> None:
|
|
"""Benchmark creating a ResourceDiffGroup."""
|
|
ResourceDiffGroup(
|
|
resource_id="RES001",
|
|
resource_name="test-resource",
|
|
entries=[
|
|
DiffEntry(
|
|
resource_id="RES001",
|
|
path="a.py",
|
|
change_type="create",
|
|
),
|
|
DiffEntry(
|
|
resource_id="RES001",
|
|
path="b.py",
|
|
change_type="modify",
|
|
),
|
|
],
|
|
)
|
|
|
|
def time_review_artifact_construction(self) -> None:
|
|
"""Benchmark creating a ReviewArtifact."""
|
|
ReviewArtifact(
|
|
plan_id="PLAN001",
|
|
changeset_id="CS001",
|
|
total_changes=5,
|
|
)
|