|
| 1 | +"""Benchmark comparator type dispatch performance. |
| 2 | +
|
| 3 | +Exercises the fast-path frozenset lookup vs isinstance MRO traversal |
| 4 | +across realistic return value shapes: primitives, nested containers, |
| 5 | +and mixed-type structures typical of real optimization verification. |
| 6 | +""" |
| 7 | + |
| 8 | +from __future__ import annotations |
| 9 | + |
| 10 | +from collections import OrderedDict |
| 11 | +from decimal import Decimal |
| 12 | + |
| 13 | +from codeflash.verification.comparator import comparator |
| 14 | + |
| 15 | +# --- Test data: realistic return value shapes --- |
| 16 | + |
| 17 | +# 1. Flat primitives (int, bool, None, str, float, bytes) — the fast-path sweet spot |
| 18 | +_PRIMITIVES_A = [ |
| 19 | + 42, |
| 20 | + True, |
| 21 | + None, |
| 22 | + 3.14, |
| 23 | + "hello", |
| 24 | + b"bytes", |
| 25 | + 0, |
| 26 | + False, |
| 27 | + "", |
| 28 | + 1.0, |
| 29 | + -1, |
| 30 | + None, |
| 31 | + True, |
| 32 | + 99, |
| 33 | + "world", |
| 34 | + b"\x00\x01", |
| 35 | + 2**31, |
| 36 | + 0.0, |
| 37 | + False, |
| 38 | + None, |
| 39 | +] |
| 40 | +_PRIMITIVES_B = list(_PRIMITIVES_A) |
| 41 | + |
| 42 | +# 2. Nested dict of lists (common return value shape: API responses, parsed configs) |
| 43 | +_NESTED_DICT_A = { |
| 44 | + "users": [{"id": i, "name": f"user_{i}", "active": i % 2 == 0, "score": i * 1.5} for i in range(50)], |
| 45 | + "metadata": {"total": 50, "page": 1, "has_next": True}, |
| 46 | + "tags": [f"tag_{i}" for i in range(20)], |
| 47 | + "config": {"timeout": 30, "retries": 3, "debug": False, "threshold": Decimal("0.95")}, |
| 48 | +} |
| 49 | +_NESTED_DICT_B = { |
| 50 | + "users": [{"id": i, "name": f"user_{i}", "active": i % 2 == 0, "score": i * 1.5} for i in range(50)], |
| 51 | + "metadata": {"total": 50, "page": 1, "has_next": True}, |
| 52 | + "tags": [f"tag_{i}" for i in range(20)], |
| 53 | + "config": {"timeout": 30, "retries": 3, "debug": False, "threshold": Decimal("0.95")}, |
| 54 | +} |
| 55 | + |
| 56 | +# 3. List of tuples (common: database rows, CSV data) |
| 57 | +_ROWS_A = [(i, f"row_{i}", i * 0.1, i % 3 == 0, None if i % 5 == 0 else i) for i in range(200)] |
| 58 | +_ROWS_B = [(i, f"row_{i}", i * 0.1, i % 3 == 0, None if i % 5 == 0 else i) for i in range(200)] |
| 59 | + |
| 60 | + |
| 61 | +# 4. Deeply nested structure (worst case for recursive comparator) |
| 62 | +def _make_deep(depth: int) -> dict: |
| 63 | + if depth == 0: |
| 64 | + return {"leaf": True, "value": 42, "items": [1, 2, 3], "label": "end"} |
| 65 | + return {"level": depth, "child": _make_deep(depth - 1), "siblings": list(range(depth))} |
| 66 | + |
| 67 | + |
| 68 | +_DEEP_A = _make_deep(15) |
| 69 | +_DEEP_B = _make_deep(15) |
| 70 | + |
| 71 | +# 5. Mixed identity types (frozenset, range, slice, OrderedDict, bytes, complex) |
| 72 | +_IDENTITY_TYPES_A = [ |
| 73 | + frozenset({1, 2, 3}), |
| 74 | + range(100), |
| 75 | + complex(1, 2), |
| 76 | + Decimal("3.14"), |
| 77 | + OrderedDict(a=1, b=2), |
| 78 | + b"binary", |
| 79 | + bytearray(b"mutable"), |
| 80 | + memoryview(b"view"), |
| 81 | + type(None), |
| 82 | + True, |
| 83 | + 42, |
| 84 | + None, |
| 85 | +] * 10 |
| 86 | +_IDENTITY_TYPES_B = list(_IDENTITY_TYPES_A) |
| 87 | + |
| 88 | + |
| 89 | +def _compare_all_primitives() -> None: |
| 90 | + for a, b in zip(_PRIMITIVES_A, _PRIMITIVES_B): |
| 91 | + comparator(a, b) |
| 92 | + |
| 93 | + |
| 94 | +def _compare_nested_dict() -> None: |
| 95 | + comparator(_NESTED_DICT_A, _NESTED_DICT_B) |
| 96 | + |
| 97 | + |
| 98 | +def _compare_rows() -> None: |
| 99 | + comparator(_ROWS_A, _ROWS_B) |
| 100 | + |
| 101 | + |
| 102 | +def _compare_deep() -> None: |
| 103 | + comparator(_DEEP_A, _DEEP_B) |
| 104 | + |
| 105 | + |
| 106 | +def _compare_identity_types() -> None: |
| 107 | + for a, b in zip(_IDENTITY_TYPES_A, _IDENTITY_TYPES_B): |
| 108 | + comparator(a, b) |
| 109 | + |
| 110 | + |
| 111 | +def test_benchmark_comparator_primitives(benchmark) -> None: |
| 112 | + """20 flat primitive comparisons (int, bool, None, str, float, bytes).""" |
| 113 | + benchmark(_compare_all_primitives) |
| 114 | + |
| 115 | + |
| 116 | +def test_benchmark_comparator_nested_dict(benchmark) -> None: |
| 117 | + """Nested dict with 50-element user list, metadata, tags, config.""" |
| 118 | + benchmark(_compare_nested_dict) |
| 119 | + |
| 120 | + |
| 121 | +def test_benchmark_comparator_rows(benchmark) -> None: |
| 122 | + """200 tuples of (int, str, float, bool, Optional[int]).""" |
| 123 | + benchmark(_compare_rows) |
| 124 | + |
| 125 | + |
| 126 | +def test_benchmark_comparator_deep(benchmark) -> None: |
| 127 | + """15-level deep nested dict structure.""" |
| 128 | + benchmark(_compare_deep) |
| 129 | + |
| 130 | + |
| 131 | +def test_benchmark_comparator_identity_types(benchmark) -> None: |
| 132 | + """120 frozenset/range/complex/Decimal/OrderedDict/bytes comparisons.""" |
| 133 | + benchmark(_compare_identity_types) |
0 commit comments