langflow icon indicating copy to clipboard operation
langflow copied to clipboard

⚡️ Speed up function `set_multiple_field_advanced` by 14% in PR #7756 (`codeflash/optimize-pr7755-2025-04-23T07.14.50`)

Open codeflash-ai[bot] opened this issue 7 months ago • 0 comments

⚡️ This pull request contains optimizations for PR #7756

If you approve this dependent PR, these changes will be merged into the original PR branch codeflash/optimize-pr7755-2025-04-23T07.14.50.

This PR will be automatically closed if the original PR is merged.


📄 14% (0.14x) speedup for set_multiple_field_advanced in src/backend/base/langflow/utils/component_utils.py

⏱️ Runtime : 1.20 millisecond 1.06 millisecond (best of 106 runs)

📝 Explanation and details

To optimize the runtime and memory requirements, here are a few changes we can make.

  • Avoid reassigning build_config inside the loops. Updating the build_config directly will suffice since build_config is mutable and the changes will persist.
  • Instead of making repetitive function calls, perform the logic directly within the set_multiple_field_advanced function to minimize overhead.
  • Avoid unnecessary checks and simplify the conditional paths.

Summary of changes.

  1. The set_field_advanced function now performs the logic directly instead of repeating function calls inside loops.
  2. Both functions now operate directly on build_config without reassigning it in each iteration.
  3. Reduced redundant isinstance and membership tests within loops by moving logic directly within the set_multiple_field_advanced function.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 31 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage
🌀 Generated Regression Tests Details
import pytest  # used for our unit tests
from langflow.utils.component_utils import set_multiple_field_advanced


# function to test
class dotdict(dict):  # noqa: N801
    """dotdict allows accessing dictionary elements using dot notation (e.g., dict.key instead of dict['key']).

    It automatically converts nested dictionaries into dotdict instances, enabling dot notation on them as well.

    Note:
        - Only keys that are valid attribute names (e.g., strings that could be variable names) are accessible via dot
          notation.
        - Keys which are not valid Python attribute names or collide with the dict method names (like 'items', 'keys')
          should be accessed using the traditional dict['key'] notation.
    """

    def __getattr__(self, attr):
        """Override dot access to behave like dictionary lookup. Automatically convert nested dicts to dotdicts.

        Args:
            attr (str): Attribute to access.

        Returns:
            The value associated with 'attr' in the dictionary, converted to dotdict if it is a dict.

        Raises:
            AttributeError: If the attribute is not found in the dictionary.
        """
        try:
            value = self[attr]
            if isinstance(value, dict) and not isinstance(value, dotdict):
                value = dotdict(value)
                self[attr] = value  # Update self to nest dotdict for future accesses
        except KeyError as e:
            msg = f"'dotdict' object has no attribute '{attr}'"
            raise AttributeError(msg) from e
        else:
            return value

    def __setattr__(self, key, value) -> None:
        """Override attribute setting to work as dictionary item assignment.

        Args:
            key (str): The key under which to store the value.
            value: The value to store in the dictionary.
        """
        if isinstance(value, dict) and not isinstance(value, dotdict):
            value = dotdict(value)
        self[key] = value

    def __delattr__(self, key) -> None:
        """Override attribute deletion to work as dictionary item deletion.

        Args:
            key (str): The key of the item to delete from the dictionary.

        Raises:
            AttributeError: If the key is not found in the dictionary.
        """
        try:
            del self[key]
        except KeyError as e:
            msg = f"'dotdict' object has no attribute '{key}'"
            raise AttributeError(msg) from e

    def __missing__(self, key):
        """Handle missing keys by returning an empty dotdict. This allows chaining access without raising KeyError.

        Args:
            key: The missing key.

        Returns:
            An empty dotdict instance for the given missing key.
        """
        return dotdict()
from langflow.utils.component_utils import set_multiple_field_advanced

# unit tests

