| Crates.io | fast-osmpbf |
| lib.rs | fast-osmpbf |
| version | 0.2.0 |
| created_at | 2025-11-28 21:56:58.386552+00 |
| updated_at | 2025-11-29 13:38:12.467975+00 |
| description | Fast OSM PBF parser for Rust |
| homepage | |
| repository | https://github.com/QuodEstDubitandum/fast-osmpbf |
| max_upload_size | |
| id | 1956087 |
| size | 64,664 |
A high-performance Rust library for reading OpenStreetMap files (*.osm.pbf). This library is focused on performance and provides pretty high-level data. if you need some lower level metadata, you might want to check out other libraries such as osmpbf.
germany-latest.osm.pbf (~4.6GB)Hyperfine was used to benchmark with 10 runs each.
What you see here is the mean time of these 10 runs.
All problems were run using parallelization if the library offered a way to do it.
| Problem | fast-osmpbf | osmpbf | osmpbfreader |
|---|---|---|---|
| Count ways | 13.51 s | 19.06 s | 39.58 s |
| Count addresses | 15.33 s | 21.70 s | 45.45 s |
use fast_osmpbf::*;
fn main() {
let arg = std::env::args_os()
.nth(1)
.expect("need a *.osm.pbf file as argument");
let path = std::path::Path::new(&arg);
let reader = OsmReader::from_path(path).expect("Invalid file path");
// apply filter
reader
.apply_element_filter(ElementFilter {
nodes: false,
relations: false,
ways: true,
})
.expect("Invalid element filter");
// iterate using .blocks() (Parallelization happens, but only for one decoding step)
let mut way_counter = 0;
reader.blocks().for_each(|block| match block {
ElementBlock::WayBlock(block) => {
for _way in block.iter() {
way_counter += 1;
}
}
_ => (),
});
println!("Ways: {:?}", way_counter);
}
use fast_osmpbf::*;
use fast_osmpbf::prelude::*;
pub fn main() {
let arg = std::env::args_os()
.nth(1)
.expect("need a *.osm.pbf file as argument");
let path = std::path::Path::new(&arg);
let reader = OsmReader::from_path(path).expect("Invalid file path");
// apply filter
reader
.apply_tag_filter(&[
"addr:city",
"addr:postcode",
"addr:street",
"addr:housenumber",
])
.expect("Invalid filter applied");
// iterate using .par_blocks() (Parallelization happens on 2 decoding steps)
let address_counter: usize = reader
.par_blocks()
.map(|block| match block {
ElementBlock::DenseNodeBlock(block) => block
.iter()
.filter(|node| node.tags().has_all_filter_keys())
.count(),
ElementBlock::NodeBlock(block) => block
.iter()
.filter(|node| node.tags().has_all_filter_keys())
.count(),
ElementBlock::WayBlock(block) => block
.iter()
.filter(|way| way.tags().has_all_filter_keys())
.count(),
ElementBlock::RelationBlock(block) => block
.iter()
.filter(|rel| rel.tags().has_all_filter_keys())
.count(),
})
.sum();
println!("Addresses: {:?}", address_counter);
}
This project is licensed under