/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef CONSTANTS_H #define CONSTANTS_H #include "mozilla/Literals.h" #include #include "Utils.h" // This file contains compile-time connstants that don't depend on sizes of // structures or the page size. It can be included before defining // structures and classes. Other runtime or structure-dependant options are // in options.h // On Linux, we use madvise(MADV_DONTNEED) to release memory back to the // operating system. If we release 1MB of live pages with MADV_DONTNEED, our // RSS will decrease by 1MB (almost) immediately. // // On Mac, we use madvise(MADV_FREE). Unlike MADV_DONTNEED on Linux, MADV_FREE // on Mac doesn't cause the OS to release the specified pages immediately; the // OS keeps them in our process until the machine comes under memory pressure. // // It's therefore difficult to measure the process's RSS on Mac, since, in the // absence of memory pressure, the contribution from the heap to RSS will not // decrease due to our madvise calls. // // We therefore define MALLOC_DOUBLE_PURGE on Mac. This causes jemalloc to // track which pages have been MADV_FREE'd. You can then call // jemalloc_purge_freed_pages(), which will force the OS to release those // MADV_FREE'd pages, making the process's RSS reflect its true memory usage. #ifdef XP_DARWIN # define MALLOC_DOUBLE_PURGE #endif #ifdef XP_WIN # define MALLOC_DECOMMIT #endif #ifndef XP_WIN // Newer Linux systems support MADV_FREE, but we're not supporting // that properly. bug #1406304. # if defined(XP_LINUX) && defined(MADV_FREE) # undef MADV_FREE # endif # ifndef MADV_FREE # define MADV_FREE MADV_DONTNEED # endif #endif // Our size classes are inclusive ranges of memory sizes. By describing the // minimums and how memory is allocated in each range the maximums can be // calculated. // In general this should match the logical page size. static constexpr size_t kMinLargeClass = 4_KiB; // On Windows the smallest allocation size must be 8 bytes on 32-bit, 16 bytes // on 64-bit. On Linux and Mac, even malloc(1) must reserve a word's worth of // memory (see Mozilla bug 691003). Mozjemalloc's minimum allocation size is // 16 bytes, regardless of architecture/OS, which limits the number of // allocations per page to 256 to support free lists (Bug 1980047). It turns // out that this has no impact on memory footprint since the size lost due to // internal fragmentation is offset by better external fragmentation. // Smallest quantum-spaced size classes. It could actually also be labelled a // tiny allocation, and is spaced as such from the largest tiny size class. // Tiny classes being powers of 2, this is twice as large as the largest of // them. static constexpr size_t kMinQuantumClass = 16; static constexpr size_t kMinQuantumWideClass = 512; // Amount (quantum) separating quantum-spaced size classes. static constexpr size_t kQuantum = 16; static constexpr size_t kQuantumMask = kQuantum - 1; static constexpr size_t kQuantumWide = 256; static constexpr size_t kQuantumWideMask = kQuantumWide - 1; static constexpr size_t kMaxQuantumClass = kMinQuantumWideClass - kQuantum; static constexpr size_t kMaxQuantumWideClass = kMinLargeClass - kQuantumWide; // We can optimise some divisions to shifts if these are powers of two. static_assert(std::has_single_bit(kQuantum), "kQuantum is not a power of two"); static_assert(std::has_single_bit(kQuantumWide), "kQuantumWide is not a power of two"); static_assert(kMaxQuantumClass % kQuantum == 0, "kMaxQuantumClass is not a multiple of kQuantum"); static_assert(kMaxQuantumWideClass % kQuantumWide == 0, "kMaxQuantumWideClass is not a multiple of kQuantumWide"); static_assert(kQuantum < kQuantumWide, "kQuantum must be smaller than kQuantumWide"); // Number of quantum-spaced classes. We add kQuantum(Max) before subtracting to // avoid underflow when a class is empty (Max