Benchmarks Web maps
Candidates
MapLibre GL JS vs Mapbox GL JS
Tick the candidates you care about and the charts, winners and table redraw for just them: same run, same rig, same samples. Winners come from the numbers alone; the story is in the post.
Startup timeline
Test 1 Load, fades off
Map constructed until the load event with fadeDuration 0: style, every tile in the view fetched and parsed, everything drawn once. The one startup mark that means the same amount of work in all three builds. (LOWER ms = FASTER)
Test 2 Bundle import
Script or module tag inserted until the library has evaluated, from the loopback server. (LOWER ms = FASTER)
Test 3 Style load
Map constructed until the style.load event: style JSON fetched and parsed, layers created. (LOWER ms = FASTER)
Test 4 First tile
Map constructed until the first vector tile has been fetched and parsed by a worker. (LOWER ms = FASTER)
Test 5 Load, default fade
Map constructed until the load event with the default 300 ms fade. mapbox-gl 1.13 holds this event until its tile fade has finished; the MapLibre builds do not, so this mark is what each build reports, not the same amount of work. (LOWER ms = FASTER)
Test 6 First idle, default fade
Map constructed until the first idle event after load with the default 300 ms fade. mapbox-gl 1.13 also holds idle until its label fade has finished; the MapLibre builds fire idle within a few milliseconds of load. (LOWER ms = FASTER)
Test 7 GeoJSON, 5,000 buildings
A pre-parsed FeatureCollection of 5,000 Berlin building footprints added as a fill layer to the idle map, until the next idle. (LOWER ms = FASTER)
Winner Mapbox GL JS 1.13 (221.5 ms)
Frame time
Test 1 Cold pan, per view
Mean time per view over the 60-view camera path, each view advanced only when the map reports idle, so fetch, parse, layout and paint are all inside it. (LOWER ms = FASTER)
Test 2 Warm paint, per frame
Mean time per frame over the 600-step camera path, the camera moved on every render event, vsync and the frame-rate limit off. Every tile the cold pan loaded is resident; tiles only needed at intermediate camera states are still requested and abandoned as the camera moves on, and those requests are counted beside the timings and included in the frame time. (LOWER ms = FASTER)
Winner MapLibre GL JS 6 (3.0 ms)
Memory
Test 1 After first idle
Renderer and GPU process memory over a blank page, once the initial view has settled. (LOWER MB = FASTER)
Test 2 After the camera path
Renderer and GPU process memory over a blank page after the 60-view cold pan, with each library's default tile cache. (LOWER MB = FASTER)
Winner MapLibre GL JS 5 (918.9 MB)
Test conditions: rig, corpus, protocol
- Machine
- BOSGAME EffiZen ARB19B mini PC
- Chip
- AMD Ryzen 7 6800H with Radeon Graphics
- Cores
- 8 cores / 16 threads
- Memory
- 24 GB at 4800 MT/s
- OS
- Microsoft Windows 11 Pro 26H2 (build 26300) (x64)
- Runtime
- Playwright 1.62.1 Chromium 151.0.7922.34 headless shell; Bun 1.4.0 harness and loopback static server
- GPU
- AMD Radeon 680M, integrated in the Ryzen 7 6800H, driver 32.0.21030.2001 (2025-09-24)
- Browser
- Chromium 151.0.7922.34, ANGLE (AMD, AMD Radeon(TM) Graphics (0x00001681) Direct3D11 vs_5_0 ps_5_0, D3D11); flags --use-angle=d3d11 --use-gl=angle --ignore-gpu-blocklist --disable-gpu-vsync --disable-frame-rate-limit --disable-background-timer-throttling --disable-renderer-backgrounding
- Display
- 1280x800 at 1x, offscreen; 1920x1080 at 59 Hz attached
- Warmups
- 2 unmeasured passes
- Measured
- 15 passes per tool
- Process
- One Chromium process for startup and frame time, fresh browser context per pass, candidates interleaved and rotated each pass; 15 memory samples with a fresh browser process each; every request outside loopback fails at the resolver and any attempt invalidates the run
- Cache
- Fresh context per pass, no HTTP cache; timing passes run with maxTileCacheSize 10000 so the warm traversal is warm, memory samples with each library's default tile cache; tiles served gzip from one MBTiles by the harness
- Output
- The map's own events timed with performance.now() under cross-origin isolation; Playwright screenshots and queryRenderedFeatures for the parity gate; process memory from the OS
Scorecard
| Candidate | Startup timeline (ms, lower is better) | Frame time (ms, lower is better) | Memory (MB, lower is better) |
|---|---|---|---|
| Mapbox GL JS 1.13 | 221.5 ms | 6.6 ms | 1,393.2 MB |
| MapLibre GL JS 5 | 328.3 ms | 3.1 ms | 918.9 MB |
| MapLibre GL JS 6 | 290.6 ms | 3.0 ms | 1,113.3 MB |
Mapbox and Mapbox GL JS are trademarks of Mapbox, Inc. mapbox-gl 1.13.3 is used under its BSD-3-Clause license. MapLibre is a project of the MapLibre organization; maplibre-gl is BSD-3-Clause. Map data: OpenStreetMap contributors, ODbL, via the Geofabrik Berlin extract of 2026-01-01, cut with planetiler. Style: OSM Bright by OpenMapTiles, BSD-3-Clause. Glyphs: Noto Sans, SIL Open Font License.