Skip to content

⚡️ Speed up method PropertyValueList._saved_copy by 47%#162

Open
codeflash-ai[bot] wants to merge 1 commit into
branch-3.9from
codeflash/optimize-PropertyValueList._saved_copy-mhwxy5n1
Open

⚡️ Speed up method PropertyValueList._saved_copy by 47%#162
codeflash-ai[bot] wants to merge 1 commit into
branch-3.9from
codeflash/optimize-PropertyValueList._saved_copy-mhwxy5n1

Conversation

@codeflash-ai
Copy link
Copy Markdown

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

📄 47% (0.47x) speedup for PropertyValueList._saved_copy in src/bokeh/core/property/wrappers.py

⏱️ Runtime : 59.2 microseconds 40.2 microseconds (best of 250 runs)

📝 Explanation and details

The optimization replaces list(self) with self.copy() in the _saved_copy method, achieving a 47% speedup by leveraging Python's built-in list copying mechanism more efficiently.

Key optimization:

  • Changed return list(self) to return self.copy()
  • self.copy() is a direct method call on the list object that bypasses the overhead of the list() constructor
  • The list() constructor has to perform argument validation, type checking, and generic sequence processing, while copy() is optimized specifically for list shallow copying

Performance benefits:

  • Small lists (1-5 elements): 13-36% faster, reducing per-hit time from ~1460ns to ~1064ns
  • Large lists (1000 elements): 55-78% faster, with the most dramatic improvements on lists with repeated elements or simple types
  • Consistent speedup across all test cases, from simple integers to complex nested structures

Why this works:
Since PropertyValueList inherits from list[T], it gets the built-in copy() method which directly calls the C-level list copying implementation. This avoids the Python-level overhead of list() constructor's generic iterable processing, argument parsing, and temporary object creation.

Impact on workloads:
This optimization is particularly beneficial for:

  • Frequent property value copying in Bokeh's property system
  • Large lists or lists with many elements
  • Any scenario where _saved_copy is called repeatedly, as the per-call overhead reduction compounds significantly

The optimization maintains identical shallow copy semantics - both approaches create independent list objects that share references to the same nested objects, ensuring no behavioral changes.

Correctness verification report:

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

# imports
import pytest
from bokeh.core.property.wrappers import PropertyValueList

T = TypeVar("T")

class PropertyValueContainer:
    _owners: set

    def __init__(self, *args, **kwargs) -> None:
        self._owners = set()
        super().__init__(*args, **kwargs)
from bokeh.core.property.wrappers import PropertyValueList

# unit tests

