Skip to content

perf: cap the mbtiles write buffer and hand out tile batches on demand - #966

Open
dktue wants to merge 1 commit into
systemed:masterfrom
dktue:perf/tile-phase-memory
Open

dktue wants to merge 1 commit into
systemed:masterfrom
dktue:perf/tile-phase-memory

Conversation

@dktue

@dktue dktue commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Gain (planet, 32 threads): anonymous memory peak 25.4 → 12.4 GB (−51%), malloc held 27.2 → 14.0 GB (−49%), write buffer peak 3.2 → 0.24 GB. Wall time unchanged within noise (2,449 → 2,482 s).

On a planet build, two things in the tile-writing phase hold far more memory than needed. glibc never returns that memory to the OS, so each early peak stays in RSS until the run ends.

All tile batches were posted to the thread pool up front. A planet has ~14M batches, and each queued handler captured options and sortOrders by value. That is ~15 GB in use as soon as the tile phase starts. Now each of the threadNum workers takes the next batch from a mutex-guarded counter. The batches themselves (and so the output) are unchanged.

The mbtiles write buffer had no limit. While SQLite is busy, finished tiles are copied into pendingStatements. When tile generation outpaces the single SQLite writer, this grows to millions of tiles (3.2 GB in one burst on the planet with #961). The buffer is now capped at 256 MB. Past the cap, a worker waits for the SQLite lock, writes its tile and drains the buffer.

Planet, 32 threads, --store, openmaptiles config

Measured with mallinfo2() sampled every 10 s and /proc/PID/status. Baseline = #949 + #961.

before after
anon RSS peak 25.4 GB 12.4 GB
malloc held, peak 27.2 GB 14.0 GB
write buffer peak 3.2 GB 0.24 GB
wall 2449 s 2482 s

The wall-time difference is within run-to-run noise on a shared server. Without #961 (slower tile workers) the buffer peaked at 0.7 GB, but the up-front batches cost the same ~15 GB.

Germany output is unchanged (same tiles and features; only poi, which already differs between identical runs).

🤖 Generated with Claude Code

All ~14M planet tile batches were posted to the thread pool up front,
each handler copying options and sortOrders (~15 GB at the start of the
tile phase). Workers now take the next batch from a shared counter; the
batch partition, and so the output, is unchanged.

The mbtiles pending-statement buffer had no limit and reached 3.2 GB on
the planet. It is now capped at 256 MB; past that, a worker waits for
the SQLite lock and drains the buffer itself.

Planet anon RSS peak 25.4 GB -> 12.4 GB, wall time unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant