Skip to content

Conversation

codeflash-ai[bot]
Copy link

@codeflash-ai codeflash-ai bot commented Oct 2, 2025

📄 5% (0.05x) speedup for _get_span_name in sentry_sdk/tracing_utils.py

⏱️ Runtime : 2.18 milliseconds 2.07 milliseconds (best of 100 runs)

📝 Explanation and details

The optimization achieves a 5% speedup by eliminating inefficient loops and reducing variable assignments. Here are the key changes:

1. Loop Elimination for AI_CHAT Template

  • Original: Used a for loop to iterate through ("model", "model_name") keys, calling kwargs.get() and isinstance() for each iteration
  • Optimized: Direct sequential checks for "model" first, then "model_name" only if needed
  • Why faster: Eliminates loop overhead and reduces function calls, especially when "model" is present (most common case)

2. Early Returns

  • Original: Used elif chains with a shared span_name variable that gets reassigned
  • Optimized: Each template branch returns immediately after computing the result
  • Why faster: Reduces variable assignments and eliminates the final return span_name lookup

3. Direct Value Validation

  • Original: Combined kwargs.get(key) and isinstance(kwargs[key], str) in loop
  • Optimized: Explicit checks with model is not None and isinstance(model, str)
  • Why faster: More predictable branching and cleaner type checking

Performance Benefits by Test Case:

  • Best gains (10-28%): Large kwargs dictionaries and cases with both model keys present, where loop elimination has maximum impact
  • Consistent gains (5-15%): Most standard AI_CHAT cases benefit from avoiding the loop
  • Minimal gains (1-3%): AI_AGENT and AI_TOOL cases see smaller improvements from early returns only

The optimization is particularly effective for AI_CHAT templates with large kwargs dictionaries, which are common in ML/AI tracing scenarios.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 4066 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
from enum import Enum
from typing import Any, Optional, Union

# imports
import pytest  # used for our unit tests
from sentry_sdk.tracing_utils import _get_span_name


class SPANTEMPLATE(Enum):
    AI_CHAT = "ai_chat"
    AI_AGENT = "ai_agent"
    AI_TOOL = "ai_tool"
from sentry_sdk.tracing_utils import _get_span_name

# ---------------------- UNIT TESTS ----------------------

# ----------- 1. Basic Test Cases -----------

def test_ai_chat_with_model():
    # Basic: AI_CHAT template with 'model' in kwargs
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model": "gpt-3"}); result = codeflash_output # 1.37μs -> 1.33μs (3.47% faster)

def test_ai_chat_with_model_name():
    # Basic: AI_CHAT template with 'model_name' in kwargs
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model_name": "gpt-4"}); result = codeflash_output # 1.03μs -> 1.05μs (1.90% slower)

def test_ai_chat_with_both_model_and_model_name():
    # Basic: AI_CHAT template with both keys, 'model' takes precedence
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model": "gpt-3", "model_name": "gpt-4"}); result = codeflash_output # 1.04μs -> 956ns (8.89% faster)

def test_ai_chat_without_model_keys():
    # Basic: AI_CHAT template with no model keys in kwargs
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"foo": "bar"}); result = codeflash_output # 1.04μs -> 934ns (11.6% faster)

def test_ai_chat_no_kwargs():
    # Basic: AI_CHAT template with kwargs=None
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", None); result = codeflash_output # 1.01μs -> 950ns (6.84% faster)

def test_ai_agent_basic():
    # Basic: AI_AGENT template, name is used
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, "my_agent", {}); result = codeflash_output # 1.06μs -> 947ns (11.5% faster)

def test_ai_tool_basic():
    # Basic: AI_TOOL template, name is used
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, "my_tool", {}); result = codeflash_output # 1.02μs -> 960ns (5.94% faster)

def test_unknown_template_returns_name():
    # Basic: Unknown template returns name unchanged
    codeflash_output = _get_span_name("unknown_template", "foo", {}); result = codeflash_output # 1.10μs -> 1.07μs (2.99% faster)

# ----------- 2. Edge Test Cases -----------

def test_ai_chat_model_is_not_string():
    # Edge: model value is not a string (should ignore and fallback to 'chat')
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model": 12345}); result = codeflash_output # 1.03μs -> 956ns (7.85% faster)

def test_ai_chat_model_name_is_not_string():
    # Edge: model_name value is not a string (should ignore and fallback to 'chat')
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model_name": ["gpt-4"]}); result = codeflash_output # 1.05μs -> 888ns (17.8% faster)