class TestPropertyValueListSavedCopy:
    # --- Basic Test Cases ---

    def test_empty_list(self):
        # Test with an empty PropertyValueList
        pvlist = PropertyValueList()
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 409ns -> 360ns (13.6% faster)

    def test_single_element_list(self):
        # Test with a single element
        pvlist = PropertyValueList([42])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 409ns -> 320ns (27.8% faster)

    def test_multiple_elements_list(self):
        # Test with multiple elements
        pvlist = PropertyValueList([1, 2, 3, 4, 5])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 403ns -> 340ns (18.5% faster)
        # Changing the copy should not affect the original
        result.append(6)

    def test_copy_is_independent(self):
        # Modifying the copy does not affect the original
        pvlist = PropertyValueList([10, 20])
        codeflash_output = pvlist._saved_copy(); copy = codeflash_output # 408ns -> 342ns (19.3% faster)
        copy[0] = 99

    # --- Edge Test Cases ---

    def test_list_with_none(self):
        # List containing None values
        pvlist = PropertyValueList([None, None])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 392ns -> 307ns (27.7% faster)

    def test_list_with_mixed_types(self):
        # List containing mixed types
        pvlist = PropertyValueList([1, "a", 3.14, None, True])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 410ns -> 326ns (25.8% faster)

    def test_list_with_nested_lists(self):
        # List containing nested lists
        pvlist = PropertyValueList([[1, 2], [3, 4]])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 395ns -> 329ns (20.1% faster)
        # The copy is shallow
        result[0].append(99)

    def test_list_with_custom_objects(self):
        # List containing custom objects
        class Dummy:
            def __init__(self, x): self.x = x
            def __eq__(self, other): return isinstance(other, Dummy) and self.x == other.x

        d1, d2 = Dummy(1), Dummy(2)
        pvlist = PropertyValueList([d1, d2])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 431ns -> 337ns (27.9% faster)
        # Changing an attribute of an object in the copy affects the original (shallow copy)
        result[0].x = 42

    def test_list_with_tuple_input(self):
        # PropertyValueList can be constructed from a tuple
        pvlist = PropertyValueList((7, 8, 9))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 423ns -> 337ns (25.5% faster)

    def test_list_with_generator_input(self):
        # PropertyValueList can be constructed from a generator
        pvlist = PropertyValueList(x for x in range(3))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 416ns -> 320ns (30.0% faster)

    def test_list_with_large_integers(self):
        # List with large integer values
        large_int = 10**18
        pvlist = PropertyValueList([large_int, -large_int])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 407ns -> 330ns (23.3% faster)

    # --- Large Scale Test Cases ---

    def test_large_list(self):
        # Large list of 1000 elements
        pvlist = PropertyValueList(range(1000))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.48μs -> 1.50μs (65.4% faster)
        # Changing the copy should not affect the original
        result[0] = -1

    def test_large_list_with_nested_structures(self):
        # Large list of nested lists
        pvlist = PropertyValueList([[i] for i in range(1000)])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.56μs -> 1.65μs (55.5% faster)
        # Shallow copy: nested lists are shared
        result[0].append("x")

    def test_large_list_with_mixed_types(self):
        # Large list with mixed types
        mixed = [i if i % 3 == 0 else str(i) if i % 3 == 1 else None for i in range(1000)]
        pvlist = PropertyValueList(mixed)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.37μs -> 1.44μs (65.1% faster)

    # --- Edge Case: Immutability of Output ---

    def test_output_is_plain_list(self):
        # Output of _saved_copy should be a plain list, not PropertyValueList
        pvlist = PropertyValueList([1, 2, 3])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 422ns -> 321ns (31.5% faster)

    # --- Edge Case: Input is already a list ---

    def test_input_is_list(self):
        # Input is a standard list
        original = [1, 2, 3]
        pvlist = PropertyValueList(original)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 427ns -> 315ns (35.6% faster)
        # Changing the copy does not affect the original
        result[0] = 99

    # --- Edge Case: Input is empty tuple ---

    def test_input_is_empty_tuple(self):
        pvlist = PropertyValueList(())
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 422ns -> 312ns (35.3% faster)

    # --- Edge Case: Input is string (should treat as iterable of chars) ---

    def test_input_is_string(self):
        pvlist = PropertyValueList("abc")
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 433ns -> 326ns (32.8% faster)

    # --- Edge Case: Input is bytes (should treat as iterable of ints) ---

    def test_input_is_bytes(self):
        pvlist = PropertyValueList(b"abc")
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 419ns -> 338ns (24.0% faster)

    # --- Edge Case: Input is range object ---

    def test_input_is_range(self):
        pvlist = PropertyValueList(range(5))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 430ns -> 333ns (29.1% faster)

    # --- Edge Case: Input is reversed list ---

    def test_input_is_reversed_list(self):
        pvlist = PropertyValueList(reversed([1, 2, 3]))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 416ns -> 312ns (33.3% faster)

    # --- Edge Case: Input is enumerate object ---

    def test_input_is_enumerate(self):
        pvlist = PropertyValueList(enumerate(["a", "b", "c"]))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 403ns -> 314ns (28.3% faster)

    # --- Edge Case: Input is zip object ---

    def test_input_is_zip(self):
        pvlist = PropertyValueList(zip([1, 2], ["a", "b"]))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 394ns -> 328ns (20.1% faster)

    # --- Edge Case: Input is map object ---

    def test_input_is_map(self):
        pvlist = PropertyValueList(map(str, [1, 2, 3]))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 403ns -> 324ns (24.4% faster)

    # --- Edge Case: Input is filter object ---

    def test_input_is_filter(self):
        pvlist = PropertyValueList(filter(lambda x: x % 2 == 0, range(5)))
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 393ns -> 319ns (23.2% faster)

    # --- Edge Case: Input is list of booleans ---

    def test_list_of_booleans(self):
        pvlist = PropertyValueList([True, False, True])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 367ns -> 327ns (12.2% faster)

    # --- Edge Case: Input is list of empty lists ---

    def test_list_of_empty_lists(self):
        pvlist = PropertyValueList([[], [], []])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 383ns -> 316ns (21.2% faster)

    # --- Edge Case: Input is list of dicts ---

    def test_list_of_dicts(self):
        pvlist = PropertyValueList([{"a": 1}, {"b": 2}])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 414ns -> 352ns (17.6% faster)
        # Shallow copy: dicts are shared
        result[0]["z"] = 42

    # --- Edge Case: Input is list with repeated elements ---

    def test_list_with_repeated_elements(self):
        obj = []
        pvlist = PropertyValueList([obj, obj, obj])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 422ns -> 334ns (26.3% faster)
        result[0].append(1)

    # --- Edge Case: Input is list with unicode strings ---

    def test_list_with_unicode_strings(self):
        pvlist = PropertyValueList(["α", "β", "γ"])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 404ns -> 319ns (26.6% faster)

    # --- Edge Case: Input is list with negative numbers ---

    def test_list_with_negative_numbers(self):
        pvlist = PropertyValueList([-1, -100, -999])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 409ns -> 315ns (29.8% faster)

    # --- Edge Case: Input is list with floats and ints ---

    def test_list_with_floats_and_ints(self):
        pvlist = PropertyValueList([1, 2.0, 3])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 403ns -> 310ns (30.0% faster)

    # --- Edge Case: Input is list with complex numbers ---

    def test_list_with_complex_numbers(self):
        pvlist = PropertyValueList([1+2j, 3-4j])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 426ns -> 312ns (36.5% faster)

    # --- Edge Case: Input is list with very large and very small floats ---

    def test_list_with_large_and_small_floats(self):
        pvlist = PropertyValueList([1e308, 1e-308])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 411ns -> 337ns (22.0% faster)

    # --- Edge Case: Input is list with empty string ---

    def test_list_with_empty_string(self):
        pvlist = PropertyValueList([""])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 396ns -> 316ns (25.3% faster)

    # --- Edge Case: Input is list with all None ---

    def test_list_with_all_none(self):
        pvlist = PropertyValueList([None]*10)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 460ns -> 316ns (45.6% faster)

    # --- Edge Case: Input is list with all True ---

    def test_list_with_all_true(self):
        pvlist = PropertyValueList([True]*10)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 416ns -> 339ns (22.7% faster)

    # --- Edge Case: Input is list with all False ---

    def test_list_with_all_false(self):
        pvlist = PropertyValueList([False]*10)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 400ns -> 339ns (18.0% faster)

    # --- Edge Case: Input is list with all zeros ---

    def test_list_with_all_zeros(self):
        pvlist = PropertyValueList([0]*10)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 430ns -> 343ns (25.4% faster)

    # --- Edge Case: Input is list with all empty dicts ---

    def test_list_with_all_empty_dicts(self):
        pvlist = PropertyValueList([{}]*10)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 392ns -> 327ns (19.9% faster)

    # --- Edge Case: Input is list with all empty sets ---

    def test_list_with_all_empty_sets(self):
        pvlist = PropertyValueList([set()]*10)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 417ns -> 312ns (33.7% faster)

    # --- Large Scale: List with 1000 None values ---

    def test_large_list_of_none(self):
        pvlist = PropertyValueList([None]*1000)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.01μs -> 1.21μs (66.2% faster)

    # --- Large Scale: List with 1000 custom objects ---

    def test_large_list_of_custom_objects(self):
        class Dummy:
            def __init__(self, x): self.x = x
            def __eq__(self, other): return isinstance(other, Dummy) and self.x == other.x

        objs = [Dummy(i) for i in range(1000)]
        pvlist = PropertyValueList(objs)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.69μs -> 1.70μs (58.2% faster)
        # Shallow copy: change attribute in copy, original is affected
        result[0].x = -1

    # --- Large Scale: List with 1000 nested lists ---

    def test_large_list_of_nested_lists(self):
        nested = [[i] for i in range(1000)]
        pvlist = PropertyValueList(nested)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.56μs -> 1.65μs (55.0% faster)
        result[1].append(9999)

    # --- Large Scale: List with 1000 repeated elements ---

    def test_large_list_with_repeated_elements(self):
        obj = {"x": 1}
        pvlist = PropertyValueList([obj]*1000)
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.06μs -> 1.16μs (77.7% faster)
        result[100].update({"y": 2})

    # --- Large Scale: List with 1000 alternating types ---

    def test_large_list_with_alternating_types(self):
        pvlist = PropertyValueList([i if i % 2 == 0 else str(i) for i in range(1000)])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.35μs -> 1.44μs (63.3% faster)

    # --- Large Scale: List with 1000 floats ---

    def test_large_list_with_floats(self):
        pvlist = PropertyValueList([float(i) for i in range(1000)])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.26μs -> 1.35μs (66.9% faster)

    # --- Large Scale: List with 1000 strings ---

    def test_large_list_with_strings(self):
        pvlist = PropertyValueList([str(i) for i in range(1000)])
        codeflash_output = pvlist._saved_copy(); result = codeflash_output # 2.49μs -> 1.50μs (66.2% 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, TypeVar

