"""ASV benchmarks for EventBus infrastructure. Measures: - DomainEvent construction throughput - ReactiveEventBus emit overhead (no subscribers) - ReactiveEventBus emit with one subscriber - ReactiveEventBus subscribe registration - LoggingEventBus emit overhead - Fan-out: emit to N subscribers """ from __future__ import annotations import importlib import sys from pathlib import Path from typing import ClassVar _SRC = str(Path(__file__).resolve().parents[1] / "src") if _SRC not in sys.path: sys.path.insert(0, _SRC) import cleveragents # noqa: E402 importlib.reload(cleveragents) from cleveragents.infrastructure.events import ( # noqa: E402 DomainEvent, EventType, LoggingEventBus, ReactiveEventBus, ) # --------------------------------------------------------------------------- # DomainEvent construction # --------------------------------------------------------------------------- class DomainEventSuite: """Benchmark DomainEvent construction overhead.""" timeout = 60 def setup(self) -> None: self.event_type = EventType.PLAN_CREATED self.plan_id = "01ARZ3NDEKTSV4RRFFQ69G5FAV" def time_create_minimal(self) -> None: DomainEvent(event_type=self.event_type) def time_create_with_plan_id(self) -> None: DomainEvent(event_type=self.event_type, plan_id=self.plan_id) def time_create_with_details(self) -> None: DomainEvent( event_type=self.event_type, plan_id=self.plan_id, details={"phase": "strategize", "actor": "strategists/planner"}, ) # --------------------------------------------------------------------------- # ReactiveEventBus emit # --------------------------------------------------------------------------- class ReactiveEmitSuite: """Benchmark ReactiveEventBus.emit() throughput.""" timeout = 60 def setup(self) -> None: self.bus = ReactiveEventBus() self.event = DomainEvent(event_type=EventType.PLAN_CREATED) self.decision_event = DomainEvent(event_type=EventType.DECISION_CREATED) # Pre-register a subscriber for the with-subscriber benchmarks self._received: list[DomainEvent] = [] self.bus.subscribe(EventType.PLAN_CREATED, self._received.append) def time_emit_no_subscribers(self) -> None: self.bus.emit(self.decision_event) def time_emit_with_one_subscriber(self) -> None: self.bus.emit(self.event) def time_emit_100_events(self) -> None: for _ in range(100): self.bus.emit(self.event) # --------------------------------------------------------------------------- # ReactiveEventBus subscribe # --------------------------------------------------------------------------- class ReactiveSubscribeSuite: """Benchmark ReactiveEventBus.subscribe() overhead.""" timeout = 60 def setup(self) -> None: self.event_type = EventType.PLAN_CREATED def time_subscribe_single(self) -> None: bus = ReactiveEventBus() bus.subscribe(self.event_type, lambda e: None) def time_subscribe_10(self) -> None: bus = ReactiveEventBus() for _ in range(10): bus.subscribe(self.event_type, lambda e: None) # --------------------------------------------------------------------------- # Fan-out benchmark # --------------------------------------------------------------------------- class FanOutSuite: """Benchmark event fan-out to multiple subscribers.""" timeout = 60 params: ClassVar[list[int]] = [1, 5, 10, 50] param_names: ClassVar[list[str]] = ["num_subscribers"] def setup(self, num_subscribers: int) -> None: self.bus = ReactiveEventBus() for _ in range(num_subscribers): self.bus.subscribe(EventType.PLAN_CREATED, lambda e: None) self.event = DomainEvent(event_type=EventType.PLAN_CREATED) def time_emit(self, num_subscribers: int) -> None: self.bus.emit(self.event) # --------------------------------------------------------------------------- # LoggingEventBus emit # --------------------------------------------------------------------------- class LoggingEmitSuite: """Benchmark LoggingEventBus.emit() overhead.""" timeout = 60 def setup(self) -> None: import logging logging.disable(logging.CRITICAL) self.bus = LoggingEventBus() self.event = DomainEvent(event_type=EventType.DECISION_CREATED) def time_emit_single(self) -> None: self.bus.emit(self.event) def time_emit_100(self) -> None: for _ in range(100): self.bus.emit(self.event)