Skip to content

⚡️ Speed up function is_local_ip by 12% in PR #9891 (lf-auto-add-mcp-servers)#10045

Closed
codeflash-ai[bot] wants to merge 72 commits into
mainfrom
codeflash/optimize-pr9891-2025-09-30T16.46.22
Closed

⚡️ Speed up function is_local_ip by 12% in PR #9891 (lf-auto-add-mcp-servers)#10045
codeflash-ai[bot] wants to merge 72 commits into
mainfrom
codeflash/optimize-pr9891-2025-09-30T16.46.22

Conversation

@codeflash-ai
Copy link
Copy Markdown
Contributor

@codeflash-ai codeflash-ai Bot commented Sep 30, 2025

⚡️ This pull request contains optimizations for PR #9891

If you approve this dependent PR, these changes will be merged into the original PR branch lf-auto-add-mcp-servers.

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


📄 12% (0.12x) speedup for is_local_ip in src/backend/base/langflow/api/v1/mcp_projects.py

⏱️ Runtime : 19.4 milliseconds 17.3 milliseconds (best of 82 runs)

📝 Explanation and details

The optimization adds fast-path string comparisons for the most common loopback IP addresses (127.0.0.1 and ::1) before falling back to the expensive ip_address() constructor.

Key changes:

  • Added if ip_str == "127.0.0.1" or ip_str == "::1": return True before the try-catch block
  • This bypasses the costly ip_address() call for these frequent cases

Why this is faster:
The ip_address() function is expensive (taking ~22,500ns per call according to profiling) because it performs comprehensive parsing and validation. Simple string equality checks are orders of magnitude faster (~400-500ns).

Performance impact:

  • Line profiler shows 734 hits on the new fast-path condition, meaning 734 calls avoided the expensive ip_address() construction
  • The ip_address() line dropped from 6,145 hits to 5,411 hits (734 fewer calls)
  • Total runtime reduced from 161.661ms to 148.718ms (11% speedup)

Best for: Applications that frequently check common loopback addresses like "127.0.0.1" and "::1", which are the most typical localhost representations. The optimization maintains full correctness while providing significant speedup for these common cases, with no performance penalty for other IP addresses.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 6589 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
from ipaddress import ip_address

# imports
import pytest  # used for our unit tests
from langflow.api.v1.mcp_projects import is_local_ip

ALL_INTERFACES_HOST = "0.0.0.0"  # noqa: S104
from langflow.api.v1.mcp_projects import is_local_ip

# unit tests

# -------------------- Basic Test Cases --------------------

def test_localhost_string():
    # Test the string "localhost"
    codeflash_output = is_local_ip("localhost")

def test_all_interfaces_ipv4():
    # Test the string "0.0.0.0"
    codeflash_output = is_local_ip("0.0.0.0")

def test_ipv4_loopback():
    # Test a typical IPv4 loopback address
    codeflash_output = is_local_ip("127.0.0.1")

def test_ipv6_loopback():
    # Test the canonical IPv6 loopback address
    codeflash_output = is_local_ip("::1")

def test_non_loopback_ipv4():
    # Test a public IPv4 address
    codeflash_output = is_local_ip("8.8.8.8")

def test_non_loopback_ipv6():
    # Test a public IPv6 address
    codeflash_output = is_local_ip("2001:4860:4860::8888")

# -------------------- Edge Test Cases --------------------

@pytest.mark.parametrize("ip_str", [
    "",  # Empty string
    "127.0.0.256",  # Invalid IPv4 address (out of range)
    "abc.def.ghi.jkl",  # Not an IP
    ":::::",  # Invalid IPv6
    "localhost.localdomain",  # Not exactly "localhost"
    "127.1",  # Incomplete IPv4
])
def test_invalid_ip_strings(ip_str):
    # All these should be considered not local
    codeflash_output = is_local_ip(ip_str)

def test_ipv4_loopback_range():
    # Test the lower and upper bounds of IPv4 loopback range
    codeflash_output = is_local_ip("127.0.0.0")
    codeflash_output = is_local_ip("127.255.255.255")