# imports
import pytest
from bokeh.core.property.wrappers import PropertyValueList

T = TypeVar("T")

class PropertyValueContainer:
    _owners: set

    def __init__(self, *args, **kwargs) -> None:
        self._owners = set()
        super().__init__(*args, **kwargs)
from bokeh.core.property.wrappers import PropertyValueList

# unit tests

# --- Basic Test Cases ---

def test_saved_copy_basic_ints():
    # Test with a simple list of integers
    pvl = PropertyValueList([1, 2, 3])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 496ns -> 369ns (34.4% faster)

def test_saved_copy_basic_strings():
    # Test with a list of strings
    pvl = PropertyValueList(['a', 'b', 'c'])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 453ns -> 367ns (23.4% faster)

def test_saved_copy_basic_empty():
    # Test with an empty list
    pvl = PropertyValueList([])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 438ns -> 350ns (25.1% faster)

def test_saved_copy_basic_tuple_input():
    # Test initializing with a tuple
    pvl = PropertyValueList((10, 20))
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 383ns -> 346ns (10.7% faster)

def test_saved_copy_basic_mutation_independence():
    # Test that the copy is independent of the original
    pvl = PropertyValueList([1, 2, 3])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 417ns -> 351ns (18.8% faster)
    copy.append(4)

# --- Edge Test Cases ---

