Fastest Geospatial Desktop Stack

Benchmarks across the three layers of a geospatial desktop app — rendering, shell, and data path — measured on an Apple M2 Max, 120 Hz. Source: geo-desktop-bench.

Verdict: Tauri + deck.gl + DuckDB/PMTiles — single-file, server-less, offline-capable. Tauri wins the metrics that constrain a desktop app (3.2 MB binary, ~97 MB RAM) by ~86× and ~4.5× over Electron; deck.gl renders to millions of points at 120 fps; DuckDB answers spatial queries in ~1.5 ms and PMTiles serves vector tiles with no server.

Live demos

Render sweep →

WebGL2 vs deck.gl vs MapLibre across 100k–10M points. Hit "sweep".

PMTiles basemap →

MapLibre streaming Firenze vector tiles by byte-range — no tile server.

Web capstone →

DuckDB-WASM query → deck.gl, over a PMTiles basemap. The whole stack in a tab.

The desktop capstone (DuckDB-on-Rust in Tauri) is native — see the repo. The web capstone above is the in-browser equivalent (DuckDB-WASM).

Rendering — deck.gl vs MapLibre vs raw WebGL2

Same synthetic point cloud, same deterministic camera path, frame-time percentiles (8.33 ms = a 120 Hz frame).

pointsWebGL2 (raw)deck.glMapLibre
100k120 fps120 fps120 fps
1M120 fps120 fps120 fps¹
3M120 fps105 fps
10M97 fps40 fps

Native render — maplibre-rs (wgpu → Metal), no webview

Every engine above draws inside the webview's WebGL2 context. maplibre-rs is the other corner of the design space: a Rust vector-tile renderer that goes straight to Metal through wgpu — no webview, so the WKWebView WebGPU gate that limits a Tauri app simply doesn't apply. Same firenze.pmtiles basemap as the PMTiles demo, driven by a deterministic camera path (rotate + tilt over the resident tile), rendered offscreen on the M2 Max.

basemap renderp50p95p99jankvsync cap
maplibre-rs — native wgpu / Metal1.66 ms1.87 ms2.94 ms0%none
MapLibre GL JS — in webview (WebGL2)⁴8.33 ms

Desktop shell — Tauri vs Electron

metricTauriElectronwinner
app size3.2 MB275 MBTauri ~86×
idle RSS~97 MB²~438 MBTauri ~4.5×
cold start429 ms³259 ms³~tie
IPC / call217 µs52 µsElectron ~4×

Data path — DuckDB-spatial & PMTiles

operationlatency
DuckDB bbox · plain lon/lat BETWEEN (1M rows)1.5 ms
DuckDB bbox · ST_Within + R-tree39 ms
DuckDB k-nearest 50 · ST_Distance4.7 ms
PMTiles getZxy — cold (read + decode)0.57 ms
PMTiles getZxy — warm (cached)0.49 ms

Method & caveats