def test_ipv4_near_loopback():
    # Test addresses just outside the loopback range
    codeflash_output = is_local_ip("126.255.255.255")
    codeflash_output = is_local_ip("128.0.0.0")

def test_ipv6_near_loopback():
    # Test addresses near but not equal to ::1
    codeflash_output = is_local_ip("::2")
    codeflash_output = is_local_ip("::")  # unspecified address

def test_case_sensitive_localhost():
    # "LOCALHOST" should not be considered local (case sensitive)
    codeflash_output = is_local_ip("LOCALHOST")
    codeflash_output = is_local_ip("Localhost")

def test_leading_trailing_spaces():
    # Leading/trailing spaces should invalidate the input
    codeflash_output = is_local_ip(" 127.0.0.1")
    codeflash_output = is_local_ip("127.0.0.1 ")
    codeflash_output = is_local_ip(" localhost")
    codeflash_output = is_local_ip("localhost ")

def test_ipv4_with_leading_zeros():
    # IPv4 with leading zeros is valid in ipaddress, so test them
    codeflash_output = is_local_ip("127.000.000.001")

def test_ipv6_loopback_with_compression():
    # "::1" is canonical, but also test expanded form
    codeflash_output = is_local_ip("0:0:0:0:0:0:0:1")

def test_ipv6_mixed_case():
    # IPv6 is case-insensitive
    codeflash_output = is_local_ip("::1")
    codeflash_output = is_local_ip("::1".upper())

def test_ipv4_loopback_with_port():
    # IP with port should not be considered valid
    codeflash_output = is_local_ip("127.0.0.1:80")

def test_ipv6_loopback_with_port():
    # IPv6 with port should not be considered valid
    codeflash_output = is_local_ip("[::1]:80")

def test_ipv4_broadcast():
    # Broadcast address is not loopback
    codeflash_output = is_local_ip("255.255.255.255")

def test_ipv4_private():
    # Private but not loopback
    codeflash_output = is_local_ip("192.168.1.1")

def test_ipv6_unspecified():
    # Unspecified IPv6 address
    codeflash_output = is_local_ip("::")

def test_ipv6_multicast():
    # Multicast IPv6 address
    codeflash_output = is_local_ip("ff02::1")

def test_ipv4_multicast():
    # Multicast IPv4 address
    codeflash_output = is_local_ip("224.0.0.1")

def test_ipv4_all_interfaces_alias():
    # "0.0.0.0" is accepted, but not "0.0.0.1"
    codeflash_output = is_local_ip("0.0.0.1")

# -------------------- Large Scale Test Cases --------------------

def test_many_ipv4_addresses():
    # Test a large set of addresses, only 127.x.x.x should be local
    for i in range(1, 256):
        ip = f"127.0.0.{i}"
        codeflash_output = is_local_ip(ip)  # All are loopback

    # Test a large set of non-loopback addresses
    for i in range(1, 256):
        ip = f"128.0.0.{i}"
        codeflash_output = is_local_ip(ip)  # None are loopback

def test_many_ipv6_addresses():
    # Generate a set of IPv6 addresses, only ::1 is loopback
    for i in range(1, 100):
        ip = f"::{i}"
        if i == 1:
            codeflash_output = is_local_ip(ip)
        else:
            codeflash_output = is_local_ip(ip)

def test_large_mixed_list():
    # Test a mixed list of local and non-local IPs
    local_ips = ["localhost", "0.0.0.0", "127.0.0.1", "::1"]
    non_local_ips = ["8.8.8.8", "192.168.1.1", "2001:db8::1", "255.255.255.255"]
    test_ips = local_ips * 200 + non_local_ips * 200  # Total 1600 elements

    count_local = 0
    count_non_local = 0
    for ip in test_ips:
        codeflash_output = is_local_ip(ip); result = codeflash_output
        if ip in local_ips:
            count_local += 1
        else:
            count_non_local += 1

def test_performance_large_non_loopback():
    # Test performance with a large number of non-loopback IPs
    for i in range(1, 1000):
        ip = f"10.0.0.{i % 255}"
        codeflash_output = is_local_ip(ip)

def test_performance_large_loopback():
    # Test performance with a large number of loopback IPs
    for i in range(1, 1000):
        ip = f"127.0.0.{i % 255}"
        codeflash_output = is_local_ip(ip)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from ipaddress import ip_address

