Skip to content

⚡️ Speed up method DefaultDependency.as_dict by 26% - #25

Open
codeflash-ai[bot] wants to merge 1 commit into
mainfrom
codeflash/optimize-DefaultDependency.as_dict-mihbqdkc
Open

⚡️ Speed up method DefaultDependency.as_dict by 26%#25
codeflash-ai[bot] wants to merge 1 commit into
mainfrom
codeflash/optimize-DefaultDependency.as_dict-mihbqdkc

Conversation

@codeflash-ai

@codeflash-ai codeflash-ai Bot commented Nov 27, 2025

Copy link
Copy Markdown

📄 26% (0.26x) speedup for DefaultDependency.as_dict in src/titiler/core/titiler/core/dependencies.py

⏱️ Runtime : 62.3 microseconds 49.3 microseconds (best of 156 runs)

📝 Explanation and details

The optimization achieves a 26% speedup by eliminating expensive method calls and reducing Python bytecode overhead in the dictionary filtering path.

Key optimizations applied:

  1. Eliminated .items() method lookup: The original code called self.__dict__.items() which creates a temporary list of key-value tuples. The optimized version directly iterates over the dictionary keys and accesses values via dct[k], avoiding this intermediate object creation.

  2. Replaced dictionary comprehension with explicit loop: Dictionary comprehensions in Python have function call overhead and cannot pre-allocate the result dictionary size. The explicit loop with pre-allocated result = {} is more efficient for filtering operations.

  3. Cached self.__dict__ lookup: Storing self.__dict__ in a local variable dct eliminates repeated attribute lookups during iteration, providing faster local variable access.

  4. Streamlined non-filtering path: Changed dict(self.__dict__.items()) to dict(dct), avoiding the unnecessary .items() call when no filtering is needed.

Performance characteristics:

  • The optimization is most effective for dataclasses with mixed None/non-None values (28-46% faster based on test results)
  • Empty dataclasses see the largest gains (52-56% faster) due to eliminating method overhead entirely
  • All-None scenarios benefit significantly (29-44% faster) as the filtering loop is more efficient
  • Cases with no None values show modest improvements (5-20% faster) since the non-filtering path is also optimized

The test results demonstrate consistent performance gains across all scenarios, with the most dramatic improvements in cases where the original code's method call overhead was most pronounced relative to the actual work being done.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 14 Passed
🌀 Generated Regression Tests 42 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 4 Passed
📊 Tests Coverage 100.0%
⚙️ Existing Unit Tests and Runtime
🌀 Generated Regression Tests and Runtime
from dataclasses import dataclass, field
from typing import Any, Dict, Optional

# imports
import pytest
from titiler.core.dependencies import DefaultDependency

# --- Unit Tests ---

# 1. Basic Test Cases

def test_empty_dataclass_returns_empty_dict():
    """Test as_dict on a dataclass with no fields."""
    class Empty(DefaultDependency):
        pass
    dep = Empty()
    codeflash_output = dep.as_dict() # 1.34μs -> 877ns (52.3% faster)

def test_single_field_not_none():
    """Test as_dict with a single non-None field."""
    @dataclass
    class Single(DefaultDependency):
        a: int
    dep = Single(a=42)
    codeflash_output = dep.as_dict() # 1.46μs -> 1.14μs (28.3% faster)

def test_single_field_none_excluded_by_default():
    """Test as_dict with a single field set to None, excluded by default."""
    @dataclass
    class Single(DefaultDependency):
        a: Optional[int] = None
    dep = Single()
    codeflash_output = dep.as_dict() # 1.49μs -> 1.02μs (45.9% faster)

def test_single_field_none_included_if_requested():
    """Test as_dict with a single field set to None, included if exclude_none=False."""
    @dataclass
    class Single(DefaultDependency):
        a: Optional[int] = None
    dep = Single()
    codeflash_output = dep.as_dict(exclude_none=False) # 1.59μs -> 1.40μs (13.8% faster)

def test_multiple_fields_mixed_values():
    """Test as_dict with multiple fields, some None, some not."""
    @dataclass
    class Mixed(DefaultDependency):
        a: int
        b: Optional[str] = None
        c: float = 1.5
    dep = Mixed(a=7, b=None, c=3.14)
    codeflash_output = dep.as_dict() # 1.70μs -> 1.24μs (37.7% faster)
    codeflash_output = dep.as_dict(exclude_none=False) # 1.11μs -> 1.06μs (5.21% faster)

def test_field_with_false_and_zero_values():
    """Test as_dict with fields set to False and 0, which should NOT be excluded."""
    @dataclass
    class BoolZero(DefaultDependency):
        a: bool = False
        b: int = 0
        c: Optional[str] = None
    dep = BoolZero()
    codeflash_output = dep.as_dict() # 1.66μs -> 1.31μs (26.8% faster)

def test_field_with_empty_string_and_list():
    """Test as_dict with empty string and list, which should NOT be excluded."""
    @dataclass
    class EmptyValues(DefaultDependency):
        a: str = ""
        b: list = field(default_factory=list)
        c: None = None
    dep = EmptyValues()
    codeflash_output = dep.as_dict() # 1.64μs -> 1.34μs (22.8% faster)

# 2. Edge Test Cases

def test_field_with_nested_dataclass():
    """Test as_dict with a nested dataclass as a field."""
    @dataclass
    class Inner(DefaultDependency):
        x: int
    @dataclass
    class Outer(DefaultDependency):
        inner: Inner
        y: int
        z: None = None
    dep = Outer(inner=Inner(x=10), y=20)
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.72μs -> 1.29μs (32.8% faster)
    codeflash_output = dep.as_dict(exclude_none=False); d2 = codeflash_output # 1.08μs -> 1.03μs (4.55% faster)

def test_field_with_custom_object():
    """Test as_dict with a field set to a custom object."""
    class CustomObj:
        pass
    @dataclass
    class CustomField(DefaultDependency):
        obj: Any
    dep = CustomField(obj=CustomObj())
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.45μs -> 1.05μs (38.2% faster)

def test_field_with_callable_and_function():
    """Test as_dict with a field set to a function/callable."""
    def myfunc():
        return 123
    @dataclass
    class FuncField(DefaultDependency):
        f: Any
    dep = FuncField(f=myfunc)
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.39μs -> 1.04μs (33.9% faster)

def test_field_with_tuple_and_set():
    """Test as_dict with tuple and set fields."""
    @dataclass
    class TupleSet(DefaultDependency):
        tup: tuple = (1, 2)
        st: set = field(default_factory=lambda: {3, 4})
        none: None = None
    dep = TupleSet()
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.78μs -> 1.37μs (29.8% faster)

def test_field_with_dict_containing_none_values():
    """Test as_dict with a dict field containing None values."""
    @dataclass
    class DictField(DefaultDependency):
        d: dict = field(default_factory=lambda: {'a': None, 'b': 1})
    dep = DictField()
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.52μs -> 1.11μs (36.1% faster)

def test_exclude_none_false_with_all_none_fields():
    """Test as_dict with all fields None and exclude_none=False."""
    @dataclass
    class AllNone(DefaultDependency):
        a: None = None
        b: None = None
    dep = AllNone()
    codeflash_output = dep.as_dict() # 1.60μs -> 1.14μs (40.6% faster)
    codeflash_output = dep.as_dict(exclude_none=False) # 1.18μs -> 1.11μs (5.75% faster)

def test_exclude_none_true_with_all_none_fields():
    """Test as_dict with all fields None and exclude_none=True."""
    @dataclass
    class AllNone(DefaultDependency):
        a: None = None
        b: None = None
    dep = AllNone()
    codeflash_output = dep.as_dict(exclude_none=True) # 1.74μs -> 1.35μs (28.6% faster)

def test_field_with_unusual_types():
    """Test as_dict with unusual field types (bytes, complex, etc)."""
    @dataclass
    class WeirdTypes(DefaultDependency):
        b: bytes = b'abc'
        c: complex = 3+4j
        n: None = None
    dep = WeirdTypes()
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.74μs -> 1.30μs (33.8% faster)

def test_field_with_property_and_private_attribute():
    """Test as_dict does not include properties or private attributes."""
    @dataclass
    class Prop(DefaultDependency):
        a: int = 1
        _private: int = field(default=2, repr=False)
        @property
        def prop(self):
            return 3
    dep = Prop()
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.56μs -> 1.10μs (42.2% faster)

