9aa966cdaa
- Fix get_retry_decorator() calls to use category string instead of keyword arguments (max_attempts, base_delay, etc.) - Fix retry_on_result() calls to pass required predicate argument - Fix retry_service_operation() to use circuit_breaker= (CircuitBreaker instance) instead of use_circuit_breaker= (bool), and backoff_strategy= instead of wait_strategy= - Fix is_read_only_plan_operation() calls to pass dict instead of string - Fix RetryContext() to use operation_name= instead of service_name=, remove non-existent use_circuit_breaker and attempt_count constructor params - Fix retry_auto_debug() to use max_debug_attempts= instead of service_name=/operation_name= (which are not valid parameters) - Remove unused Any import from core_circuit_breaker_bench.py - Apply ruff format to all three benchmark files to fix CI format check
282 lines
8.2 KiB
Python
282 lines
8.2 KiB
Python
"""ASV benchmarks for retry patterns.
|
|
|
|
Measures the overhead of retry decorator construction and
|
|
happy-path invocation for the public retry factory functions.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from typing import Any
|
|
|
|
from cleveragents.core.retry_patterns import (
|
|
get_retry_decorator,
|
|
retry_on_result,
|
|
retry_with_exponential_backoff,
|
|
retry_with_jitter,
|
|
retry_with_timeout,
|
|
should_retry_result,
|
|
)
|
|
|
|
|
|
class RetryDecoratorConstructionBench:
|
|
"""Benchmark retry decorator construction overhead."""
|
|
|
|
timeout = 60
|
|
|
|
def time_retry_with_exponential_backoff_construction(self) -> None:
|
|
"""Benchmark constructing exponential backoff decorator."""
|
|
|
|
@retry_with_exponential_backoff(max_attempts=3)
|
|
def dummy_func() -> str:
|
|
return "success"
|
|
|
|
def time_retry_with_jitter_construction(self) -> None:
|
|
"""Benchmark constructing jitter decorator."""
|
|
|
|
@retry_with_jitter(max_attempts=3)
|
|
def dummy_func() -> str:
|
|
return "success"
|
|
|
|
def time_retry_with_timeout_construction(self) -> None:
|
|
"""Benchmark constructing timeout decorator."""
|
|
|
|
@retry_with_timeout(timeout_seconds=5.0)
|
|
def dummy_func() -> str:
|
|
return "success"
|
|
|
|
def time_retry_on_result_construction(self) -> None:
|
|
"""Benchmark constructing result-based retry decorator."""
|
|
|
|
@retry_on_result(should_retry_result, max_attempts=3)
|
|
def dummy_func() -> str:
|
|
return "success"
|
|
|
|
def time_get_retry_decorator_network(self) -> None:
|
|
"""Benchmark constructing decorator via factory for network category."""
|
|
get_retry_decorator("network")
|
|
|
|
def time_get_retry_decorator_provider(self) -> None:
|
|
"""Benchmark constructing decorator via factory for provider category."""
|
|
get_retry_decorator("provider")
|
|
|
|
def time_get_retry_decorator_database(self) -> None:
|
|
"""Benchmark constructing decorator via factory for database category."""
|
|
get_retry_decorator("database")
|
|
|
|
def time_get_retry_decorator_unknown(self) -> None:
|
|
"""Benchmark constructing decorator via factory for unknown category."""
|
|
get_retry_decorator("unknown_category")
|
|
|
|
|
|
class RetryDecoratorInvocationBench:
|
|
"""Benchmark happy-path retry decorator invocation."""
|
|
|
|
timeout = 60
|
|
|
|
def setup(self) -> None:
|
|
"""Set up decorated functions."""
|
|
|
|
@retry_with_exponential_backoff(max_attempts=3)
|
|
def exponential_func() -> str:
|
|
return "success"
|
|
|
|
@retry_with_jitter(max_attempts=3)
|
|
def jitter_func() -> str:
|
|
return "success"
|
|
|
|
@retry_with_timeout(timeout_seconds=5.0)
|
|
def timeout_func() -> str:
|
|
return "success"
|
|
|
|
@retry_on_result(should_retry_result, max_attempts=3)
|
|
def result_func() -> str:
|
|
return "success"
|
|
|
|
self.exponential_func = exponential_func
|
|
self.jitter_func = jitter_func
|
|
self.timeout_func = timeout_func
|
|
self.result_func = result_func
|
|
|
|
def time_exponential_backoff_invocation(self) -> None:
|
|
"""Benchmark exponential backoff invocation (happy path)."""
|
|
self.exponential_func()
|
|
|
|
def time_jitter_invocation(self) -> None:
|
|
"""Benchmark jitter invocation (happy path)."""
|
|
self.jitter_func()
|
|
|
|
def time_timeout_invocation(self) -> None:
|
|
"""Benchmark timeout invocation (happy path)."""
|
|
self.timeout_func()
|
|
|
|
def time_result_based_invocation(self) -> None:
|
|
"""Benchmark result-based retry invocation (happy path)."""
|
|
self.result_func()
|
|
|
|
|
|
class RetryDecoratorAsyncBench:
|
|
"""Benchmark async retry decorator operations."""
|
|
|
|
timeout = 60
|
|
|
|
def setup(self) -> None:
|
|
"""Set up async decorated functions."""
|
|
|
|
@retry_with_exponential_backoff(max_attempts=3)
|
|
async def async_exponential() -> str:
|
|
return "success"
|
|
|
|
@retry_with_jitter(max_attempts=3)
|
|
async def async_jitter() -> str:
|
|
return "success"
|
|
|
|
@retry_with_timeout(timeout_seconds=5.0)
|
|
async def async_timeout() -> str:
|
|
return "success"
|
|
|
|
self.async_exponential = async_exponential
|
|
self.async_jitter = async_jitter
|
|
self.async_timeout = async_timeout
|
|
|
|
def time_async_exponential_invocation(self) -> None:
|
|
"""Benchmark async exponential backoff invocation."""
|
|
asyncio.run(self.async_exponential())
|
|
|
|
def time_async_jitter_invocation(self) -> None:
|
|
"""Benchmark async jitter invocation."""
|
|
asyncio.run(self.async_jitter())
|
|
|
|
def time_async_timeout_invocation(self) -> None:
|
|
"""Benchmark async timeout invocation."""
|
|
asyncio.run(self.async_timeout())
|
|
|
|
|
|
class RetryDecoratorWithArgumentsBench:
|
|
"""Benchmark retry decorators with function arguments."""
|
|
|
|
timeout = 60
|
|
|
|
def setup(self) -> None:
|
|
"""Set up decorated functions with arguments."""
|
|
|
|
@retry_with_exponential_backoff(max_attempts=3)
|
|
def func_with_args(x: int, y: str, z: float = 1.0) -> str:
|
|
return f"{x}:{y}:{z}"
|
|
|
|
@retry_with_jitter(max_attempts=3)
|
|
def func_with_kwargs(a: int, b: str = "default") -> str:
|
|
return f"{a}:{b}"
|
|
|
|
self.func_with_args = func_with_args
|
|
self.func_with_kwargs = func_with_kwargs
|
|
|
|
def time_exponential_with_positional_args(self) -> None:
|
|
"""Benchmark exponential backoff with positional arguments."""
|
|
self.func_with_args(42, "test", 2.5)
|
|
|
|
def time_exponential_with_keyword_args(self) -> None:
|
|
"""Benchmark exponential backoff with keyword arguments."""
|
|
self.func_with_args(x=42, y="test", z=2.5)
|
|
|
|
def time_jitter_with_mixed_args(self) -> None:
|
|
"""Benchmark jitter with mixed positional and keyword arguments."""
|
|
self.func_with_kwargs(100, b="custom")
|
|
|
|
|
|
class RetryDecoratorFactoryBench:
|
|
"""Benchmark retry decorator factory function."""
|
|
|
|
timeout = 60
|
|
|
|
def time_factory_network_category(self) -> None:
|
|
"""Benchmark factory with network category."""
|
|
decorator = get_retry_decorator("network")
|
|
|
|
@decorator
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
def time_factory_provider_category(self) -> None:
|
|
"""Benchmark factory with provider category."""
|
|
decorator = get_retry_decorator("provider")
|
|
|
|
@decorator
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
def time_factory_database_category(self) -> None:
|
|
"""Benchmark factory with database category."""
|
|
decorator = get_retry_decorator("database")
|
|
|
|
@decorator
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
def time_factory_file_operation_category(self) -> None:
|
|
"""Benchmark factory with file_operation category."""
|
|
decorator = get_retry_decorator("file_operation")
|
|
|
|
@decorator
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
|
|
class RetryDecoratorConfigurationBench:
|
|
"""Benchmark retry decorator with various configurations."""
|
|
|
|
timeout = 60
|
|
|
|
def time_minimal_config(self) -> None:
|
|
"""Benchmark decorator with minimal configuration."""
|
|
|
|
@retry_with_exponential_backoff()
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
def time_aggressive_config(self) -> None:
|
|
"""Benchmark decorator with aggressive retry settings."""
|
|
|
|
@retry_with_exponential_backoff(max_attempts=10)
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
def time_conservative_config(self) -> None:
|
|
"""Benchmark decorator with conservative retry settings."""
|
|
|
|
@retry_with_exponential_backoff(max_attempts=1)
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
def time_long_timeout_config(self) -> None:
|
|
"""Benchmark decorator with long timeout."""
|
|
|
|
@retry_with_timeout(timeout_seconds=300.0)
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|
|
|
|
def time_short_timeout_config(self) -> None:
|
|
"""Benchmark decorator with short timeout."""
|
|
|
|
@retry_with_timeout(timeout_seconds=0.1)
|
|
def dummy() -> str:
|
|
return "success"
|
|
|
|
dummy()
|