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)

Load, fades off (ms)
Mapbox GL JS 1.13221.5 ms
MapLibre GL JS 5328.3 ms
MapLibre GL JS 6290.6 ms
Load, fades off in ms
Mapbox GL JS 1.13221.5 ms
MapLibre GL JS 5328.3 ms
MapLibre GL JS 6290.6 ms

Test 2 Bundle import

Script or module tag inserted until the library has evaluated, from the loopback server. (LOWER ms = FASTER)

Bundle import (ms)
Mapbox GL JS 1.1324.7 ms
MapLibre GL JS 531.0 ms
MapLibre GL JS 629.0 ms
Bundle import in ms
Mapbox GL JS 1.1324.7 ms
MapLibre GL JS 531.0 ms
MapLibre GL JS 629.0 ms

Test 3 Style load

Map constructed until the style.load event: style JSON fetched and parsed, layers created. (LOWER ms = FASTER)

Style load (ms)
Mapbox GL JS 1.1333.9 ms
MapLibre GL JS 533.2 ms
MapLibre GL JS 632.7 ms
Style load in ms
Mapbox GL JS 1.1333.9 ms
MapLibre GL JS 533.2 ms
MapLibre GL JS 632.7 ms

Test 4 First tile

Map constructed until the first vector tile has been fetched and parsed by a worker. (LOWER ms = FASTER)

First tile (ms)
Mapbox GL JS 1.13149.5 ms
MapLibre GL JS 5261.1 ms
MapLibre GL JS 6232.9 ms
First tile in ms
Mapbox GL JS 1.13149.5 ms
MapLibre GL JS 5261.1 ms
MapLibre GL JS 6232.9 ms

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)

Load, default fade (ms)
Mapbox GL JS 1.13201.5 ms
MapLibre GL JS 5340.4 ms
MapLibre GL JS 6290.3 ms
Load, default fade in ms
Mapbox GL JS 1.13201.5 ms
MapLibre GL JS 5340.4 ms
MapLibre GL JS 6290.3 ms

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)

First idle, default fade (ms)
Mapbox GL JS 1.13661.6 ms
MapLibre GL JS 5353.1 ms
MapLibre GL JS 6296.6 ms
First idle, default fade in ms
Mapbox GL JS 1.13661.6 ms
MapLibre GL JS 5353.1 ms
MapLibre GL JS 6296.6 ms

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)

GeoJSON, 5,000 buildings (ms)
Mapbox GL JS 1.13394.2 ms
MapLibre GL JS 5351.9 ms
MapLibre GL JS 6275.4 ms
GeoJSON, 5,000 buildings in ms
Mapbox GL JS 1.13394.2 ms
MapLibre GL JS 5351.9 ms
MapLibre GL JS 6275.4 ms

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)

Cold pan, per view (ms)
Mapbox GL JS 1.13628.9 ms
MapLibre GL JS 5700.4 ms
MapLibre GL JS 6594.4 ms
Cold pan, per view in ms
Mapbox GL JS 1.13628.9 ms
MapLibre GL JS 5700.4 ms
MapLibre GL JS 6594.4 ms

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)

Warm paint, per frame (ms)
Mapbox GL JS 1.136.6 ms
MapLibre GL JS 53.1 ms
MapLibre GL JS 63.0 ms
Warm paint, per frame in ms
Mapbox GL JS 1.136.6 ms
MapLibre GL JS 53.1 ms
MapLibre GL JS 63.0 ms

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)

After first idle (MB)
Mapbox GL JS 1.13316.6 MB
MapLibre GL JS 5172.8 MB
MapLibre GL JS 6158 MB
After first idle in MB
Mapbox GL JS 1.13316.6 MB
MapLibre GL JS 5172.8 MB
MapLibre GL JS 6158 MB

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)

After the camera path (MB)
Mapbox GL JS 1.131,393.2 MB
MapLibre GL JS 5918.9 MB
MapLibre GL JS 61,113.3 MB
After the camera path in MB
Mapbox GL JS 1.131,393.2 MB
MapLibre GL JS 5918.9 MB
MapLibre GL JS 61,113.3 MB

Winner MapLibre GL JS 5 (918.9 MB)

Test conditions: rig, corpus, protocol
Rig
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
Protocol
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

Mean of each section's samples for the candidates you picked. The best value in each column is marked in red.
CandidateStartup timeline (ms, lower is better)Frame time (ms, lower is better)Memory (MB, lower is better)
Mapbox GL JS 1.13221.5 ms6.6 ms1,393.2 MB
MapLibre GL JS 5328.3 ms3.1 ms918.9 MB
MapLibre GL JS 6290.6 ms3.0 ms1,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.