def test_ai_chat_model_is_empty_string():
    # Edge: model is empty string (should still use it)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model": ""}); result = codeflash_output # 1.04μs -> 921ns (12.9% faster)

def test_ai_chat_model_name_is_empty_string():
    # Edge: model_name is empty string, model missing
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model_name": ""}); result = codeflash_output # 985ns -> 945ns (4.23% faster)

def test_ai_chat_model_is_none():
    # Edge: model is None (should ignore and fallback to 'chat')
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"model": None}); result = codeflash_output # 1.05μs -> 982ns (6.92% faster)

def test_ai_chat_kwargs_is_empty_dict():
    # Edge: kwargs is empty dict (should fallback to 'chat')
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {}); result = codeflash_output # 1.06μs -> 878ns (20.7% faster)

def test_ai_agent_name_is_empty_string():
    # Edge: AI_AGENT with empty name
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, "", {}); result = codeflash_output # 1.05μs -> 989ns (6.37% faster)

def test_ai_tool_name_is_empty_string():
    # Edge: AI_TOOL with empty name
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, "", {}); result = codeflash_output # 1.02μs -> 895ns (14.5% faster)

def test_unknown_template_with_empty_name():
    # Edge: Unknown template with empty name
    codeflash_output = _get_span_name("unknown_template", "", {}); result = codeflash_output # 1.12μs -> 1.04μs (7.60% faster)

def test_template_as_string_equivalent():
    # Edge: template passed as string matching enum value
    codeflash_output = _get_span_name("ai_chat", "ignored", {"model": "gpt-3"}); result = codeflash_output # 1.78μs -> 1.43μs (24.9% faster)

def test_kwargs_has_extra_keys():
    # Edge: kwargs contains many unrelated keys
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"foo": "bar", "baz": 123, "model": "gpt-3"}); result = codeflash_output # 1.07μs -> 991ns (8.48% faster)

def test_model_key_case_sensitivity():
    # Edge: model key is wrong case, should not match
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"Model": "gpt-3"}); result = codeflash_output # 1.06μs -> 930ns (13.8% faster)

def test_model_name_key_case_sensitivity():
    # Edge: model_name key is wrong case, should not match
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", {"MODEL_NAME": "gpt-4"}); result = codeflash_output # 1.04μs -> 955ns (9.21% faster)

def test_kwargs_is_not_dict():
    # Edge: kwargs is not a dict (should be ignored safely)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", "notadict"); result = codeflash_output # 1.03μs -> 938ns (9.91% faster)

def test_kwargs_is_list():
    # Edge: kwargs is a list (should be ignored safely)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", ["model", "gpt-3"]); result = codeflash_output # 994ns -> 970ns (2.47% faster)

def test_kwargs_is_int():
    # Edge: kwargs is an int (should be ignored safely)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", 123); result = codeflash_output # 1.02μs -> 921ns (10.5% faster)

def test_name_is_special_characters():
    # Edge: name contains special characters
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, "@!#$_", {}); result = codeflash_output # 977ns -> 964ns (1.35% faster)

def test_name_is_long_string():
    # Edge: name is a very long string
    long_name = "a" * 1000
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, long_name, {}); result = codeflash_output # 1.01μs -> 890ns (13.7% faster)

# ----------- 3. Large Scale Test Cases -----------

def test_large_kwargs_dict():
    # Large: kwargs dict with 999 unrelated keys and one 'model'
    kwargs = {f"key{i}": f"value{i}" for i in range(999)}
    kwargs["model"] = "gpt-999"
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", kwargs); result = codeflash_output # 1.08μs -> 1.00μs (8.19% faster)

def test_large_kwargs_model_name():
    # Large: kwargs dict with 999 unrelated keys and one 'model_name'
    kwargs = {f"key{i}": f"value{i}" for i in range(999)}
    kwargs["model_name"] = "gpt-999"
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", kwargs); result = codeflash_output # 1.06μs -> 969ns (9.91% faster)

def test_large_name_string():
    # Large: name is 1000 characters
    long_name = "x" * 1000
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, long_name, {}); result = codeflash_output # 1.00μs -> 978ns (2.56% faster)

def test_many_calls_performance():
    # Large: Call the function 1000 times with different names
    for i in range(1000):
        name = f"agent_{i}"
        codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, name, {}); result = codeflash_output # 518μs -> 508μs (1.93% faster)

def test_large_kwargs_no_model_or_model_name():
    # Large: kwargs dict with 1000 unrelated keys, no model/model_name
    kwargs = {f"key{i}": f"value{i}" for i in range(1000)}
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "ignored", kwargs); result = codeflash_output # 1.19μs -> 1.08μs (9.91% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from typing import Any, Optional, Union

# imports
import pytest  # used for our unit tests
from sentry_sdk.tracing_utils import _get_span_name


# --- Mocking SPANTEMPLATE for test purposes ---
# We avoid external dependencies for unit tests
class SPANTEMPLATE:
    AI_CHAT = "ai_chat"
    AI_AGENT = "ai_agent"
    AI_TOOL = "ai_tool"
from sentry_sdk.tracing_utils import _get_span_name

# ------------------ UNIT TESTS ------------------

# Basic Test Cases

def test_ai_chat_with_model():
    # Test AI_CHAT with 'model' in kwargs
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": "gpt-4"}) # 1.76μs -> 1.48μs (18.3% faster)

def test_ai_chat_with_model_name():
    # Test AI_CHAT with 'model_name' in kwargs
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model_name": "gpt-3.5"}) # 1.81μs -> 1.57μs (15.3% faster)

def test_ai_chat_with_both_model_and_model_name():
    # If both are present, 'model' takes precedence
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": "gpt-4", "model_name": "gpt-3.5"}) # 1.64μs -> 1.35μs (21.5% faster)

def test_ai_chat_without_model():
    # Test AI_CHAT with no model info
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {}) # 974ns -> 961ns (1.35% faster)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant") # 600ns -> 588ns (2.04% faster)

def test_ai_agent_basic():
    # Test AI_AGENT basic case
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, "agent_foo") # 1.20μs -> 1.19μs (1.09% faster)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, "my_agent", {"model": "gpt-4"}) # 618ns -> 631ns (2.06% slower)

def test_ai_tool_basic():
    # Test AI_TOOL basic case
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, "tool_bar") # 1.27μs -> 1.28μs (0.235% slower)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, "my_tool", {"model": "gpt-4"}) # 856ns -> 852ns (0.469% faster)

def test_other_template_returns_name():
    # Test unknown template returns name unchanged
    codeflash_output = _get_span_name("unknown", "foobar") # 1.04μs -> 1.06μs (1.52% slower)
    codeflash_output = _get_span_name(None, "baz") # 767ns -> 771ns (0.519% slower)

# Edge Test Cases

def test_ai_chat_model_not_str():
    # Model present but not a string
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": 123}) # 1.75μs -> 1.53μs (14.4% faster)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model_name": ["gpt-4"]}) # 967ns -> 864ns (11.9% faster)

def test_ai_chat_model_empty_string():
    # Model present but empty string
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": ""}) # 1.37μs -> 1.21μs (12.6% faster)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model_name": ""}) # 690ns -> 766ns (9.92% slower)

def test_ai_chat_model_none():
    # Model present but None
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": None}) # 1.25μs -> 1.22μs (2.96% faster)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model_name": None}) # 719ns -> 727ns (1.10% slower)

def test_ai_chat_kwargs_with_extra_keys():
    # kwargs has unrelated keys
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"foo": "bar"}) # 1.15μs -> 1.14μs (0.965% faster)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": "gpt-4", "foo": "bar"}) # 1.15μs -> 905ns (27.4% faster)

def test_ai_agent_name_empty():
    # AI_AGENT with empty name
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, "") # 1.20μs -> 1.14μs (5.72% faster)

def test_ai_tool_name_empty():
    # AI_TOOL with empty name
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, "") # 1.36μs -> 1.23μs (10.5% faster)

def test_other_template_name_empty():
    # Unknown template with empty name
    codeflash_output = _get_span_name("unknown", "") # 1.12μs -> 1.01μs (11.0% faster)

def test_kwargs_is_not_dict():
    # kwargs is not a dict
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", [])
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", "notadict")

def test_kwargs_is_none():
    # kwargs is None
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", None) # 1.50μs -> 1.71μs (12.3% slower)

def test_template_is_none():
    # template is None
    codeflash_output = _get_span_name(None, "foo", {"model": "gpt-4"}) # 1.37μs -> 1.25μs (9.35% faster)

