Documentation
¶
Overview ¶
Example 20_concurrent_reads — the lock-free read contract of a frozen CSR snapshot, exercised by many concurrent readers.
A single immutable csr.CSR is built once from a seeded, realistic scale-free network and then read concurrently by a pool of worker goroutines. Each worker runs the same mixed read workload — a batch of Dijkstra single-source shortest paths, a BFS reach count, and a PageRank to convergence — over the one shared snapshot. None of them takes a lock on the snapshot: an immutable CSR is safe for any number of concurrent readers with zero synchronisation on the hot path (Mehlhorn-Sanders, GraphBLAS). That is the contract this example demonstrates and measures.
Model ¶
The graph is a Barabási-Albert preferential-attachment network — the canonical model of a social / web graph, where a few high-degree hubs dominate and the degree distribution is heavy-tailed. It is the right shape here for three reasons:
- It is connected by construction (a connected seed core, and every new node attaches at least one edge to the already-connected component), so BFS reaches every node and its reach count is a constant, regardless of the seed.
- The hub structure gives PageRank a meaningful, well-separated top-k, so "the top-k set is constant" is a robust invariant.
- The high-degree hubs create heavy adjacency fan-out, so each read does real CPU work — the point of a concurrency benchmark.
Edges are undirected (an adjlist.AdjList with Directed:false mirrors every insertion) and carry an integer weight in [1, weightMax] drawn from the seeded RNG. Integer weights keep Dijkstra free of NaN/Inf concerns and make distance sums exact.
Evidence — the lock-free read contract ¶
The example reports the evidence that matters for a concurrency subject (see docs/examples-standard.md):
- Aggregate read throughput (reads/s) of the mixed workload.
- Per-worker-count scaling: the identical workload is run at 1, 2, 4, 8 … workers (capped at GOMAXPROCS), and the throughput at each level is printed as telemetry. Throughput that climbs with the worker count is the observable evidence that readers do not contend on the snapshot.
- Live heap, so a reader can see the immutable snapshot is shared, not copied per worker.
All telemetry lines are prefixed with "# " and vary per run and machine. The correctness evidence is printed as bare deterministic fact lines: every concurrent read returns the SAME answer a single reader computes. Specifically — for a fixed seed — every concurrent Dijkstra from the fixed source yields the same distance to the fixed target, the BFS reach count is constant, and the PageRank top-k node set is constant. The headline fact, reads.agree=true, asserts that concurrent reads agreed with the single-threaded reference across every worker count.
Scale ¶
Run with no flags, the example builds a small, deterministic default (a few thousand nodes) that a test pins and that completes well under a second. Every dimension is a flag, so the same binary scales up to a size where concurrent reads do enough work for the scaling curve to be observable:
go run ./examples/20_concurrent_reads -nodes 200000 -attach 8 -workers 16
The data shape is reproducible for a fixed -seed; only the telemetry (lines prefixed with "# ") varies between runs and machines.