# Basic Functionality
def test_single_field_update_via_fields():
    build_config = dotdict({"field1": {}})
    fields = {"field1": True}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_multiple_field_update_via_fields():
    build_config = dotdict({"field1": {}, "field2": {}})
    fields = {"field1": True, "field2": False}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_single_field_update_via_field_list():
    build_config = dotdict({"field1": {}})
    field_list = ["field1"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output

def test_multiple_field_update_via_field_list():
    build_config = dotdict({"field1": {}, "field2": {}})
    field_list = ["field1", "field2"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=False); result = codeflash_output

# Edge Cases
def test_empty_fields_dict():
    build_config = dotdict({"field1": {}})
    fields = {}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_empty_field_list():
    build_config = dotdict({"field1": {}})
    field_list = []
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output

def test_non_existent_field_in_fields():
    build_config = dotdict({"field1": {}})
    fields = {"non_existent_field": True}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_non_existent_field_in_field_list():
    build_config = dotdict({"field1": {}})
    field_list = ["non_existent_field"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output

# Large Scale Test Cases
def test_large_fields_dict():
    build_config = dotdict({f"field{i}": {} for i in range(1000)})
    fields = {f"field{i}": True for i in range(1000)}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
    for i in range(1000):
        pass

def test_large_field_list():
    build_config = dotdict({f"field{i}": {} for i in range(1000)})
    field_list = [f"field{i}" for i in range(1000)]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output
    for i in range(1000):
        pass

# Mixed Scenarios
def test_mixed_valid_and_invalid_fields():
    build_config = dotdict({"field1": {}, "invalid_field": {}})
    fields = {"field1": True, "invalid_field": "not_a_boolean"}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_mixed_existing_and_non_existent_fields():
    build_config = dotdict({"field1": {}})
    field_list = ["field1", "non_existent_field"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output

# Nested dotdict Structures
def test_nested_dotdict_multiple_field_updates():
    build_config = dotdict({"nested": {"field1": {}, "field2": {}}})
    fields = {"nested.field1": True, "nested.field2": False}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

# Default Parameters
def test_default_is_advanced_parameter():
    build_config = dotdict({"field1": {}})
    fields = {"field1": None}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_default_is_advanced_with_field_list():
    build_config = dotdict({"field1": {}})
    field_list = ["field1"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list); result = codeflash_output
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

import pytest  # used for our unit tests
from langflow.schema.dotdict import dotdict
from langflow.utils.component_utils import set_multiple_field_advanced


# function to test
class dotdict(dict):  # noqa: N801
    """dotdict allows accessing dictionary elements using dot notation (e.g., dict.key instead of dict['key']).

    It automatically converts nested dictionaries into dotdict instances, enabling dot notation on them as well.

    Note:
        - Only keys that are valid attribute names (e.g., strings that could be variable names) are accessible via dot
          notation.
        - Keys which are not valid Python attribute names or collide with the dict method names (like 'items', 'keys')
          should be accessed using the traditional dict['key'] notation.
    """

    def __getattr__(self, attr):
        """Override dot access to behave like dictionary lookup. Automatically convert nested dicts to dotdicts.

        Args:
            attr (str): Attribute to access.

        Returns:
            The value associated with 'attr' in the dictionary, converted to dotdict if it is a dict.

        Raises:
            AttributeError: If the attribute is not found in the dictionary.
        """
        try:
            value = self[attr]
            if isinstance(value, dict) and not isinstance(value, dotdict):
                value = dotdict(value)
                self[attr] = value  # Update self to nest dotdict for future accesses
        except KeyError as e:
            msg = f"'dotdict' object has no attribute '{attr}'"
            raise AttributeError(msg) from e
        else:
            return value

    def __setattr__(self, key, value) -> None:
        """Override attribute setting to work as dictionary item assignment.

        Args:
            key (str): The key under which to store the value.
            value: The value to store in the dictionary.
        """
        if isinstance(value, dict) and not isinstance(value, dotdict):
            value = dotdict(value)
        self[key] = value

    def __delattr__(self, key) -> None:
        """Override attribute deletion to work as dictionary item deletion.

        Args:
            key (str): The key of the item to delete from the dictionary.

        Raises:
            AttributeError: If the key is not found in the dictionary.
        """
        try:
            del self[key]
        except KeyError as e:
            msg = f"'dotdict' object has no attribute '{key}'"
            raise AttributeError(msg) from e

    def __missing__(self, key):
        """Handle missing keys by returning an empty dotdict. This allows chaining access without raising KeyError.

        Args:
            key: The missing key.

        Returns:
            An empty dotdict instance for the given missing key.
        """
        return dotdict()
from langflow.utils.component_utils import set_multiple_field_advanced

# unit tests

def test_single_field_update_with_fields_dict():
    build_config = dotdict({"field1": {}})
    fields = {"field1": True}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_multiple_fields_update_with_fields_dict():
    build_config = dotdict({"field1": {}, "field2": {}})
    fields = {"field1": True, "field2": False}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_single_field_update_with_field_list():
    build_config = dotdict({"field1": {}})
    field_list = ["field1"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output

def test_multiple_fields_update_with_field_list():
    build_config = dotdict({"field1": {}, "field2": {}})
    field_list = ["field1", "field2"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=False); result = codeflash_output

def test_both_fields_and_field_list_provided():
    build_config = dotdict({"field1": {}, "field2": {}, "field3": {}})
    fields = {"field1": True}
    field_list = ["field2"]
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields, field_list=field_list, is_advanced=False); result = codeflash_output

def test_neither_fields_nor_field_list_provided():
    build_config = dotdict({"field1": {}})
    codeflash_output = set_multiple_field_advanced(build_config); result = codeflash_output

def test_empty_fields_dict():
    build_config = dotdict({"field1": {}})
    fields = {}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_empty_field_list():
    build_config = dotdict({"field1": {}})
    field_list = []
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output

def test_non_existent_field_in_fields():
    build_config = dotdict({"field1": {}})
    fields = {"non_existent_field": True}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_non_existent_field_in_field_list():
    build_config = dotdict({"field1": {}})
    field_list = ["non_existent_field"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output

def test_nested_field_in_fields():
    build_config = dotdict({"nested_field": {"inner_field": {}}})
    fields = {"nested_field": True}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_nested_field_in_field_list():
    build_config = dotdict({"nested_field": {"inner_field": {}}})
    field_list = ["nested_field"]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=False); result = codeflash_output

def test_large_fields_dict():
    build_config = dotdict({f"field{i}": {} for i in range(1000)})
    fields = {f"field{i}": i % 2 == 0 for i in range(1000)}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
    for i in range(1000):
        pass

def test_large_field_list():
    build_config = dotdict({f"field{i}": {} for i in range(1000)})
    field_list = [f"field{i}" for i in range(1000)]
    codeflash_output = set_multiple_field_advanced(build_config, field_list=field_list, is_advanced=True); result = codeflash_output
    for i in range(1000):
        pass




def test_deeply_nested_fields():
    build_config = dotdict({"level1": {"level2": {"level3": {"field": {}}}}})
    fields = {"level1.level2.level3.field": True}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output

def test_stress_test_with_max_input_size():
    build_config = dotdict({f"field{i}": {} for i in range(1000)})
    fields = {f"field{i}": i % 2 == 0 for i in range(1000)}
    codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
    for i in range(1000):
        pass
# 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-pr7756-2025-04-23T07.37.53 and push.

Codeflash

codeflash-ai[bot] avatar Apr 23 '25 07:04 codeflash-ai[bot]