# imports
import pytest  # used for our unit tests
from langflow.api.v1.mcp_projects import is_local_ip

ALL_INTERFACES_HOST = "0.0.0.0"  # noqa: S104
from langflow.api.v1.mcp_projects import is_local_ip

# unit tests

# -------------------------
# 1. Basic Test Cases
# -------------------------

def test_localhost_string():
    # Should recognize 'localhost' as local
    codeflash_output = is_local_ip("localhost")

def test_all_interfaces_ipv4():
    # Should recognize '0.0.0.0' as local
    codeflash_output = is_local_ip("0.0.0.0")

def test_ipv4_loopback():
    # Should recognize classic IPv4 loopback addresses
    codeflash_output = is_local_ip("127.0.0.1")
    codeflash_output = is_local_ip("127.0.0.42")
    codeflash_output = is_local_ip("127.255.255.255")

def test_ipv6_loopback():
    # Should recognize IPv6 loopback address
    codeflash_output = is_local_ip("::1")

def test_non_local_ipv4():
    # Should not recognize public IPv4 addresses as local
    codeflash_output = is_local_ip("8.8.8.8")
    codeflash_output = is_local_ip("192.168.1.1")  # private, but not loopback
    codeflash_output = is_local_ip("10.0.0.1")     # private, but not loopback

def test_non_local_ipv6():
    # Should not recognize public IPv6 addresses as local
    codeflash_output = is_local_ip("2001:4860:4860::8888")
    codeflash_output = is_local_ip("fe80::1")  # link-local, but not loopback

# -------------------------
# 2. Edge Test Cases
# -------------------------

def test_invalid_ip_strings():
    # Should return False for invalid IP strings
    codeflash_output = is_local_ip("")
    codeflash_output = is_local_ip("not.an.ip")
    codeflash_output = is_local_ip("127.0.0.256")  # out of range
    codeflash_output = is_local_ip("::g")  # invalid IPv6

def test_case_sensitivity():
    # Should be case-sensitive for 'localhost'
    codeflash_output = is_local_ip("LOCALHOST")
    codeflash_output = is_local_ip("Localhost")

def test_leading_trailing_spaces():
    # Should not recognize IPs with leading/trailing spaces
    codeflash_output = is_local_ip(" 127.0.0.1")
    codeflash_output = is_local_ip("127.0.0.1 ")
    codeflash_output = is_local_ip(" localhost")
    codeflash_output = is_local_ip("localhost ")

def test_ipv4_loopback_network_range():
    # Test the lower and upper bounds of IPv4 loopback
    codeflash_output = is_local_ip("127.0.0.0")
    codeflash_output = is_local_ip("127.255.255.255")
    # Next address outside the range
    codeflash_output = is_local_ip("128.0.0.0")

def test_ipv6_loopback_variants():
    # Should only recognize '::1' as loopback
    codeflash_output = is_local_ip("::2")
    codeflash_output = is_local_ip("::")  # unspecified address

def test_ip_with_port():
    # Should not recognize IPs with port numbers as valid
    codeflash_output = is_local_ip("127.0.0.1:80")
    codeflash_output = is_local_ip("[::1]:443")

def test_ip_with_extra_characters():
    # Should not recognize IPs with extra characters
    codeflash_output = is_local_ip("127.0.0.1/8")
    codeflash_output = is_local_ip("::1/128")

def test_non_string_input():
    # Should return False for non-string input
    codeflash_output = is_local_ip(None)
    codeflash_output = is_local_ip(127001)
    codeflash_output = is_local_ip(["127.0.0.1"])

def test_unicode_and_special_characters():
    # Should return False for unicode or special character input
    codeflash_output = is_local_ip("127.0.0.1\u200b")  # zero-width space
    codeflash_output = is_local_ip("127.0.0.1\n")      # newline
    codeflash_output = is_local_ip("::1\t")            # tab

# -------------------------
# 3. Large Scale Test Cases
# -------------------------