def test_saved_copy_nested_lists():
    # Test with nested lists
    pvl = PropertyValueList([[1, 2], [3, 4]])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 433ns -> 344ns (25.9% faster)
    # Mutating a nested list should affect both, since it's a shallow copy
    copy[0].append(99)

def test_saved_copy_various_types():
    # Test with mixed types
    class Dummy: pass
    pvl = PropertyValueList([None, 3.14, "hi", Dummy()])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 444ns -> 353ns (25.8% faster)

def test_saved_copy_single_element():
    # Test with a single element
    pvl = PropertyValueList([42])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 426ns -> 337ns (26.4% faster)

def test_saved_copy_mutation_after_copy():
    # Test that mutating the original after copying does not affect the copy
    pvl = PropertyValueList([1, 2, 3])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 435ns -> 358ns (21.5% faster)
    pvl.append(4)

def test_saved_copy_mutation_before_copy():
    # Test that mutating the original before copying reflects in the copy
    pvl = PropertyValueList([1, 2])
    pvl += [3, 4]
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 379ns -> 301ns (25.9% faster)

def test_saved_copy_with_custom_objects():
    # Test with custom objects
    class Foo:
        def __init__(self, val): self.val = val
        def __eq__(self, other): return isinstance(other, Foo) and self.val == other.val
    objs = [Foo(1), Foo(2)]
    pvl = PropertyValueList(objs)
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 436ns -> 316ns (38.0% faster)

def test_saved_copy_with_unhashable():
    # Test with unhashable objects (e.g., dicts)
    pvl = PropertyValueList([{"a": 1}, {"b": 2}])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 417ns -> 335ns (24.5% faster)
    copy[0]["c"] = 3

