langflow
langflow copied to clipboard
⚡️ Speed up function `set_multiple_field_advanced` by 12% in PR #7741 (`mcp-server-backend`)
⚡️ This pull request contains optimizations for PR #7741
If you approve this dependent PR, these changes will be merged into the original PR branch mcp-server-backend.
This PR will be automatically closed if the original PR is merged.
📄 12% (0.12x) speedup for set_multiple_field_advanced in src/backend/base/langflow/utils/component_utils.py
⏱️ Runtime : 923 microseconds → 826 microseconds (best of 114 runs)
📝 Explanation and details
To optimize the given program, we will make improvements to reduce redundant function calls and leverage direct dictionary updates where possible. Here is the revised version of the program.
Summary of Changes.
-
Removed Redundant Function Calls:
- In
set_multiple_field_advanced, theset_field_advancedfunction was replaced with direct dictionary updates to avoid the overhead of repeated function calls. This helps ensure that the updates are more efficient.
- In
-
Avoiding Unnecessary Return in
set_field_advanced:- The
set_field_advancedfunction now returnsNonesince the purpose of the function is to modify thebuild_configin place. This avoids confusion about needing the return value.
- The
-
Integrated Direct Checks within
set_multiple_field_advanced:- The checks for the field existence and type have been integrated directly within the loops of
set_multiple_field_advancedto avoid extra function calls, making the loops more efficient.
- The checks for the field existence and type have been integrated directly within the loops of
These subtle changes help to optimize both runtime and memory usage while maintaining the same functionality.
✅ Correctness verification report:
| Test | Status |
|---|---|
| ⚙️ Existing Unit Tests | 🔘 None Found |
| 🌀 Generated Regression Tests | ✅ 28 Passed |
| ⏪ Replay Tests | 🔘 None Found |
| 🔎 Concolic Coverage Tests | 🔘 None Found |
| 📊 Tests Coverage |
🌀 Generated Regression Tests Details
import pytest # used for our unit tests
# function to test
from langflow.schema.dotdict import dotdict
from langflow.utils.component_utils import set_multiple_field_advanced
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=True); 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_dict():
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_mixed_valid_and_non_existent_fields_in_fields_dict():
build_config = dotdict({"field1": {}})
fields = {"field1": True, "non_existent_field": False}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
def test_mixed_valid_and_non_existent_fields_in_field_list():
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
def test_nested_dictionaries():
build_config = dotdict({"field1": {"nested_field": {"advanced": False}}})
fields = {"field1.nested_field": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
def test_fields_with_existing_advanced_key():
build_config = dotdict({"field1": {"advanced": False}})
fields = {"field1": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
def test_fields_without_existing_advanced_key():
build_config = dotdict({"field1": {}})
fields = {"field1": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
def test_large_number_of_fields_in_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_number_of_fields_in_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
import pytest # used for our unit tests
# function to test
from langflow.schema.dotdict import dotdict
from langflow.utils.component_utils import set_multiple_field_advanced
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_in_fields():
build_config = dotdict({"field1": {}})
fields = {"field1": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
def test_multiple_fields_in_fields():
build_config = dotdict({"field1": {}, "field2": {}})
fields = {"field1": True, "field2": False}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
# Using field_list
def test_single_field_in_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_in_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
# Mixed and Empty Inputs
def test_both_fields_and_field_list_none():
build_config = dotdict({"field1": {}})
codeflash_output = set_multiple_field_advanced(build_config, fields=None, field_list=None); result = codeflash_output
def test_fields_none_field_list_provided():
build_config = dotdict({"field1": {}, "field2": {}})
field_list = ["field1", "field2"]
codeflash_output = set_multiple_field_advanced(build_config, fields=None, field_list=field_list, is_advanced=True); result = codeflash_output
def test_fields_provided_field_list_none():
build_config = dotdict({"field1": {}})
fields = {"field1": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields, field_list=None); result = codeflash_output
def test_empty_fields_and_field_list():
build_config = dotdict({"field1": {}})
codeflash_output = set_multiple_field_advanced(build_config, fields={}, field_list=[]); result = codeflash_output
# Edge Cases
def test_field_not_present_in_build_config():
build_config = dotdict({})
fields = {"non_existent_field": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
def test_field_present_but_not_a_dict():
build_config = dotdict({"field1": "not_a_dict"})
fields = {"field1": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
def test_nested_fields():
build_config = dotdict({"parent": {"child": {}}})
fields = {"parent.child": True}
codeflash_output = set_multiple_field_advanced(build_config, fields=fields); result = codeflash_output
# Large Scale Test Cases
def test_large_number_of_fields_in_fields():
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_number_of_fields_in_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
# 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-pr7741-2025-04-24T07.39.46 and push.