Skip to content

Conversation

@codeflash-ai
Copy link

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

📄 6% (0.06x) speedup for set_tags in sentry_sdk/api.py

⏱️ Runtime : 29.9 microseconds 28.1 microseconds (best of 54 runs)

📝 Explanation and details

The optimization eliminates a redundant function call by directly calling Scope.get_isolation_scope() instead of going through the intermediate get_isolation_scope() wrapper function in set_tags().

Key Change:

  • Original: return get_isolation_scope().set_tags(tags) (calls wrapper function first)
  • Optimized: scope = Scope.get_isolation_scope() followed by scope.set_tags(tags) (direct call)

Why It's Faster:
The original version creates an unnecessary function call overhead. When set_tags() calls get_isolation_scope(), Python has to:

  1. Execute the wrapper function get_isolation_scope()
  2. Which then calls Scope.get_isolation_scope()
  3. Return the scope and immediately call set_tags() on it

The optimized version eliminates step 1 by calling Scope.get_isolation_scope() directly, reducing the call stack depth and function call overhead.

Performance Impact:
The line profiler shows the optimization reduces total time in set_tags() from 1.74ms to 1.55ms. The 6% speedup is consistent across test cases, with the annotated test showing improvement from 14.3μs to 13.5μs.

This optimization is particularly effective for high-frequency logging scenarios where set_tags() is called repeatedly, as it eliminates function call overhead on every invocation.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 18 Passed
🌀 Generated Regression Tests 23 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
⚙️ Existing Unit Tests and Runtime
Test File::Test Function Original ⏱️ Optimized ⏱️ Speedup
test_api.py::test_set_tags 15.6μs 14.6μs 6.60%✅
🌀 Generated Regression Tests and Runtime
from collections.abc import Mapping
# function to test
from copy import copy, deepcopy

# imports
import pytest  # used for our unit tests
from sentry_sdk.api import set_tags


class ContextVar:
    def __init__(self, name, default=None):
        self.name = name
        self.value = default

    def get(self):
        return self.value

    def set(self, value):
        self.value = value

def scopemethod(fn):
    # Dummy decorator for compatibility
    return fn

# Holds data for the active request.
_isolation_scope = ContextVar("isolation_scope", default=None)
from sentry_sdk.api import set_tags


# Helper to reset isolation scope between tests
def reset_scope():
    _isolation_scope.set(None)

# unit tests

# -- BASIC TEST CASES --



def test_set_tags_overwrite_tags():
    """Test that set_tags overwrites previous tags."""
    reset_scope()
    set_tags({"x": "y"})
    set_tags({"a": "b"})
    scope = get_isolation_scope()

def test_set_tags_empty_mapping():
    """Test setting tags to an empty mapping clears tags."""
    reset_scope()
    set_tags({"foo": "bar"})
    set_tags({})
    scope = get_isolation_scope()







def test_set_tags_with_none_mapping():
    """Test that passing None as tags raises TypeError."""
    reset_scope()
    with pytest.raises(TypeError):
        set_tags(None) # 14.3μs -> 13.5μs (6.34% faster)


def test_set_tags_overwrite_with_same_keys():
    """Test that overwriting tags with same keys updates values."""
    reset_scope()
    set_tags({"x": 1})
    set_tags({"x": 2})
    scope = get_isolation_scope()




def test_set_tags_large_and_overwrite():
    """Test overwriting large tags with another large set."""
    reset_scope()
    tags1 = {f"k{i}": i for i in range(500)}
    tags2 = {f"z{i}": -i for i in range(500)}
    set_tags(tags1)
    set_tags(tags2)
    scope = get_isolation_scope()



#------------------------------------------------
from collections.abc import Mapping
# function to test
from copy import copy, deepcopy

# imports
import pytest  # used for our unit tests
from sentry_sdk.api import set_tags

# --- BASIC TEST CASES ---



def test_set_tags_basic_overwrite_tag():
    # Test overwriting an existing tag
    set_tags({"x": 1})
    set_tags({"x": 2})
    scope = get_isolation_scope()

def test_set_tags_basic_additional_tags():
    # Test adding new tags on top of existing ones
    set_tags({"a": "A"})
    set_tags({"b": "B"})
    scope = get_isolation_scope()

def test_set_tags_basic_empty_dict():
    # Setting empty dict should not change tags
    set_tags({"foo": "bar"})
    set_tags({})
    scope = get_isolation_scope()

# --- EDGE TEST CASES ---









def test_set_tags_edge_update_existing_tags():
    # Update existing tags with new values
    set_tags({"a": 1, "b": 2})
    set_tags({"a": 3, "c": 4})
    scope = get_isolation_scope()






def test_set_tags_edge_tags_are_merged():
    # set_tags merges tags, does not replace
    set_tags({"a": 1})
    set_tags({"b": 2})
    scope = get_isolation_scope()

# --- LARGE SCALE TEST CASES ---


def test_set_tags_large_update_many_tags():
    # Update a large number of tags in two steps
    tags1 = {f"key{i}": i for i in range(500)}
    tags2 = {f"key{i}": i*2 for i in range(500, 1000)}
    set_tags(tags1)
    set_tags(tags2)
    scope = get_isolation_scope()
    expected = tags1.copy()
    expected.update(tags2)

def test_set_tags_large_overwrite_many_tags():
    # Overwrite many tags
    tags1 = {f"key{i}": i for i in range(1000)}
    tags2 = {f"key{i}": -i for i in range(1000)}
    set_tags(tags1)
    set_tags(tags2)
    scope = get_isolation_scope()

To edit these changes git checkout codeflash/optimize-set_tags-mg95ey0w and push.

Codeflash

The optimization eliminates a redundant function call by directly calling `Scope.get_isolation_scope()` instead of going through the intermediate `get_isolation_scope()` wrapper function in `set_tags()`.

**Key Change:**
- Original: `return get_isolation_scope().set_tags(tags)` (calls wrapper function first)
- Optimized: `scope = Scope.get_isolation_scope()` followed by `scope.set_tags(tags)` (direct call)

**Why It's Faster:**
The original version creates an unnecessary function call overhead. When `set_tags()` calls `get_isolation_scope()`, Python has to:
1. Execute the wrapper function `get_isolation_scope()`  
2. Which then calls `Scope.get_isolation_scope()`
3. Return the scope and immediately call `set_tags()` on it

The optimized version eliminates step 1 by calling `Scope.get_isolation_scope()` directly, reducing the call stack depth and function call overhead.

**Performance Impact:**
The line profiler shows the optimization reduces total time in `set_tags()` from 1.74ms to 1.55ms. The 6% speedup is consistent across test cases, with the annotated test showing improvement from 14.3μs to 13.5μs.

This optimization is particularly effective for high-frequency logging scenarios where `set_tags()` is called repeatedly, as it eliminates function call overhead on every invocation.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 October 2, 2025 08:23
@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.

1 participant