Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: ⚡️ Speed up function find_cycle_vertices by 324% #5262

Conversation

misrasaurabh1
Copy link
Contributor

📄 find_cycle_vertices in src/backend/base/langflow/graph/graph/utils.py

✨ Performance Summary:

  • Speed Increase: 📈 324% (3.24x faster)
  • Runtime Reduction: ⏱️ From 71.5 milliseconds down to 16.9 milliseconds (best of 19 runs)

📝 Explanation and details

Here's an optimized version of the code. It uses a more efficient way to find the vertices on a cycle.


Correctness verification

The new optimized code was tested for correctness. The results are listed below:

Test Status Details
⚙️ Existing Unit Tests 56 Passed See below
🌀 Generated Regression Tests 29 Passed See below
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Coverage 100.0%

⚙️ Existing Unit Tests Details

Click to view details
- graph/graph/test_cycles.py
- graph/graph/test_utils.py

🌀 Generated Regression Tests Details

Click to view details
import networkx as nx  # used for the function to test
# imports
import pytest  # used for our unit tests
from langflow.graph.graph.utils import find_cycle_vertices

# unit tests

def test_single_cycle():
    edges = [(1, 2), (2, 3), (3, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_multiple_disjoint_cycles():
    edges = [(1, 2), (2, 1), (3, 4), (4, 3)]
    codeflash_output = find_cycle_vertices(edges)

def test_cycle_with_additional_edges():
    edges = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5)]
    codeflash_output = find_cycle_vertices(edges)

def test_acyclic_graph():
    edges = [(1, 2), (2, 3), (3, 4)]
    codeflash_output = find_cycle_vertices(edges)

def test_empty_graph():
    edges = []
    codeflash_output = find_cycle_vertices(edges)

def test_multiple_interconnected_cycles():
    edges = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 3)]
    codeflash_output = find_cycle_vertices(edges)

def test_nested_cycles():
    edges = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 4)]
    codeflash_output = find_cycle_vertices(edges)