def test_large_batch_of_ips():
    # Generate a mix of loopback and non-loopback IPv4 addresses
    loopback_ips = [f"127.0.0.{i}" for i in range(1, 501)]    # 500 loopback
    non_loopback_ips = [f"128.0.0.{i}" for i in range(1, 251)] # 250 non-loopback
    all_ips = loopback_ips + non_loopback_ips

    # Check that all loopback IPs are recognized as local
    for ip in loopback_ips:
        codeflash_output = is_local_ip(ip)

    # Check that all non-loopback IPs are not recognized as local
    for ip in non_loopback_ips:
        codeflash_output = is_local_ip(ip)

def test_large_batch_of_ipv6():
    # Generate a batch of IPv6 loopback and non-loopback addresses
    loopback_ipv6 = ["::1"] * 300
    non_loopback_ipv6 = [f"::2:{i}" for i in range(300)]
    all_ipv6 = loopback_ipv6 + non_loopback_ipv6

    # Check loopback
    for ip in loopback_ipv6:
        codeflash_output = is_local_ip(ip)

    # Check non-loopback
    for ip in non_loopback_ipv6:
        codeflash_output = is_local_ip(ip)

def test_large_batch_of_invalid_ips():
    # Generate a batch of invalid IP addresses
    invalid_ips = [f"invalid{i}" for i in range(100)]
    invalid_ips += [f"127.0.0.{i}x" for i in range(100)]
    invalid_ips += [f"::1:{i}g" for i in range(100)]

    for ip in invalid_ips:
        codeflash_output = is_local_ip(ip)

def test_performance_large_mixed_batch():
    # Mix of valid loopback, valid non-loopback, and invalid IPs
    batch = []
    batch += [f"127.0.0.{i}" for i in range(1, 201)]             # 200 loopback
    batch += [f"192.168.0.{i}" for i in range(1, 201)]            # 200 non-loopback
    batch += [f"invalid{i}" for i in range(1, 201)]               # 200 invalid
    batch += ["localhost", "0.0.0.0", "::1"] * 20                 # 60 special cases

    # Check correct classification
    for ip in batch:
        if ip.startswith("127.0.0.") or ip in ("localhost", "0.0.0.0", "::1"):
            codeflash_output = is_local_ip(ip)
        else:
            codeflash_output = is_local_ip(ip)
# 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-pr9891-2025-09-30T16.46.22 and push.

Codeflash

Moved MCP-related utility functions (auto_configure_starter_projects_mcp, get_project_sse_url, get_url_by_os) from mcp_projects.py to a new dedicated utils/mcp/config_utils.py module for better code organization and maintainability. Added __init__.py files for new utils submodules and updated imports accordingly. Also updated documentation and comments for clarity. Minor docstring update in settings/base.py.
Added support for configurable default authentication type when auto-registering MCP servers for new projects, including handling for 'none', 'apikey', and unimplemented 'oauth' types. MCP server names are now updated on project rename, and corresponding MCP servers are deleted when projects are removed. Introduced 'default_mcp_auth_type' setting to control authentication mode for auto-added MCP servers.
Replaces the 'current_port' field with 'runtime_port' in settings to clarify its temporary, system-managed nature. Updates all references and documentation to reflect the new field name and its intended use until strict port enforcement is implemented.
Added a TODO comment to improve the method for determining the position of the SSE URL in the argument list within validate_mcp_server_for_project.
…tings pages for testing purposes

🔧 (frontend): add convertTestName utility function for converting test names to lowercase with hyphens
🔧 (frontend): add cleanOldFolders utility function to remove old folders in testing environment
🔧 (frontend): add navigateSettingsPages utility function to navigate to specific settings pages in testing
…havior

✨ (use-patch-flows-mcp.ts): add retry: 0 option to improve mutation behavior
✨ (use-patch-install-mcp.ts): add retry: 0 option to improve mutation behavior
✨ (use-patch-mcp-server.ts): add retry: 0 option to improve mutation behavior
📝 (mcp-server-starter-projects.spec.ts): add test to prevent adding duplicate mcp servers from starter projects
…orTimeout to 5000ms for stability

⬆️ (starter-projects.spec.ts): adjust timeout value to 5000 * 3 for better performance and reliability
The optimization adds fast-path string comparisons for the most common loopback IP addresses (`127.0.0.1` and `::1`) before falling back to the expensive `ip_address()` constructor.

