langflow
langflow copied to clipboard
⚡️ Speed up function `set_multiple_field_advanced` by 14% in PR #7756 (`codeflash/optimize-pr7755-2025-04-23T07.14.50`)
⚡️ 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_configinside the loops. Updating thebuild_configdirectly will suffice sincebuild_configis mutable and the changes will persist. - Instead of making repetitive function calls, perform the logic directly within the
set_multiple_field_advancedfunction to minimize overhead. - Avoid unnecessary checks and simplify the conditional paths.
Summary of changes.
- The
set_field_advancedfunction now performs the logic directly instead of repeating function calls inside loops. - Both functions now operate directly on
build_configwithout reassigning it in each iteration. - Reduced redundant
isinstanceand membership tests within loops by moving logic directly within theset_multiple_field_advancedfunction.
✅ 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.