def test_self_loop():
    edges = [(1, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_single_node_no_edges():
    edges = [(1, 2)]
    codeflash_output = find_cycle_vertices(edges)

def test_disconnected_nodes():
    edges = [(1, 2), (3, 4)]
    codeflash_output = find_cycle_vertices(edges)

def test_large_graph_single_cycle():
    edges = [(i, i+1) for i in range(1, 1000)] + [(1000, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_large_graph_no_cycles():
    edges = [(i, i+1) for i in range(1, 1000)]
    codeflash_output = find_cycle_vertices(edges)

def test_large_graph_multiple_cycles():
    edges = [(i, i+1) for i in range(1, 500)] + [(500, 1)] + [(i, i+1) for i in range(501, 1000)] + [(1000, 501)]
    codeflash_output = find_cycle_vertices(edges)

def test_string_nodes():
    edges = [('a', 'b'), ('b', 'c'), ('c', 'a')]
    codeflash_output = find_cycle_vertices(edges)


def test_duplicate_edges_in_cycle():
    edges = [(1, 2), (2, 3), (3, 1), (1, 2), (2, 3)]
    codeflash_output = find_cycle_vertices(edges)

def test_duplicate_edges_no_cycle():
    edges = [(1, 2), (1, 2), (2, 3), (2, 3)]
    codeflash_output = find_cycle_vertices(edges)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
import networkx as nx
# imports
import pytest  # used for our unit tests
from langflow.graph.graph.utils import find_cycle_vertices

# unit tests

def test_single_cycle():
    # Basic test with a single cycle
    edges = [(1, 2), (2, 3), (3, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_multiple_disjoint_cycles():
    # Test with multiple disjoint cycles
    edges = [(1, 2), (2, 1), (3, 4), (4, 3)]
    codeflash_output = find_cycle_vertices(edges)

def test_single_node_cycle():
    # Test with a single node cycle
    edges = [(1, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_acyclic_graph():
    # Test with an acyclic graph
    edges = [(1, 2), (2, 3), (3, 4)]
    codeflash_output = find_cycle_vertices(edges)

def test_empty_graph():
    # Test with an empty graph
    edges = []
    codeflash_output = find_cycle_vertices(edges)

def test_multiple_interconnected_cycles():
    # Test with multiple interconnected cycles
    edges = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 2)]
    codeflash_output = find_cycle_vertices(edges)

def test_nested_cycles():
    # Test with nested cycles
    edges = [(1, 2), (2, 3), (3, 4), (4, 2), (3, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_self_loop_and_disjoint_cycle():
    # Test with a self-loop and a disjoint cycle
    edges = [(1, 1), (2, 3), (3, 2)]
    codeflash_output = find_cycle_vertices(edges)

def test_graph_with_isolated_nodes():
    # Test with isolated nodes
    edges = [(1, 2), (2, 1), (3, 4)]
    codeflash_output = find_cycle_vertices(edges)

def test_large_graph_one_large_cycle():
    # Test with a large graph with one large cycle
    edges = [(i, i+1) for i in range(1, 1000)] + [(1000, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_large_graph_multiple_small_cycles():
    # Test with a large graph with multiple small cycles
    edges = [(i, i+1) for i in range(1, 100)] + [(i+1, i) for i in range(1, 100, 2)]
    codeflash_output = find_cycle_vertices(edges)

def test_graph_with_parallel_edges():
    # Test with a graph with parallel edges (multigraph)
    edges = [(1, 2), (1, 2), (2, 1)]
    codeflash_output = find_cycle_vertices(edges)

def test_graph_with_no_edges_but_multiple_nodes():
    # Test with a graph with no edges but multiple nodes
    edges = [(1, 2), (3, 4)]
    codeflash_output = find_cycle_vertices(edges)

# Run the tests
if __name__ == "__main__":
    pytest.main()
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

📣 **Feedback**

If you have any feedback or need assistance, feel free to join our Discord community:

Discord

Here's an optimized version of the code.
@dosubot dosubot bot added size:S This PR changes 10-29 lines, ignoring generated files. enhancement New feature or request labels Dec 13, 2024
Copy link

codspeed-hq bot commented Dec 13, 2024

CodSpeed Performance Report

Merging #5262 will improve performances by ×2.1

Comparing codeflash-ai:codeflash/optimize-find_cycle_vertices-2024-12-11T14.43.05 (6e6c072) with main (4736aae)

Summary

⚡ 2 improvements
✅ 13 untouched benchmarks

Benchmarks breakdown

Benchmark main codeflash-ai:codeflash/optimize-find_cycle_vertices-2024-12-11T14.43.05 Change
test_get_and_cache_all_types_dict 2.4 ms 1.1 ms ×2.1
test_successful_run_with_input_type_any 331.1 ms 272.8 ms +21.4%

@ogabrielluiz ogabrielluiz changed the title ⚡️ Speed up function find_cycle_vertices by 324% perf:⚡️ Speed up function find_cycle_vertices by 324% Dec 14, 2024
@ogabrielluiz ogabrielluiz changed the title perf:⚡️ Speed up function find_cycle_vertices by 324% refactor:⚡️ Speed up function find_cycle_vertices by 324% Dec 16, 2024
Copy link
Contributor

@ogabrielluiz ogabrielluiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @misrasaurabh1

We need to fix these before we can merge.

@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Dec 16, 2024
@ogabrielluiz ogabrielluiz changed the title refactor:⚡️ Speed up function find_cycle_vertices by 324% ref:⚡️ Speed up function find_cycle_vertices by 324% Dec 16, 2024
@ogabrielluiz ogabrielluiz changed the title ref:⚡️ Speed up function find_cycle_vertices by 324% refactor: ⚡️ Speed up function find_cycle_vertices by 324% Dec 16, 2024
@ogabrielluiz ogabrielluiz changed the title refactor: ⚡️ Speed up function find_cycle_vertices by 324% refactor: ⚡️ Speed up function find_cycle_vertices by 324% Dec 16, 2024
@github-actions github-actions bot added refactor Maintenance tasks and housekeeping and removed enhancement New feature or request labels Dec 16, 2024
@github-actions github-actions bot added refactor Maintenance tasks and housekeeping and removed refactor Maintenance tasks and housekeeping labels Dec 16, 2024
@ogabrielluiz ogabrielluiz merged commit a97c29f into langflow-ai:main Dec 17, 2024
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lgtm This PR has been approved by a maintainer refactor Maintenance tasks and housekeeping size:S This PR changes 10-29 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants