How the memory-bounded batching pattern works
developThe PBFCompleteWayReader avoids the massive memory overhead of a global node coordinate dictionary by processing the PBF in discrete batches. This is achieved through the following lifecycle:
- Way Collection: The reader iterates through ways using
MoveNext(OsmGeoType.Way, lastId + 1). It buffers way metadata and tags and accumulates the required node IDs into aHashSet<long>. - Budget Trigger: Once the number of unique node IDs in the current batch reaches the
nodeBudget, the collection phase stops. - Node Fetching: The reader calls
source.Reset()and usesMoveNext(OsmGeoType.Node, sortedId)to perform a monotonic walk of the required node IDs. BecausePBFOsmStreamSourcemaintains a block index, it can skip entire blobs that do not contain the requested IDs, making this second pass efficient. - Materialization: Each fetched
Nodeis stored in a dictionary. The reader then constructsCompleteWayobjects by combining the buffered way data with the fetched node data. - Cleanup: After the batch is yielded, the way buffer, node ID set, and node dictionary are discarded. The process repeats for the next range of ways.
Note on Performance: The first batch may have a higher 'collect' time because it warms up the PBFOsmStreamSource block index by walking the node section. Subsequent batches benefit from a warm index and faster skips.