diff --git a/src/tilemaker.cpp b/src/tilemaker.cpp index 7a7ae1e5..c737981e 100644 --- a/src/tilemaker.cpp +++ b/src/tilemaker.cpp @@ -97,11 +97,19 @@ int main(const int argc, const char* argv[]) { #ifdef __GLIBC__ // glibc raises its mmap threshold dynamically (up to 32/64 MB) once a large // mmapped chunk is freed; multi-MB buffers then land in per-thread arenas - // that are never trimmed, inflating peak RSS. Setting the trim threshold - // explicitly also disables that dynamic adjustment (the mmap threshold - // stays at its 128 KB default), unless the user tunes malloc via the environment. - if (!getenv("MALLOC_TRIM_THRESHOLD_") && !getenv("MALLOC_MMAP_THRESHOLD_") && !getenv("GLIBC_TUNABLES")) { - mallopt(M_TRIM_THRESHOLD, 4 << 20); + // that are never trimmed, inflating peak RSS. Setting malloc parameters + // explicitly turns that dynamic adjustment off, so both are set here: + // - a 16 MB top pad makes the heap grow and shrink in large steps; with many + // threads allocating, the default 128 KB steps cost many brk() calls and + // page faults + // - a fixed 8 MB mmap threshold: otherwise it would stay at 128 KB, and every + // larger buffer would be a fresh mmap with zeroed pages. Boost's validity + // check on a huge polygon grows such buffers over and over (one relation + // with 1.9M points took 3x as long). + // Users who tune malloc via the environment keep their settings. + if (!getenv("MALLOC_TRIM_THRESHOLD_") && !getenv("MALLOC_MMAP_THRESHOLD_") && !getenv("MALLOC_TOP_PAD_") && !getenv("GLIBC_TUNABLES")) { + mallopt(M_TOP_PAD, 16 << 20); + mallopt(M_MMAP_THRESHOLD, 8 << 20); } #endif