def test_field_with_class_variable():
    """Test as_dict does not include class variables."""
    @dataclass
    class ClassVar(DefaultDependency):
        a: int = 1
        b: int = 2
        static: int = 3
    ClassVar.static = 999  # class variable
    dep = ClassVar()
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.61μs -> 1.31μs (22.5% faster)

# 3. Large Scale Test Cases

def test_large_nested_dataclass():
    """Test as_dict with a large nested dataclass structure."""
    @dataclass
    class Inner(DefaultDependency):
        val: int
    N = 100
    @dataclass
    class Outer(DefaultDependency):
        inners: list = field(default_factory=list)
    dep = Outer(inners=[Inner(val=i) for i in range(N)])
    codeflash_output = dep.as_dict(); d = codeflash_output # 1.68μs -> 1.27μs (32.3% faster)
    for i, inner in enumerate(d['inners']):
        pass
from dataclasses import dataclass, field
from typing import Any, Dict, Optional

# imports
import pytest
from titiler.core.dependencies import DefaultDependency

# ---- UNIT TESTS ----

# --- BASIC TEST CASES ---

def test_as_dict_basic_with_no_fields():
    """Test as_dict on a dataclass with no fields."""
    dep = DefaultDependency()
    # Should return empty dict regardless of exclude_none
    codeflash_output = dep.as_dict() # 1.18μs -> 759ns (55.7% faster)
    codeflash_output = dep.as_dict(exclude_none=False) # 969ns -> 687ns (41.0% faster)

def test_as_dict_basic_with_fields_all_non_none():
    """Test as_dict with all fields set and non-None values."""
    @dataclass
    class MyDep(DefaultDependency):
        a: int
        b: str
        c: float

    dep = MyDep(a=5, b="hello", c=3.14)
    # Should include all fields
    expected = {'a': 5, 'b': 'hello', 'c': 3.14}
    codeflash_output = dep.as_dict() # 1.55μs -> 1.28μs (20.9% faster)
    codeflash_output = dep.as_dict(exclude_none=False) # 1.13μs -> 1.02μs (10.3% faster)

def test_as_dict_basic_with_some_none_fields():
    """Test as_dict with some fields set to None."""
    @dataclass
    class MyDep(DefaultDependency):
        a: int
        b: Optional[str]
        c: Optional[float]

    dep = MyDep(a=42, b=None, c=None)
    # exclude_none=True should omit None fields
    codeflash_output = dep.as_dict() # 1.62μs -> 1.19μs (36.1% faster)
    # exclude_none=False should include all fields, including None
    codeflash_output = dep.as_dict(exclude_none=False) # 1.04μs -> 1.02μs (2.45% faster)

def test_as_dict_basic_with_falsey_values():
    """Test as_dict with fields set to falsey values (0, '', False)."""
    @dataclass
    class MyDep(DefaultDependency):
        a: int
        b: str
        c: bool

    dep = MyDep(a=0, b='', c=False)
    # Falsey values are not None, so they should be included
    expected = {'a': 0, 'b': '', 'c': False}
    codeflash_output = dep.as_dict() # 1.57μs -> 1.26μs (25.0% faster)
    codeflash_output = dep.as_dict(exclude_none=False) # 1.06μs -> 954ns (11.4% faster)

# --- EDGE TEST CASES ---

def test_as_dict_edge_with_all_none_fields():
    """Test as_dict with all fields set to None."""
    @dataclass
    class MyDep(DefaultDependency):
        a: Optional[int]
        b: Optional[str]

    dep = MyDep(a=None, b=None)
    # exclude_none=True should return empty dict
    codeflash_output = dep.as_dict() # 1.52μs -> 1.06μs (43.2% faster)
    # exclude_none=False should return all fields with None values
    codeflash_output = dep.as_dict(exclude_none=False) # 1.06μs -> 948ns (11.9% faster)

def test_as_dict_edge_with_mixed_types_and_nested_dict():
    """Test as_dict with mixed types including nested dicts and lists."""
    @dataclass
    class MyDep(DefaultDependency):
        a: int
        b: dict
        c: list
        d: None

    dep = MyDep(a=1, b={'x': 2}, c=[1, 2, 3], d=None)
    # exclude_none=True should omit 'd'
    codeflash_output = dep.as_dict() # 1.73μs -> 1.44μs (20.4% faster)
    # exclude_none=False should include 'd'
    codeflash_output = dep.as_dict(exclude_none=False) # 1.10μs -> 1.10μs (0.000% faster)

def test_as_dict_edge_with_field_named_none():
    """Test as_dict with a field literally named 'none'."""
    @dataclass
    class MyDep(DefaultDependency):
        none: int
        value: None

    dep = MyDep(none=123, value=None)
    # 'none' field is not None, so should be included
    codeflash_output = dep.as_dict() # 1.55μs -> 1.21μs (28.4% faster)
    codeflash_output = dep.as_dict(exclude_none=False) # 1.05μs -> 1.01μs (4.15% faster)

def test_as_dict_edge_with_field_default_factory_none():
    """Test as_dict with a field that defaults to None via default_factory."""
    @dataclass
    class MyDep(DefaultDependency):
        a: Optional[int] = field(default_factory=lambda: None)
        b: str = "test"

    dep = MyDep()
    # 'a' is None, so omitted with exclude_none=True
    codeflash_output = dep.as_dict() # 1.56μs -> 1.17μs (33.4% faster)
    codeflash_output = dep.as_dict(exclude_none=False) # 1.04μs -> 965ns (7.46% faster)

def test_as_dict_edge_with_private_and_dunder_fields():
    """Test as_dict ignores private and dunder fields (by default, dataclasses don't include them)."""
    @dataclass
    class MyDep(DefaultDependency):
        a: int
        _private: int = 99
        __dunder: int = 88

    dep = MyDep(a=1)
    # Only 'a' is included, as dataclasses do not include _private or __dunder in __dict__ by default
    # But let's check __dict__ to be sure
    codeflash_output = dep.as_dict() # 1.59μs -> 1.21μs (31.2% faster)
    # _private is included in __dict__, but __dunder is name-mangled
    codeflash_output = dep.as_dict() # 557ns -> 448ns (24.3% faster)
    # __dunder is name-mangled
    codeflash_output = dep.as_dict(exclude_none=False); dct = codeflash_output # 941ns -> 928ns (1.40% faster)
    mangled = [k for k in dct if k.startswith('_MyDep__dunder')]

# --- LARGE SCALE TEST CASES ---
from titiler.core.dependencies import DefaultDependency

def test_DefaultDependency_as_dict():
    DefaultDependency.as_dict(DefaultDependency(), exclude_none=True)

def test_DefaultDependency_as_dict_2():
    DefaultDependency.as_dict(DefaultDependency(), exclude_none=False)
🔎 Concolic Coverage Tests and Runtime

To edit these changes git checkout codeflash/optimize-DefaultDependency.as_dict-mihbqdkc and push.

Codeflash Static Badge

The optimization achieves a **26% speedup** by eliminating expensive method calls and reducing Python bytecode overhead in the dictionary filtering path.

**Key optimizations applied:**

1. **Eliminated `.items()` method lookup**: The original code called `self.__dict__.items()` which creates a temporary list of key-value tuples. The optimized version directly iterates over the dictionary keys and accesses values via `dct[k]`, avoiding this intermediate object creation.

2. **Replaced dictionary comprehension with explicit loop**: Dictionary comprehensions in Python have function call overhead and cannot pre-allocate the result dictionary size. The explicit loop with pre-allocated `result = {}` is more efficient for filtering operations.

3. **Cached `self.__dict__` lookup**: Storing `self.__dict__` in a local variable `dct` eliminates repeated attribute lookups during iteration, providing faster local variable access.

4. **Streamlined non-filtering path**: Changed `dict(self.__dict__.items())` to `dict(dct)`, avoiding the unnecessary `.items()` call when no filtering is needed.

**Performance characteristics:**
- The optimization is most effective for dataclasses with **mixed None/non-None values** (28-46% faster based on test results)
- **Empty dataclasses** see the largest gains (52-56% faster) due to eliminating method overhead entirely  
- **All-None scenarios** benefit significantly (29-44% faster) as the filtering loop is more efficient
- Cases with **no None values** show modest improvements (5-20% faster) since the non-filtering path is also optimized

The test results demonstrate consistent performance gains across all scenarios, with the most dramatic improvements in cases where the original code's method call overhead was most pronounced relative to the actual work being done.
@codeflash-ai
codeflash-ai Bot requested a review from mashraf-222 November 27, 2025 11:02
@codeflash-ai codeflash-ai Bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash labels Nov 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants