Skip to content

⚡️ Speed up method Usage.__add__ by 290% #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: try-refinement
Choose a base branch
from

Conversation

codeflash-ai[bot]
Copy link

@codeflash-ai codeflash-ai bot commented Jul 22, 2025

📄 290% (2.90x) speedup for Usage.__add__ in pydantic_ai_slim/pydantic_ai/usage.py

⏱️ Runtime : 3.25 microseconds 834 nanoseconds (best of 235 runs)

📝 Explanation and details

REFINEMENT Here is an optimized version of your provided code.
Summary of speedups applied:

  • Avoid repeated getattr/setattr: Use direct attribute access since field names are statically known, avoiding attribute lookup overhead.
  • In __add__: Avoid slow copy(self). Use direct construction, which is both faster and more memory-efficient for your dataclass.
  • Details merging optimization: Bulk update details using collections.Counter if available to minimize key-by-key dict overhead (but without importing new modules if not already present, as none are imported in the original).

All logic and return values remain identical.

Key optimizations.

  • incr:
    • Uses local variables for self/other, and direct attribute access.
    • Merges details dict in-place if present; only copies when necessary.
  • __add__:
    • Avoids copy, just constructs a merged Usage directly, calculating all fields in one step.
    • For details, merges in minimal steps, using shallow .copy() only as needed.

This will notably reduce attribute lookup, dictionary calls, and avoid unnecessary copying for the common case. No external dependencies are used, and all comments are preserved unless a related section changed.

Your Usage.__repr__ and type annotations remain as in the reference codebase and are consistent with this version.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 8 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
from copy import copy
from dataclasses import dataclass
from typing import Optional

# imports
import pytest  # used for our unit tests
from pydantic_ai.usage import Usage

# unit tests

# --------------------------
# Basic Test Cases
# --------------------------

def test_add_zero_usages():
    # Both operands are default Usage (all zero/None)
    u1 = Usage()
    u2 = Usage()
    result = u1 + u2

















from copy import copy
from dataclasses import dataclass
from typing import Optional

# imports
import pytest  # used for our unit tests
from pydantic_ai.usage import Usage

# unit tests

# ----------------- BASIC TEST CASES -----------------









def test_add_edge_all_fields_none():
    # Both operands have all fields None/default except requests
    u1 = Usage()
    u2 = Usage()
    result = u1 + u2











def test_add_large_zero_and_large():
    # Add a zero Usage to a large Usage
    big = 10**9
    details = {f"k{i}": i for i in range(1000)}
    u1 = Usage()  # all fields default/None
    u2 = Usage(requests=big, request_tokens=big, response_tokens=big, total_tokens=big, details=details)
    result = u1 + u2





from pydantic_ai.usage import Usage

def test_Usage___add__():
    Usage.__add__(Usage(requests=0, request_tokens=None, response_tokens=0, total_tokens=None, details=None), Usage(requests=0, request_tokens=None, response_tokens=None, total_tokens=None, details={'': 0}))

To edit these changes git checkout codeflash/optimize-Usage.__add__-mddvpy23 and push.

Codeflash

REFINEMENT Here is an optimized version of your provided code.  
**Summary of speedups applied:**
- **Avoid repeated `getattr`/`setattr`:** Use direct attribute access since field names are statically known, avoiding attribute lookup overhead.
- **In `__add__`:** Avoid slow `copy(self)`. Use direct construction, which is both faster and more memory-efficient for your dataclass.
- **Details merging optimization:** Bulk update details using `collections.Counter` if available to minimize key-by-key dict overhead (but without importing new modules if not already present, as none are imported in the original).

All logic and return values remain **identical**.



### Key optimizations.
- **`incr`:**  
  - Uses local variables for self/other, and direct attribute access.
  - Merges details dict in-place if present; only copies when necessary.
- **`__add__`:**  
  - Avoids copy, just constructs a merged `Usage` directly, calculating all fields in one step.
  - For `details`, merges in minimal steps, using shallow `.copy()` only as needed.

This will notably reduce attribute lookup, dictionary calls, and avoid unnecessary copying for the common case. No external dependencies are used, and all comments are preserved unless a related section changed.

**Your `Usage.__repr__` and type annotations remain as in the reference codebase and are consistent with this version.**
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Jul 22, 2025
@codeflash-ai codeflash-ai bot requested a review from aseembits93 July 22, 2025 01:52
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants