Benchmarks
Backend speed is an end-to-end question. These results include conversion from NetworkX, the rustworkx kernel, and remapping to the original node IDs. Both implementations receive the same graphs and seeds.
Dispatch follows the measurements. At 2,000 nodes, 89 of 111 supported functions are faster end to end. Automatic backend priority declines the 24 functions where NetworkX keeps winning.
Real projects
The strongest evidence is other people's code. The runners in
benches/external/
drop the backend into real NetworkX projects without changing their
application code and compare against stock NetworkX on the same
machine. Every timed call is verified to have actually dispatched, and
the committed
RESULTS.md
holds the full tables, including the honest losses.
| Workload | NetworkX | nx-rustworkx | Speedup |
|---|---|---|---|
| City street network (OSMnx MultiDiGraph, parallel ways included), weighted closeness centrality | 358 s | 2.6 s | 136× |
| Same network, unweighted betweenness centrality | 115 s | 1.5 s | 78× |
| Same network, 200 point-to-point travel-time routes | 8.0 s | 2.3 s | 3.4× |
| nx-parallel benchmark suite, all-pairs Bellman–Ford lengths (n=400) | 18.7 s | 0.44 s | 42× |
| NetworkX's bundled benchmark suite, strongly connected components (n=10,000) | 32 ms | 4 ms | 8× |
A good fit: CPU-heavy whole-graph algorithms on graphs from a few
hundred nodes up — centralities, all-pairs shortest paths,
components, isomorphism — and repeat-call pipelines, where the
one-time conversion is cached. Not the tool: graphs below the
200-node/400-edge floor, one-off linear-time calls where conversion
costs more than NetworkX's answer, SciPy-backed algorithms such as
pagerank, callable weights, and code that walks
G.adj directly — a backend can only accelerate the
NetworkX API.
Parity suite
bench_parity.py
runs one representative call for every supported function. It fails if
a materially slower function would still be selected automatically.
python benches/bench_parity.py --nodes 2000
| Function | rustworkx (s) | NetworkX (s) | Speedup |
|---|---|---|---|
is_isomorphic | 0.0228 | 13.42 | 589× |
bridges | 0.00058 | 0.134 | 232× |
katz_centrality | 0.0055 | 0.393 | 72× |
group_betweenness_centrality | 0.378 | 25.63 | 68× |
transitivity | 0.0024 | 0.149 | 63× |
betweenness_centrality | 0.313 | 16.98 | 54× |
floyd_warshall | 0.354 | 13.30 | 38× |
max_weight_matching | 0.167 | 4.09 | 25× |
all_pairs_dijkstra_path_length | 0.076 | 1.76 | 23× |
eigenvector_centrality | 0.0042 | 0.068 | 16× |
minimum_spanning_tree | 0.0149 | 0.066 | 4.4× |
core_number | 0.0076 | 0.0118 | 1.6× |
These figures describe one machine and workload, not a universal ranking. Run the scripts on your own graph shapes before tuning cutoffs.
Conversion cost
bench_centrality.py
separates conversion from the betweenness-centrality kernel.
python benches/bench_centrality.py
| n | m | convert (s) | kernel (s) | total (s) | NetworkX (s) | speedup |
|---|---|---|---|---|---|---|
| 200 | 2,035 | 0.00031 | 0.0019 | 0.0048 | 0.067 | 14× |
| 2,000 | 20,050 | 0.0043 | 0.19 | 0.30 | 8.4 | 28× |
| 20,000 | 200,473 | 0.098 | 50 | 52 | — | — |
The 2,000-node row is the public milestone graph. The NetworkX run at 20,000 nodes is omitted because the pure-Python Brandes computation is impractical there.
Read the result
- Use backend priority when workloads mix cheap and expensive calls.
- Use an explicit backend when you value a predictable implementation over the cutoff.
- Use a backend graph when repeated conversion is a meaningful share of runtime.