⚡️ Speed up function find_last_node by 22,229%
#247
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 22,229% (222.29x) speedup for
find_last_nodeinsrc/algorithms/graph.py⏱️ Runtime :
69.9 milliseconds→313 microseconds(best of250runs)📝 Explanation and details
The optimized code achieves a 222x speedup by eliminating a nested loop anti-pattern that created O(n*m) time complexity.
What changed:
The original implementation used a nested comprehension
all(e["source"] != n["id"] for e in edges)that, for each node, iterated through ALL edges to verify none had that node as a source. This means for every node candidate, the entire edge list was scanned.The optimization pre-computes a set of all source IDs once (
source_ids = {e["source"] for e in edges}), then performs a simple O(1) set membership check (n["id"] not in source_ids) for each node.Why it's faster:
The performance gain is most dramatic when both node and edge counts are large, as shown in the tests:
test_large_linear_chain: 31,815% faster (17.8ms → 55.8μs) with 1000 nodes/999 edgestest_large_graph_no_last_node: 32,219% faster (17.7ms → 54.8μs)test_large_complete_binary_tree: 12,333% faster (2.26ms → 18.2μs)Even small graphs benefit significantly (50-90% faster in most test cases) because set construction and membership testing are highly optimized in Python's C implementation.
Impact:
This optimization is crucial if
find_last_nodeis called frequently or on graphs with hundreds/thousands of nodes and edges. The quadratic behavior of the original would become a bottleneck in any workflow processing multiple large graphs. The optimized version scales linearly and maintains consistent sub-millisecond performance even on 1000-node graphs.✅ Correctness verification report:
🌀 Click to see Generated Regression Tests
To edit these changes
git checkout codeflash/optimize-find_last_node-mk3l3ik1and push.