Show HN: Fast Elevation API with memory mapped tiles
terraintap.comI recently wrote and launched a high-performance Elevation API, built from the ground up, in C. I was highly inspired by the handmade community and I was intrigued by the idea of handling fairly large datasets and optimizing caching and smart prefetching, and to cream out maximum performance in terms of latency and handling large loads.
The whole thing is built from scratch. I wanted to roll my own high performance server that could handle a lot, mostly for the technical challenge but also because it brings down hosting costs.
At the core is a hand made TCP server where a single thread handles all I/O via epoll, distributing the events to a pool of worker threads. The server is fully non-blocking and edge-triggered, with a minimal syscall footprint during steady-state operation.
Worker threads handle request parsing and perform either direct elevation lookups for single- or multi-points, or compute sample points along polyline paths.
The elevation data is stored as memory mapped geotiff raster tiles, The tiles are indexed in an R-tree for fast lookup. Given a coordinate, the correct tile is located with a bounding-box search algorithm through the tree, and the elevation value is extracted directly from the mapped memory. If the tile is missing the data, underlying tiles act as fallback.
I also implemented a prefetching mechanism. That is, to avoid repeated page faults in popular areas, I employ a strategy where each tile is divided into smaller sub-tiles. Then, I have a running popularity count per sub-tile. This information is then used to guide prefetching. More popular sub-tiles trigger larger-radius prefetches around the lookup point, with the logic that if a specific region is seeing frequent access, it’s worth pulling in more of it into RAM. Over time, this makes the memory layout adapt to real usage patterns, keeping hot areas resident and minimizing I/O latency. Prefetching is done using linux madvise, in a separate prefetch thread to not affect request latency.
There’s a free option to try it out!