Instant Map / Benchmarks
Measured, and repeatable.
These are the results of the benchmark suite in the repository, run on 2026-11-14 against version 0.1.0. Every number comes from one run of one command, and you can run the same command on your own machine.
The short version
- First map image, desktop
- 45ms
- From the start of the page load, with nothing cached.
- Script run before that image
- 4.6ms
- The loader is 7.5 KB gzipped.
- Main thread per frame while dragging
- 1.70ms
- Out of the 16.7 ms a frame has at 60 frames a second.
- Same drag, low-end phone profile
- 7.46ms
- CPU slowed six times.
In the browser
One visit is: load the page with nothing cached, move the pointer onto the map, drag it, zoom in three levels, then replace the markers with 2,000 and with 10,000. Each figure is the median of 5 visits in Chromium 158.
| Measure | Desktop | Laptop hidpi | Phone mid | Phone low | Unit |
|---|---|---|---|---|---|
| First map image on screen | 45 | 44 | 559 | 1,359 | ms from the start of the page load, nothing cached |
| Script time before the first image | 4.6 | 5.5 | 21.6 | 34.4 | ms of JavaScript run by then |
| Waking the map | 44 | 51 | 211 | 655 | ms from the first pointer move until the map can be dragged |
| Wake until live tiles are drawn | 983 | 983 | 1,815 | 2,416 | ms, includes the hand-over from the image and downloading the tiles |
| Drag, slowest frames | 16.8 | 16.7 | 16.8 | 16.7 | ms per frame at the 95th percentile; 16.7 is a full 60 frames a second |
| Drag, main thread per frame | 1.70 | 4.42 | 6.31 | 7.46 | ms of work per frame, out of 16.7 available |
| Drag, slow frames | 0.0 | 0.0 | 0.0 | 0.0 | % of frames that took longer than 25 ms |
| Zoom, slowest frames | 16.8 | 16.7 | 16.8 | 16.7 | ms per frame at the 95th percentile |
| Replace with 2,000 markers | 29 | 30 | 33 | 55 | ms until they are drawn |
| Replace with 10,000 markers | 42 | 40 | 71 | 132 | ms until they are drawn |
| Blocking time, whole visit | 0 | 0 | 6 | 105 | ms of main-thread tasks beyond 50 ms each |
| Script time, whole visit | 82 | 72 | 239 | 382 | ms of JavaScript for load, wake, drag, zoom and markers |
| JavaScript memory after the visit | 3.8 | 3.4 | 3.1 | 3.4 | MB |
The device profiles
- Desktop. Desktop, 1280×800, CPU as it is, no network limit.
- Laptop hidpi. High-density laptop, 1440×900 at 2×, CPU as it is, no network limit.
- Phone mid. Mid-range phone, 390×844 at 3×, CPU 4× slower, 9 Mbps down with 60 ms latency.
- Phone low. Low-end phone, 360×780 at 2×, CPU 6× slower, 1.6 Mbps down with 150 ms latency.
The phone profiles slow the CPU and the network of the test machine. They imitate slower devices; they are not measurements on real phones.
Other browser engines
The same visit in the other engines, on the desktop and laptop profiles. CPU and network limits, script time and memory are only available in Chromium, so those rows are left out here.
| Measure | Firefox, desktop | Firefox, laptop hidpi | WebKit, desktop | WebKit, laptop hidpi | Unit |
|---|---|---|---|---|---|
| First map image on screen | 45 | 52 | 44 | 42 | ms from the start of the page load, nothing cached |
| Waking the map | 44 | 48 | 29 | 30 | ms from the first pointer move until the map can be dragged |
| Wake until live tiles are drawn | 959 | 963 | 960 | 963 | ms, includes the hand-over from the image and downloading the tiles |
| Drag, slowest frames | 9.0 | 9.1 | 17.0 | 17.0 | ms per frame at the 95th percentile; 16.7 is a full 60 frames a second |
| Drag, slow frames | 0.0 | 0.0 | 0.0 | 0.0 | % of frames that took longer than 25 ms |
| Zoom, slowest frames | 9.1 | 9.0 | 18.0 | 18.0 | ms per frame at the 95th percentile |
| Replace with 2,000 markers | 11 | 12 | 28 | 29 | ms until they are drawn |
| Replace with 10,000 markers | 38 | 42 | 37 | 35 | ms until they are drawn |
| Blocking time, whole visit | 0 | 0 | 0 | 0 | ms of main-thread tasks beyond 50 ms each |
Drawing a picture on the server
Time for one HTTP request to the image service, running locally with map data on the same machine. “First” is a picture that has to be drawn. “Again” is the same address a second time, answered from cache.
| Request | First, ms | Again, ms | Size, KB |
|---|---|---|---|
| One 512-point tile, JPEG | 35 | 2.6 | 64 |
| One 512-point tile at 2×, JPEG | 81 | 2.8 | 122 |
| One 512-point tile at 2×, PNG | 119 | 3.2 | 445 |
| First image, 960×540 at 2×, no markers | 160 | 3.0 | 258 |
| First image, 960×540 at 2×, 50 markers | 171 | 3.4 | 283 |
| First image, 960×540 at 2×, 400 markers | 274 | 4.0 | 334 |
A deployed service adds the time to fetch map data, which depends on where that data is kept. Run the suite against your own deployment with bun run bench --url https://your-domain.
The renderer by itself
The Rust renderer, compiled natively, turning vector tiles into a JPEG. Median of 30 runs, in milliseconds.
| Picture | Pixels | Read tiles | Draw | Encode | Total | Size, KB |
|---|---|---|---|---|---|---|
| City tile | 512×512 | 0.2 | 20.8 | 1.7 | 22.8 | 63 |
| City tile at 2× | 1024×1024 | 0.2 | 57.7 | 6.4 | 64.8 | 128 |
| Metro-area tile at 2× | 1024×1024 | 0.2 | 59.5 | 6.3 | 66.9 | 135 |
| Regional tile at 2× | 1024×1024 | 0.2 | 31.3 | 5.9 | 37.6 | 84 |
| Country-scale tile at 2× | 1024×1024 | 0.2 | 24.6 | 5.8 | 30.7 | 59 |
| First image, city, at 2× | 1920×1080 | 0.3 | 99.3 | 12.3 | 111.7 | 232 |
| First image, city, 400 markers, at 2× | 1920×1080 | 0.3 | 102.9 | 12.2 | 115.8 | 251 |
| First image, country scale | 1280×800 | 0.2 | 21.2 | 5.4 | 27.0 | 92 |
How this was measured
The machine
Apple M5 Pro, 18 cores, 48 GB of memory, macOS, arm64. Source at commit
4331ed4.No network in the way
The image service and the map data run on the test machine, so results do not depend on a connection or on what happens to be cached elsewhere. The phone profiles add a network limit on purpose.
The slower path to the first image
The test page lets the script create the first image. A page that puts the image in its HTML, as the guides recommend, shows it sooner, because nothing waits for a script.
Medians, fresh every time
Each visit starts in a new browser profile with an empty cache, against an image service that has already drawn the pictures, as a service in use has. The tables show the median; the result file also holds the fastest run and the 90th percentile.
Timings change from machine to machine and from run to run. Compare numbers measured on the same machine, and treat differences of a few percent as noise.
Run it yourself
One command runs the renderer, server and browser benchmarks and writes a JSON file. Another records a profile, so you can see where the time goes.
Benchmark and profiling guide on GitHubThe full result file
Terminal
git clone https://github.com/williamrogersdev/instantmap.git && cd instantmap
bun install && (cd worker && bun install) && bun run build
bun run bench