def test_saved_copy_with_generator_input():
    # Test initializing with a generator
    pvl = PropertyValueList(x for x in range(3))
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 438ns -> 338ns (29.6% faster)

def test_saved_copy_with_range_input():
    # Test initializing with a range
    pvl = PropertyValueList(range(5))
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 407ns -> 325ns (25.2% faster)

# --- Large Scale Test Cases ---

def test_saved_copy_large_list():
    # Test with a large list
    large = list(range(1000))
    pvl = PropertyValueList(large)
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 2.43μs -> 1.44μs (68.5% faster)
    # Check that modifying the copy does not affect the original
    copy[0] = -1

def test_saved_copy_large_nested_list():
    # Test with a large nested list (shallow copy)
    nested = [[i] for i in range(1000)]
    pvl = PropertyValueList(nested)
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 2.65μs -> 1.59μs (66.4% faster)
    copy[0].append("x")

def test_saved_copy_large_strings():
    # Test with a large list of strings
    strings = [str(i) for i in range(1000)]
    pvl = PropertyValueList(strings)
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 2.60μs -> 1.60μs (62.3% faster)

def test_saved_copy_large_mutation_independence():
    # Check independence for large list
    large = list(range(1000))
    pvl = PropertyValueList(large)
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 2.36μs -> 1.38μs (71.4% faster)
    copy.extend([1001, 1002])

def test_saved_copy_performance():
    # Performance: Should not take excessive time for 1000 elements
    import time
    pvl = PropertyValueList(range(1000))
    start = time.time()
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 2.40μs -> 1.36μs (75.7% faster)
    end = time.time()

# --- Miscellaneous/Regression Tests ---

def test_saved_copy_does_not_modify_original():
    # Regression: _saved_copy must not modify the original
    pvl = PropertyValueList([1, 2, 3])
    before = pvl[:]
    codeflash_output = pvl._saved_copy(); _ = codeflash_output # 454ns -> 324ns (40.1% faster)

def test_saved_copy_returns_new_object():
    # Regression: The returned object must not be the same as the original
    pvl = PropertyValueList([1, 2, 3])
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 426ns -> 340ns (25.3% faster)

def test_saved_copy_with_propertyvaluelist_input():
    # Regression: If input is already a PropertyValueList, copy should be a plain list
    orig = PropertyValueList([1, 2, 3])
    pvl = PropertyValueList(orig)
    codeflash_output = pvl._saved_copy(); copy = codeflash_output # 359ns -> 329ns (9.12% 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-PropertyValueList._saved_copy-mhwxy5n1 and push.

Codeflash Static Badge

The optimization replaces `list(self)` with `self.copy()` in the `_saved_copy` method, achieving a **47% speedup** by leveraging Python's built-in list copying mechanism more efficiently.

**Key optimization:**
- Changed `return list(self)` to `return self.copy()`
- `self.copy()` is a direct method call on the list object that bypasses the overhead of the `list()` constructor
- The `list()` constructor has to perform argument validation, type checking, and generic sequence processing, while `copy()` is optimized specifically for list shallow copying

**Performance benefits:**
- **Small lists (1-5 elements)**: 13-36% faster, reducing per-hit time from ~1460ns to ~1064ns
- **Large lists (1000 elements)**: 55-78% faster, with the most dramatic improvements on lists with repeated elements or simple types
- Consistent speedup across all test cases, from simple integers to complex nested structures

**Why this works:**
Since `PropertyValueList` inherits from `list[T]`, it gets the built-in `copy()` method which directly calls the C-level list copying implementation. This avoids the Python-level overhead of `list()` constructor's generic iterable processing, argument parsing, and temporary object creation.

**Impact on workloads:**
This optimization is particularly beneficial for:
- Frequent property value copying in Bokeh's property system
- Large lists or lists with many elements
- Any scenario where `_saved_copy` is called repeatedly, as the per-call overhead reduction compounds significantly

The optimization maintains identical shallow copy semantics - both approaches create independent list objects that share references to the same nested objects, ensuring no behavioral changes.
@codeflash-ai codeflash-ai Bot requested a review from mashraf-222 November 13, 2025 04:40
@codeflash-ai codeflash-ai Bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Nov 13, 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: High Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants