Benchmarks¶
How does PyGeoHash compare to the other geohash libraries on PyPI? This page
publishes the numbers rather than leaving the question open. It is generated by
scripts/run_comparison_benchmark.py from the suite in
tests/test_benchmark_comparison.py, which measures every library on identical
work.
What is measured¶
Every library receives the same inputs: latitude 42.6, longitude -5.6 and
precision 9 for encoding, and the geohash ezs42e44y for decoding and
bounding-box lookups. The encode cases assert that each library returns the same
standard geohash, so the comparison is genuinely like for like.
Two libraries offer no bounding-box helper (pygeohash-fast and
geohash-tools), so they appear only in the encode and decode tables. Two
others are excluded from the suite entirely: geohash-hilbert computes a
Hilbert-curve variant rather than a standard geohash, and mzgeohash takes no
precision parameter, so equal work cannot be guaranteed.
The whole suite was run 3 times. Each library’s headline figure is the median of its per-run medians, and the range column gives the lowest and highest median it produced, so the run-to-run movement behind every number is visible. Ops/sec is derived from the headline median, and the final column is each library’s median divided by pygeohash’s.
Encode¶
Encode (42.6, -5.6) to a precision-9 geohash.
Library |
Implementation |
Median (ns) |
Range over 3 runs (ns) |
Ops/sec |
vs pygeohash |
|---|---|---|---|---|---|
geohashr |
Rust extension |
125 |
84 - 166 |
8,005,531 |
0.50x |
pygeohash-fast |
Rust extension |
166 |
125 - 166 |
6,023,797 |
0.66x |
python-geohash |
C++ extension |
208 |
208 - 209 |
4,806,902 |
0.83x |
pygeohash |
C extension |
250 |
250 - 584 |
3,999,038 |
1.00x |
libgeohash |
pure Python |
2,709 |
2,709 - 2,709 |
369,142 |
10.83x |
geohash-tools |
pure Python |
3,792 |
3,792 - 3,833 |
263,713 |
15.16x |
geolib |
pure Python |
10,584 |
10,584 - 10,625 |
94,482 |
42.33x |
On this machine pygeohash takes 1.20x the median time of python-geohash and is 10.8x
faster than libgeohash, the quickest pure-Python entry. geohashr,
pygeohash-fast are faster still.
The repeated runs did not separate geohashr and pygeohash-fast. Their ranges of
medians overlap, so their relative order in the table is within measurement noise and
swaps between runs: read them as tied.
Decode¶
Decode ezs42e44y back to coordinates.
Library |
Implementation |
Median (ns) |
Range over 3 runs (ns) |
Ops/sec |
vs pygeohash |
|---|---|---|---|---|---|
geohashr |
Rust extension |
80 |
80 - 81 |
12,435,484 |
0.24x |
pygeohash-fast |
Rust extension |
167 |
166 - 167 |
5,990,191 |
0.50x |
python-geohash |
C++ extension |
250 |
250 - 250 |
4,000,901 |
0.75x |
pygeohash |
C extension |
333 |
333 - 334 |
3,002,424 |
1.00x |
libgeohash |
pure Python |
2,625 |
2,625 - 2,667 |
380,962 |
7.88x |
geohash-tools |
pure Python |
3,375 |
3,334 - 3,375 |
296,297 |
10.13x |
geolib |
pure Python |
58,208 |
56,916 - 59,313 |
17,180 |
174.77x |
On this machine pygeohash takes 1.33x the median time of python-geohash and is 7.9x
faster than libgeohash, the quickest pure-Python entry. geohashr,
pygeohash-fast are faster still.
Bounding box¶
Look up the bounding box of the ezs42e44y cell.
Library |
Implementation |
Median (ns) |
Range over 3 runs (ns) |
Ops/sec |
vs pygeohash |
|---|---|---|---|---|---|
geohashr |
Rust extension |
104 |
104 - 104 |
9,619,080 |
0.15x |
python-geohash |
C++ extension |
250 |
250 - 291 |
3,999,038 |
0.35x |
pygeohash |
C extension |
709 |
709 - 750 |
1,410,498 |
1.00x |
libgeohash |
pure Python |
2,750 |
2,750 - 2,750 |
363,626 |
3.88x |
geolib |
pure Python |
43,292 |
42,959 - 44,000 |
23,099 |
61.06x |
On this machine pygeohash takes 2.84x the median time of python-geohash and is 3.9x
faster than libgeohash, the quickest pure-Python entry. geohashr is faster
still.
Environment¶
These figures come from repeated runs on one machine. They are not an average across hardware, and they should be read as an ordering rather than as absolute throughput you can expect elsewhere.
Date of run: 2026-08-14 (3 repeats of the suite)
Machine: Apple M4 (arm64, 10 cores)
Operating system: Darwin 25.2.0
Python: CPython 3.12.11
pytest-benchmark: 5.2.3
Installed versions of every library measured:
geohash-tools0.2.0geohashr1.6.0geolib1.0.7libgeohash0.1.1pygeohash3.4.0pygeohash-fast0.3.0python-geohash0.9.2
Reproducing this page¶
From a checkout, with the dev and benchmark extras installed:
uv pip install -e ".[dev,benchmark]"
python scripts/run_comparison_benchmark.py
The script runs the suite several times, reads the pytest-benchmark JSON reports, and rewrites this page with the numbers and the environment it observed. Rerun it on your own machine before quoting any of these figures as your own.
Caveats¶
Every figure is a median from one machine; a benchmark is a draw from a noisy process, not a constant.
The fastest entries take well under a microsecond, which is only tens of ticks of the platform timer, so their medians are coarsely quantized. Where two adjacent entries were not separated by the measurement, the note under the table says so and they should be read as tied.
Only the three operations above are measured. A library that is slower here may be faster on work this suite does not cover.
Install cost is not measured.
pygeohashships pre-built wheels and needs no compiler at install time, which is what motivated the comparison in the first place, but that is a packaging property rather than a speed result.