**Key changes:**
- Added `if ip_str == "127.0.0.1" or ip_str == "::1": return True` before the try-catch block
- This bypasses the costly `ip_address()` call for these frequent cases

**Why this is faster:**
The `ip_address()` function is expensive (taking ~22,500ns per call according to profiling) because it performs comprehensive parsing and validation. Simple string equality checks are orders of magnitude faster (~400-500ns). 

**Performance impact:**
- Line profiler shows 734 hits on the new fast-path condition, meaning 734 calls avoided the expensive `ip_address()` construction
- The `ip_address()` line dropped from 6,145 hits to 5,411 hits (734 fewer calls)
- Total runtime reduced from 161.661ms to 148.718ms (11% speedup)

**Best for:** Applications that frequently check common loopback addresses like "127.0.0.1" and "::1", which are the most typical localhost representations. The optimization maintains full correctness while providing significant speedup for these common cases, with no performance penalty for other IP addresses.
@codeflash-ai codeflash-ai Bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Sep 30, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 30, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


🧪 Early access (Sonnet 4.5): enabled

We are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

@codecov
Copy link
Copy Markdown

codecov Bot commented Sep 30, 2025

Codecov Report

❌ Patch coverage is 60.64982% with 109 lines in your changes missing coverage. Please review.
✅ Project coverage is 24.12%. Comparing base (e3bf7cd) to head (c1e57d5).
⚠️ Report is 617 commits behind head on main.

Files with missing lines Patch % Lines
src/backend/base/langflow/api/v1/projects.py 33.33% 56 Missing ⚠️
...ackend/base/langflow/api/utils/mcp/config_utils.py 76.27% 42 Missing ⚠️
src/backend/base/langflow/api/v1/mcp_projects.py 42.85% 4 Missing ⚠️
src/frontend/src/utils/stringManipulation.ts 0.00% 3 Missing ⚠️
...sideBarFolderButtons/components/select-options.tsx 0.00% 2 Missing ⚠️
src/backend/base/langflow/main.py 50.00% 1 Missing ⚠️
.../pages/SettingsPage/pages/MCPServersPage/index.tsx 0.00% 1 Missing ⚠️

❌ Your project status has failed because the head coverage (47.01%) is below the target coverage (55.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #10045      +/-   ##
==========================================
+ Coverage   23.68%   24.12%   +0.44%     
==========================================
  Files        1090     1091       +1     
  Lines       39766    40014     +248     
  Branches     5542     5543       +1     
==========================================
+ Hits         9417     9655     +238     
- Misses      30178    30188      +10     
  Partials      171      171              
Flag Coverage Δ
backend 47.01% <61.99%> (+0.82%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/backend/base/langflow/__main__.py 55.36% <100.00%> (+0.09%) ⬆️
src/backend/base/langflow/api/utils/core.py 55.90% <ø> (ø)
.../controllers/API/queries/mcp/use-add-mcp-server.ts 0.00% <ø> (ø)
...controllers/API/queries/mcp/use-patch-flows-mcp.ts 0.00% <ø> (ø)
...ntrollers/API/queries/mcp/use-patch-install-mcp.ts 0.00% <ø> (ø)
...ontrollers/API/queries/mcp/use-patch-mcp-server.ts 0.00% <ø> (ø)
...rc/frontend/src/modals/addMcpServerModal/index.tsx 0.00% <ø> (ø)
...ages/ApiKeysPage/components/ApiKeyHeader/index.tsx 0.00% <ø> (ø)
...GeneralPage/components/GeneralPageHeader/index.tsx 0.00% <ø> (ø)
...s/SettingsPage/pages/GlobalVariablesPage/index.tsx 0.00% <ø> (ø)
... and 10 more

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Base automatically changed from lf-auto-add-mcp-servers to main September 30, 2025 20:10
@ogabrielluiz
Copy link
Copy Markdown
Contributor

Closing automated codeflash PR.

@codeflash-ai codeflash-ai Bot deleted the codeflash/optimize-pr9891-2025-09-30T16.46.22 branch March 3, 2026 18:15
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.

5 participants