def test_name_is_none():
    # name is None
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, None) # 1.53μs -> 1.45μs (5.31% faster)
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, None) # 930ns -> 880ns (5.68% faster)
    codeflash_output = _get_span_name("unknown", None) # 662ns -> 650ns (1.85% faster)

def test_kwargs_with_model_and_model_name_non_str():
    # Both keys present, but neither is a string
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": 123, "model_name": 456}) # 1.78μs -> 1.54μs (15.1% faster)

# Large Scale Test Cases

def test_ai_chat_large_kwargs():
    # Large kwargs dict with model at the end
    kwargs = {f"key{i}": f"value{i}" for i in range(998)}
    kwargs["model"] = "gpt-large"
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", kwargs) # 1.92μs -> 1.50μs (28.6% faster)

def test_ai_chat_large_kwargs_model_name():
    # Large kwargs dict with model_name at the end
    kwargs = {f"key{i}": f"value{i}" for i in range(998)}
    kwargs["model_name"] = "gpt-huge"
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", kwargs) # 1.99μs -> 1.59μs (25.2% faster)

def test_ai_chat_large_kwargs_no_model():
    # Large kwargs dict with no model or model_name
    kwargs = {f"key{i}": f"value{i}" for i in range(1000)}
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", kwargs) # 1.56μs -> 1.34μs (16.0% faster)

def test_ai_agent_large_name():
    # Very long agent name
    long_name = "agent_" + "x" * 900
    expected = f"invoke_agent {long_name}"
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, long_name) # 1.32μs -> 1.26μs (4.60% faster)

def test_ai_tool_large_name():
    # Very long tool name
    long_name = "tool_" + "y" * 900
    expected = f"execute_tool {long_name}"
    codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, long_name) # 1.49μs -> 1.32μs (12.8% faster)

def test_other_template_large_name():
    # Unknown template with very long name
    long_name = "foobar_" + "z" * 900
    codeflash_output = _get_span_name("unknown", long_name) # 1.10μs -> 1.03μs (7.60% faster)

def test_ai_chat_many_invocations():
    # Test performance with many invocations (not exceeding 1000)
    for i in range(1000):
        model = f"model_{i}"
        codeflash_output = _get_span_name(SPANTEMPLATE.AI_CHAT, "irrelevant", {"model": model}) # 548μs -> 479μs (14.4% faster)

def test_ai_agent_many_invocations():
    # Test performance with many agent names
    for i in range(1000):
        name = f"agent_{i}"
        codeflash_output = _get_span_name(SPANTEMPLATE.AI_AGENT, name) # 472μs -> 455μs (3.64% faster)

def test_ai_tool_many_invocations():
    # Test performance with many tool names
    for i in range(1000):
        name = f"tool_{i}"
        codeflash_output = _get_span_name(SPANTEMPLATE.AI_TOOL, name) # 568μs -> 557μs (1.89% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-_get_span_name-mg9nnwxm and push.

Codeflash

The optimization achieves a **5% speedup** by eliminating inefficient loops and reducing variable assignments. Here are the key changes:

**1. Loop Elimination for AI_CHAT Template**
- **Original**: Used a `for` loop to iterate through `("model", "model_name")` keys, calling `kwargs.get()` and `isinstance()` for each iteration
- **Optimized**: Direct sequential checks for "model" first, then "model_name" only if needed
- **Why faster**: Eliminates loop overhead and reduces function calls, especially when "model" is present (most common case)

**2. Early Returns**
- **Original**: Used `elif` chains with a shared `span_name` variable that gets reassigned
- **Optimized**: Each template branch returns immediately after computing the result
- **Why faster**: Reduces variable assignments and eliminates the final `return span_name` lookup

**3. Direct Value Validation**
- **Original**: Combined `kwargs.get(key) and isinstance(kwargs[key], str)` in loop
- **Optimized**: Explicit checks with `model is not None and isinstance(model, str)`
- **Why faster**: More predictable branching and cleaner type checking

**Performance Benefits by Test Case:**
- **Best gains** (10-28%): Large kwargs dictionaries and cases with both model keys present, where loop elimination has maximum impact
- **Consistent gains** (5-15%): Most standard AI_CHAT cases benefit from avoiding the loop
- **Minimal gains** (1-3%): AI_AGENT and AI_TOOL cases see smaller improvements from early returns only

The optimization is particularly effective for AI_CHAT templates with large kwargs dictionaries, which are common in ML/AI tracing scenarios.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 October 2, 2025 16:54
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Oct 2, 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants