A fast, offline, reverse geocoder

Overview

Rust Reverse Geocoder

A fast reverse geocoder in Rust. Inspired by Python reverse-geocoder.

Links

Description

rrgeo takes a latitude and longitude as input and returns the closest city, country, latitude, and longitude, using a k-d tree to efficiently find the nearest neighbour based on a known list of locations. This can be useful if you need to reverse geocode a large number of coordinates quickly, or just need the rough location of coordinates but don't want the expense or complication of an online reverse geocoder.

This crate is implemented as a library, an Actix REST API, a Warp REST API, and as a command-line utility, thanks to Cargo workspaces.

Usage

Command line search

Example usage:

> cargo run -p rrgeo-cmd --release 40 -73
0 ms to search
Location: (40.72788, -73.09761): West Sayville, New York, Suffolk County, US
Distance: 0.539337006499999

Actix Web Server

Example usage:

cargo run -p rrgeo-actix --release

Navigate to the local web server.

Warp Web Server

Example usage:

cargo run -p rrgeo-warp --release

Navigate to the local web server.

Benchmarks

Benchmarked on Apple M1.

  • Core library benchmarked with cargo bench and criterion
  • Web servers benchmarked with oha

Core library:

> cargo bench
search                  time:   [489.30 us 490.03 us 490.94 us]

Served via Actix Web:

> cargo run --release --bin rrgeo-actix
> oha http://localhost:3000/\?lat\=40\&long\=\-73 -z 5sec
Summary:
  Success rate:	1.0000
  Total:	5.0069 secs
  Slowest:	0.1105 secs
  Fastest:	0.0012 secs
  Average:	0.0079 secs
  Requests/sec:	5773.4290

  Total data:	3.17 MiB
  Size/request:	115 B
  Size/sec:	648.38 KiB

Response time histogram:
  0.002 [451]  |■
  0.004 [4146] |■■■■■■■■■■■■■
  0.006 [9914] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.008 [7200] |■■■■■■■■■■■■■■■■■■■■■■■
  0.010 [4414] |■■■■■■■■■■■■■■
  0.012 [1915] |■■■■■■
  0.014 [557]  |■
  0.016 [160]  |
  0.018 [59]   |
  0.020 [18]   |
  0.023 [73]   |

Latency distribution:
  10% in 0.0048 secs
  25% in 0.0059 secs
  50% in 0.0073 secs
  75% in 0.0093 secs
  90% in 0.0113 secs
  95% in 0.0126 secs
  99% in 0.0157 secs

Details (average, fastest, slowest):
  DNS+dialup:	0.0018 secs, 0.0013 secs, 0.0029 secs
  DNS-lookup:	0.0002 secs, 0.0000 secs, 0.0013 secs

Status code distribution:
  [200] 28907 responses

Served via Warp:

> cargo run --release --bin rrgeo-warp
> oha http://localhost:3000/\?lat\=40\&long\=\-73 -z 5sec
Summary:
  Success rate:	1.0000
  Total:	5.0040 secs
  Slowest:	0.0812 secs
  Fastest:	0.0008 secs
  Average:	0.0078 secs
  Requests/sec:	5883.9353

  Total data:	4.35 MiB
  Size/request:	155 B
  Size/sec:	890.63 KiB

Response time histogram:
  0.002 [1237] |■■■■
  0.004 [3309] |■■■■■■■■■■■
  0.006 [7022] |■■■■■■■■■■■■■■■■■■■■■■■■■
  0.008 [8985] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.010 [5565] |■■■■■■■■■■■■■■■■■■■
  0.012 [2402] |■■■■■■■■
  0.014 [648]  |■■
  0.016 [173]  |
  0.019 [35]   |
  0.021 [7]    |
  0.023 [60]   |

Latency distribution:
  10% in 0.0041 secs
  25% in 0.0058 secs
  50% in 0.0077 secs
  75% in 0.0095 secs
  90% in 0.0113 secs
  95% in 0.0123 secs
  99% in 0.0151 secs

Details (average, fastest, slowest):
  DNS+dialup:	0.0015 secs, 0.0013 secs, 0.0019 secs
  DNS-lookup:	0.0001 secs, 0.0000 secs, 0.0004 secs

Status code distribution:
  [200] 29443 responses

License

Licensed under either of

at your option.

Comments
  • Replace old dependencies for reverse-geocoder

    Replace old dependencies for reverse-geocoder

    Currently, it uses rustc-serialize which has been deprecated in favor of serde (https://crates.io/crates/rustc-serialize) and quick-csv, which depends on rustc-serialize and has not been updated in 5 years.

    opened by jqnatividad 3
  • use new_with_capacity to reduce allocations

    use new_with_capacity to reduce allocations

    I also made the lookup return an Option<&Record> so clients can choose themselves if they want to clone, and rewrote some code to be more rustic.

    opened by llogiq 2
  • performance: switch to kiddo kd tree library for ~800x improvement on benchmark 😲

    performance: switch to kiddo kd tree library for ~800x improvement on benchmark 😲

    I tried a little experiment and switched out the old kdtree library for kiddo, a performance-improved fork of the now 2-year-old kdtree. (fair disclosure: I'm the maintainer of kiddo).

    This resulted in a huge improvement in performance on the benchmark. Tested on a Ryzen 5900X, I got the following result for the old master branch:

    image

    316.1 microseconds.

    After my refactoring, I got the following result:

    image

    409.9 nanoseconds - i.e. 0.4 microseconds! Faster by a factor of 790 😎

    opened by sdd 1
  • use quick-csv

    use quick-csv

    Gets tiny boost using quick-csv instead of csv

    csv
    $ time target/release/rreverse
    PT0.355788687S seconds to load cities.csv
    PT0.214264474S seconds to build the KdTree
    (44.9483, -93.34801): Saint Louis Park Minnesota Hennepin County US
    
    real    0m0.616s
    user    0m0.548s
    sys 0m0.068s
    
    quick-csv
    $ time target/release/rreverse
    PT0.276284187S seconds to load cities.csv
    PT0.212306487S seconds to build the KdTree
    (44.9483, -93.34801): Saint Louis Park Minnesota Hennepin County US
    
    real    0m0.539s
    user    0m0.468s
    sys 0m0.068s
    
    opened by tafia 1
  • Bump axum-core from 0.2.7 to 0.2.8

    Bump axum-core from 0.2.7 to 0.2.8

    Bumps axum-core from 0.2.7 to 0.2.8.

    Release notes

    Sourced from axum-core's releases.

    axum-core - v0.2.8

    Security

    • breaking: Added default limit to how much data Bytes::from_request will consume. Previously it would attempt to consume the entire request body without checking its length. This meant if a malicious peer sent an large (or infinite) request body your server might run out of memory and crash.

      The default limit is at 2 MB and can be disabled by adding the new DefaultBodyLimit::disable() middleware. See its documentation for more details.

      This also applies to String which used Bytes::from_request internally.

      (#1346)

    #1346: tokio-rs/axum#1346

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • V2.0

    V2.0

    V2.0

    Update and improve error handling and function signatures.

    • Simplify the search API function signature
    • Use standard 2018 edition Rust error handling idioms
    • actix_web handler demonstrating exhaustive match of all errors
    opened by gx0r 0
  • More information about bundled cities.csv file

    More information about bundled cities.csv file

    Hi @gx0r ! First off, thanks again for this awesome library!

    However, could you include some information on how the bundled cities.csv was prepared?

    Specifically, how it was transformed to its current format from the files published by Geonames here - http://download.geonames.org/export/dump/?

    Also, having a README when the cities.csv file was last updated would be great too!

    I'm asking as I'd like to take advantage of the Locations::from_path method to upload the latest version from Geonames.

    opened by jqnatividad 2
Owner
Grant Miner
Grant Miner
Reverse-geocoder microservice

Reverse Geocoder This is a simple and very lightweight reverse geocoder for offline use. It's implemented in Rust and uses a k-d-tree to find the clos

Treestack GmbH 3 May 12, 2023
A set of tools for generating isochrones and reverse isochrones from geographic coordinates

This library provides a set of tools for generating isochrones and reverse isochrones from geographic coordinates. It leverages OpenStreetMap data to construct road networks and calculate areas accessible within specified time limits.

null 3 Feb 22, 2024
Fast Geospatial Feature Storage API

Hecate OpenStreetMap Inspired Data Storage Backend Focused on Performance and GeoJSON Interchange Hecate Feature Comparison Feature Hecate ESRI MapSer

Mapbox 243 Dec 19, 2022
Blazing fast and lightweight PostGIS vector tiles server

Martin Martin is a PostGIS vector tiles server suitable for large databases. Martin is written in Rust using Actix web framework. Requirements Install

Urbica 921 Jan 7, 2023
Fast 2D Delaunay triangulation in Rust. A port of Delaunator.

delaunator-rs A very fast static 2D Delaunay triangulation library for Rust. A port of Delaunator. Documentation Example use delaunator::{Point, trian

Vladimir Agafonkin 123 Dec 20, 2022
Fast shortest path calculations for Rust

Fast Paths The most famous algorithms used to calculate shortest paths are probably Dijkstra's algorithm and A*. However, shortest path calculation ca

Andi 226 Jan 2, 2023
A fast R-tree for Rust. Ported from an implementation that's designed for Tile38.

rtree.rs A fast R-tree for Rust. Ported from an implementation that's designed for Tile38. Features Optimized for fast inserts and updates. Ideal for

Josh Baker 102 Dec 30, 2022
Trees for fast location-to-value lookup.

HexTree hextree provides tree structures that represent geographic regions with H3 cells. The primary structures are: HexTreeMap: an H3 cell-to-value

Jay Kickliter 38 Dec 15, 2022
A fast, offline reverse geocoder in Python

Reverse Geocoder A Python library for offline reverse geocoding. It improves on an existing library called reverse_geocode developed by Richard Penman

Ajay Thampi 1.8k Dec 26, 2022
A fast, offline, reverse geocoder

Rust Reverse Geocoder A fast reverse geocoder in Rust. Inspired by Python reverse-geocoder. Links Crate Changelog Latest Docs v2.0 Docs v1.0 Docs Desc

Grant Miner 82 Dec 3, 2022
Reverse-geocoder microservice

Reverse Geocoder This is a simple and very lightweight reverse geocoder for offline use. It's implemented in Rust and uses a k-d-tree to find the clos

Treestack GmbH 3 May 12, 2023
A Rust library containing an offline version of webster's dictionary.

webster-rs A Rust library containing an offline version of webster's dictionary. Add to Cargo.toml webster = 0.3.0 Simple example: fn main() { le

Grant Handy 12 Sep 27, 2022
An end-to-end encrypted, anonymous IP-hiding, decentralized, audio/video/file sharing/offline messaging multi-device platform built for both communications and application security and performance.

An end-to-end encrypted, anonymous IP-hiding, decentralized, audio/video/file sharing/offline messaging multi-device platform built for both communications and application security and performance.

null 2 Apr 27, 2022
Find out who is pretending to be offline

Dinkleberg Find out who is pretending to be offline Preview Disclaimer Dinkleberg was developed for educational, private and fair use. I am not respon

oSumAtrIX 40 Dec 28, 2022
Offline-viewer for registry files

regview Offline-viewer for registry files Usage regview 0.1.4 Offline-viewer for registry files USAGE: regview [FLAGS] <REG_FILE> FLAGS:

Jan Starke 8 Dec 9, 2022
Create tasks and save notes offline from your terminal

Create tasks and save notes offline from your terminal

null 9 Dec 18, 2022
Bitcoin PSBT signer, descriptor exporter and more for offline devices.

KeeChain Description KeeChain is a Bitcoin application to transform your offline computer in an AirGap Signing Device (aka Hardware Wallet). Getting s

Yuki Kishimoto 3 Dec 15, 2022
Briolette is an experimental framework for researching offline digital currency designs.

Briolette - experimental framework for offline-enabled digital currency Briolette is an experimental framework for researching offline digital currenc

Google 39 Apr 9, 2023
🐚+🦞 Ultra-portable Rust game engine suited for offline 2D games powered by WebAssembly

pagurus ?? + ?? Ultra-portable Rust game engine suited for offline 2D games powered by WebAssembly. Examples Snake Traditional snake game: examples/sn

Takeru Ohta 20 Mar 7, 2023
Crates Registry is a tool for serving and publishing crates and serving rustup installation in offline networks.

Crates Registry Description Crates Registry is a tool for serving and publishing crates and serving rustup installation in offline networks. (like Ver

TalYRoni 5 Jul 6, 2023