127 lines
5.1 KiB
C++
127 lines
5.1 KiB
C++
/* 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 <bit>
|
|
|
|
#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.
|
|
|
|
// 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;
|
|
static constexpr size_t kMinSubPageClass = 4_KiB;
|
|
|
|
// 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 = kMinSubPageClass - 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");
|
|
static_assert(std::has_single_bit(kMinSubPageClass),
|
|
"kMinSubPageClass is not a power of two");
|
|
|
|
// Number of quantum-spaced classes. We add kQuantum(Max) before subtracting to
|
|
// avoid underflow when a class is empty (Max<Min).
|
|
static constexpr size_t kNumQuantumClasses =
|
|
(kMaxQuantumClass + kQuantum - kMinQuantumClass) / kQuantum;
|
|
static constexpr size_t kNumQuantumWideClasses =
|
|
(kMaxQuantumWideClass + kQuantumWide - kMinQuantumWideClass) / kQuantumWide;
|
|
|
|
// Size and alignment of memory chunks that are allocated by the OS's virtual
|
|
// memory system.
|
|
static constexpr size_t kChunkSize = 1_MiB;
|
|
static constexpr size_t kChunkSizeMask = kChunkSize - 1;
|
|
|
|
// Maximum size of L1 cache line. This is used to avoid cache line aliasing,
|
|
// so over-estimates are okay (up to a point), but under-estimates will
|
|
// negatively affect performance.
|
|
constexpr size_t kCacheLineSize =
|
|
#if defined(XP_DARWIN) && defined(__aarch64__)
|
|
128
|
|
#else
|
|
64
|
|
#endif
|
|
;
|
|
constexpr size_t kCacheLineMask = kCacheLineSize - 1;
|
|
|
|
// Recycle at most 128 MiB of chunks. This means we retain at most
|
|
// 6.25% of the process address space on a 32-bit OS for later use.
|
|
static constexpr size_t gRecycleLimit = 128_MiB;
|
|
|
|
#endif /* ! CONSTANTS_H */
|