Repository navigation
Conversation
This is the same as PR sbromberger/LightGraphs.jl#1559 in the old lightgraphs repository. From substantial benchmarking, this is a significant speedup in most cases and an asymptotic improvement from quadratic to linear for star graphs, with a performance regression of a few percent only in the limit of extremely sparse graphs. Furthermore, it opens up the possibility for future speedups in other functions provided by this package, since it also computes data that can be directly used in those other functions. This PR does not change the API for the function itself, but it does add a couple of performance and type hint functions that other library types that inherit from AbstractGraphs can optionally overload to improve/tune performance, for example if they store adjacency lists in a linked list and so have different performance characteristics than array representations.
Hoist `destructure_type` to top-level methods and make
`infer_nb_iterstate_type(::AbstractSimpleGraph{T}) = T` (so narrow eltypes
infer the right iteration-state type), then fix the remaining Aqua
`unbound_args` failure: dispatching `destructure_type` on
`Type{Union{Nothing,Tuple{...}}}` leaves a type parameter unbound (both the
`{A,B}` and `{<:Any,B}` spellings fail), because the `Nothing` arm of the
union means the tuple parameters need not be determined by the argument.
Instead strip the `Nothing` arm with `Base.typesplit` in the caller and
dispatch `destructure_type` directly on `Tuple{A,B}`, which is unbound-clean.
Behaviour and type stability are unchanged.
Co-Authored-By: Guillaume Dalle <22795598+gdalle@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds two testsets requested during PR review: * a randomized differential test asserting that `strongly_connected_components_tarjan` produces the same partition as the independent `strongly_connected_components_kosaraju` over many random digraphs of varying size and density, that every vertex is assigned to exactly one component, and that components are returned in reverse-topological order; * a regression test on large out-/bidirectional-star graphs (centre degree >= 1024) that exercises the large-vertex DFS-iteration-state code path guarding against the old O(|E|^2) blow-up, including a narrow (Int16) eltype.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #527 +/- ##
==========================================
- Coverage 97.47% 97.45% -0.02%
==========================================
Files 128 128
Lines 7811 7830 +19
==========================================
+ Hits 7614 7631 +17
- Misses 197 199 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Hi @simsurace, |
|
No worries, I'll try to find someone else who participated in #32. |
| end | ||
|
|
||
| # Vertex size threshold below which it isn't worth keeping the DFS iteration state. | ||
| is_large_vertex(g, v) = length(outneighbors(g, v)) >= 1024 |
There was a problem hiding this comment.
In my benchmarks, this cutoff is not great:
- 1,024 vertices: it is 3.52× slower than ours (separate implementation).
- 1,025 vertices: it is 14% faster.
|
FWIW, I've also encountered this (Ferrite-FEM/Ferrite.jl#1539). This PR makes us more or less able to drop the local implementation (the hard coded 1024 is not great for us though). |
|
That's oddly sensitive. Do you have a small reproducer? I will look into it later. |
|
Why is it "oddly sensitive", it changes the alg used. Here is a benchmark: using Graphs, BenchmarkTools
function out_star(n)
g = SimpleDiGraph(n)
for v in 2:n
add_edge!(g, 1, v)
end
return g
end
for n in (1024, 1025)
g = out_star(n)
t = @belapsed strongly_connected_components_tarjan($g)
tk = @belapsed strongly_connected_components_kosaraju($g)
println("n = $n (center degree $(n - 1)): tarjan ", round(t * 1e6; digits=1), " μs, kosaraju ", round(tk * 1e6; digits=1), " μs")
end
Conclusion: Just remove the cutoff and use it unconditionally. |
This replaces #32.
I ran into long runtimes with
strongly_connected_componentsmyself and then saw that there was this unmerged PR. I brushed it up a little and added the stress tests that have been requested. The performance claims made in the PR still hold against today's master branch:The asymptotic quadratic→linear win on star / high-out-degree graphs is confirmed (three orders of magnitude at 10⁵ vertices), and the new implementation is faster with lower memory on every other case as well. The small-margin rows (1.1×–1.6×) carry run-to-run noise but were consistently ≥
master.