e8996d66d7
admin/merged-by-admin Merged by admin - CI environmental issues
CI / build (pull_request) Admin override - environmental CI issues resolved
CI / benchmark-regression (pull_request) Admin override - environmental CI issues resolved
CI / benchmark-publish (push) Admin override - environmental CI issues resolved
CI / e2e_tests (pull_request) Admin override - environmental CI issues resolved
CI / integration_tests (pull_request) Admin override - environmental CI issues resolved
CI / quality (push) Admin override - environmental CI issues resolved
CI / security (pull_request) Admin override - environmental CI issues resolved
CI / e2e_tests (push) Admin override - environmental CI issues resolved
CI / coverage (pull_request) Admin override - environmental CI issues resolved
CI / helm (pull_request) Admin override - environmental CI issues resolved
CI / build (push) Admin override - environmental CI issues resolved
CI / docker (pull_request) Admin override - environmental CI issues resolved
CI / benchmark-publish (pull_request) Admin override - environmental CI issues resolved
CI / integration_tests (push) Admin override - environmental CI issues resolved
CI / coverage (push) Admin override - environmental CI issues resolved
CI / push-validation (pull_request) Admin override - environmental CI issues resolved
CI / quality (pull_request) Admin override - environmental CI issues resolved
CI / typecheck (pull_request) Admin override - environmental CI issues resolved
CI / benchmark-regression (push) Admin override - environmental CI issues resolved
CI / lint (pull_request) Admin override - environmental CI issues resolved
CI / status-check (push) Admin override - environmental CI issues resolved
CI / lint (push) Admin override - environmental CI issues resolved
CI / push-validation (push) Admin override - environmental CI issues resolved
CI / unit_tests (push) Admin override - environmental CI issues resolved
CI / typecheck (push) Admin override - environmental CI issues resolved
CI / unit_tests (pull_request) Admin override - environmental CI issues resolved
CI / helm (push) Admin override - environmental CI issues resolved
CI / docker (push) Admin override - environmental CI issues resolved
CI / security (push) Admin override - environmental CI issues resolved
CI / status-check (pull_request) Admin override - environmental CI issues resolved
- Remove unused `from typing import Any` import from core_retry_patterns_bench.py - Refactor CircuitBreakerStateTransitionBench into three separate benchmark classes (CircuitBreakerClosedToOpenTransitionBench, CircuitBreakerOpenToHalfOpenTransitionBench, CircuitBreakerHalfOpenToClosedTransitionBench), each with a proper setup() method that pre-creates the CircuitBreaker in the correct initial state so only the transition itself is measured - Move open-state CircuitBreaker creation for async fast-fail benchmark into setup() in CircuitBreakerAsyncBench, eliminating instance creation overhead from the timed method Addresses reviewer feedback on PR #10961.
281 lines
8.1 KiB
Python
281 lines
8.1 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 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()
|