2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_MEMORY_MANAGER_H_
18 #define incl_HPHP_MEMORY_MANAGER_H_
24 #include <unordered_map>
27 #include <folly/Memory.h>
29 #include "hphp/util/alloc.h" // must be included before USE_JEMALLOC is used
30 #include "hphp/util/compilation-flags.h"
31 #include "hphp/util/thread-local.h"
32 #include "hphp/util/trace.h"
33 #include "hphp/util/type-scan.h"
35 #include "hphp/runtime/base/memory-usage-stats.h"
36 #include "hphp/runtime/base/request-event-handler.h"
37 #include "hphp/runtime/base/runtime-option.h"
38 #include "hphp/runtime/base/sweepable.h"
39 #include "hphp/runtime/base/header-kind.h"
40 #include "hphp/runtime/base/req-containers.h"
41 #include "hphp/runtime/base/req-malloc.h"
42 #include "hphp/runtime/base/req-ptr.h"
53 void* malloc_big(size_t, type_scan::Index
);
54 void* calloc_big(size_t, type_scan::Index
);
55 void* realloc_big(void*, size_t);
59 //////////////////////////////////////////////////////////////////////
62 * Request local memory in HHVM is managed by a thread local object
63 * called MemoryManager.
65 * The object may be accessed with tl_heap, but higher-level apis are
68 * The MemoryManager serves the following functions in hhvm:
70 * - Managing request-local memory.
72 * - Tracking "sweepable" objects--i.e. objects that must run custom
73 * cleanup code if they are still live at the end of the request.
75 * - Accounting for usage of memory "by this request", whether it
76 * goes through the request-local allocator, or the underlying
77 * malloc implementation. (This feature is gated on being
78 * compiled with jemalloc.)
81 //////////////////////////////////////////////////////////////////////
84 * Slabs are consumed via bump allocation. The individual allocations are
85 * quantized into a fixed set of size classes, the sizes of which are an
86 * implementation detail documented here to shed light on the algorithms that
87 * compute size classes. Request sizes are rounded up to the nearest size in
88 * the relevant SIZE_CLASSES table; e.g. 17 is rounded up to 32. There are
89 * 4 size classes for each doubling of size
90 * (ignoring the alignment-constrained smallest size classes), which limits
91 * internal fragmentation to 20%.
93 * SIZE_CLASSES: Complete table of SIZE_CLASS(index, lg_grp, lg_delta, ndelta,
94 * lg_delta_lookup, ncontig) tuples.
95 * index: Size class index.
96 * lg_grp: Lg group base size (no deltas added).
97 * lg_delta: Lg delta to previous size class.
98 * ndelta: Delta multiplier. size == 1<<lg_grp + ndelta<<lg_delta
99 * lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no'
101 * ncontig: Number of contiguous regions to batch allocate in the slow path
102 * due to the corresponding free list being empty. Must be greater
103 * than zero, and small enough that the contiguous regions fit within
106 #define SIZE_CLASSES \
107 /* index, lg_grp, lg_delta, ndelta, lg_delta_lookup, ncontig */ \
108 SIZE_CLASS( 0, 4, 4, 0, 4, 128) \
109 SIZE_CLASS( 1, 4, 4, 1, 4, 128) \
110 SIZE_CLASS( 2, 4, 4, 2, 4, 128) \
111 SIZE_CLASS( 3, 4, 4, 3, 4, 96) /* 64 */\
113 SIZE_CLASS( 4, 6, 4, 1, 4, 96) \
114 SIZE_CLASS( 5, 6, 4, 2, 4, 96) \
115 SIZE_CLASS( 6, 6, 4, 3, 4, 96) \
116 SIZE_CLASS( 7, 6, 4, 4, 4, 64) /* 128 */\
118 SIZE_CLASS( 8, 7, 5, 1, 5, 64) \
119 SIZE_CLASS( 9, 7, 5, 2, 5, 64) \
120 SIZE_CLASS( 10, 7, 5, 3, 5, 64) \
121 SIZE_CLASS( 11, 7, 5, 4, 5, 32) /* 256 */\
123 SIZE_CLASS( 12, 8, 6, 1, 6, 32) \
124 SIZE_CLASS( 13, 8, 6, 2, 6, 32) \
125 SIZE_CLASS( 14, 8, 6, 3, 6, 32) \
126 SIZE_CLASS( 15, 8, 6, 4, 6, 16) /* 512 */\
128 SIZE_CLASS( 16, 9, 7, 1, 7, 16) \
129 SIZE_CLASS( 17, 9, 7, 2, 7, 16) \
130 SIZE_CLASS( 18, 9, 7, 3, 7, 16) \
131 SIZE_CLASS( 19, 9, 7, 4, 7, 8) /* 1K */\
133 SIZE_CLASS( 20, 10, 8, 1, 8, 8) \
134 SIZE_CLASS( 21, 10, 8, 2, 8, 8) \
135 SIZE_CLASS( 22, 10, 8, 3, 8, 8) \
136 SIZE_CLASS( 23, 10, 8, 4, 8, 4) /* 2K */\
138 SIZE_CLASS( 24, 11, 9, 1, 9, 4) \
139 SIZE_CLASS( 25, 11, 9, 2, 9, 4) \
140 SIZE_CLASS( 26, 11, 9, 3, 9, 4) \
141 SIZE_CLASS( 27, 11, 9, 4, 9, 2) /* 4K */\
143 SIZE_CLASS( 28, 12, 10, 1, no, 2) \
144 SIZE_CLASS( 29, 12, 10, 2, no, 2) \
145 SIZE_CLASS( 30, 12, 10, 3, no, 2) \
146 SIZE_CLASS( 31, 12, 10, 4, no, 1) /* 8K */\
148 SIZE_CLASS( 32, 13, 11, 1, no, 1) \
149 SIZE_CLASS( 33, 13, 11, 2, no, 1) \
150 SIZE_CLASS( 34, 13, 11, 3, no, 1) \
151 SIZE_CLASS( 35, 13, 11, 4, no, 1) /* 16K */\
153 SIZE_CLASS( 36, 14, 12, 1, no, 1) \
154 SIZE_CLASS( 37, 14, 12, 2, no, 1) \
155 SIZE_CLASS( 38, 14, 12, 3, no, 1) \
156 SIZE_CLASS( 39, 14, 12, 4, no, 1) /* 32K */\
158 SIZE_CLASS( 40, 15, 13, 1, no, 1) \
159 SIZE_CLASS( 41, 15, 13, 2, no, 1) \
160 SIZE_CLASS( 42, 15, 13, 3, no, 1) \
161 SIZE_CLASS( 43, 15, 13, 4, no, 1) /* 64K */\
163 SIZE_CLASS( 44, 16, 14, 1, no, 1) \
164 SIZE_CLASS( 45, 16, 14, 2, no, 1) \
165 SIZE_CLASS( 46, 16, 14, 3, no, 1) \
166 SIZE_CLASS( 47, 16, 14, 4, no, 1) /* 128K */\
168 SIZE_CLASS( 48, 17, 15, 1, no, 1) \
169 SIZE_CLASS( 49, 17, 15, 2, no, 1) \
170 SIZE_CLASS( 50, 17, 15, 3, no, 1) \
171 SIZE_CLASS( 51, 17, 15, 4, no, 1) /* 256K */\
173 SIZE_CLASS( 52, 18, 16, 1, no, 1) \
174 SIZE_CLASS( 53, 18, 16, 2, no, 1) \
175 SIZE_CLASS( 54, 18, 16, 3, no, 1) \
176 SIZE_CLASS( 55, 18, 16, 4, no, 1) /* 512K */\
178 SIZE_CLASS( 56, 19, 17, 1, no, 1) \
179 SIZE_CLASS( 57, 19, 17, 2, no, 1) \
180 SIZE_CLASS( 58, 19, 17, 3, no, 1) \
181 SIZE_CLASS( 59, 19, 17, 4, no, 1) /* 1M */\
183 SIZE_CLASS( 60, 20, 18, 1, no, 1) \
184 SIZE_CLASS( 61, 20, 18, 2, no, 1) \
185 SIZE_CLASS( 62, 20, 18, 3, no, 1) \
186 SIZE_CLASS( 63, 20, 18, 4, no, 1) /* 2M */\
188 SIZE_CLASS( 64, 21, 19, 1, no, 1) \
189 SIZE_CLASS( 65, 21, 19, 2, no, 1) \
190 SIZE_CLASS( 66, 21, 19, 3, no, 1) \
191 SIZE_CLASS( 67, 21, 19, 4, no, 1) /* 4M */\
193 SIZE_CLASS( 68, 22, 20, 1, no, 1) \
194 SIZE_CLASS( 69, 22, 20, 2, no, 1) \
195 SIZE_CLASS( 70, 22, 20, 3, no, 1) \
196 SIZE_CLASS( 71, 22, 20, 4, no, 1) /* 8M */\
198 SIZE_CLASS( 72, 23, 21, 1, no, 1) \
199 SIZE_CLASS( 73, 23, 21, 2, no, 1) \
200 SIZE_CLASS( 74, 23, 21, 3, no, 1) \
201 SIZE_CLASS( 75, 23, 21, 4, no, 1) /* 16M */\
203 SIZE_CLASS( 76, 24, 22, 1, no, 1) \
204 SIZE_CLASS( 77, 24, 22, 2, no, 1) \
205 SIZE_CLASS( 78, 24, 22, 3, no, 1) \
206 SIZE_CLASS( 79, 24, 22, 4, no, 1) /* 32M */\
208 SIZE_CLASS( 80, 25, 23, 1, no, 1) \
209 SIZE_CLASS( 81, 25, 23, 2, no, 1) \
210 SIZE_CLASS( 82, 25, 23, 3, no, 1) \
211 SIZE_CLASS( 83, 25, 23, 4, no, 1) /* 64M */\
213 SIZE_CLASS( 84, 26, 24, 1, no, 1) \
214 SIZE_CLASS( 85, 26, 24, 2, no, 1) \
215 SIZE_CLASS( 86, 26, 24, 3, no, 1) \
216 SIZE_CLASS( 87, 26, 24, 4, no, 1) /* 128M */\
218 SIZE_CLASS( 88, 27, 25, 1, no, 1) \
219 SIZE_CLASS( 89, 27, 25, 2, no, 1) \
220 SIZE_CLASS( 90, 27, 25, 3, no, 1) \
221 SIZE_CLASS( 91, 27, 25, 4, no, 1) /* 256M */\
223 SIZE_CLASS( 92, 28, 26, 1, no, 1) \
224 SIZE_CLASS( 93, 28, 26, 2, no, 1) \
225 SIZE_CLASS( 94, 28, 26, 3, no, 1) \
226 SIZE_CLASS( 95, 28, 26, 4, no, 1) /* 512M */\
228 SIZE_CLASS( 96, 29, 27, 1, no, 1) \
229 SIZE_CLASS( 97, 29, 27, 2, no, 1) \
230 SIZE_CLASS( 98, 29, 27, 3, no, 1) \
231 SIZE_CLASS( 99, 29, 27, 4, no, 1) /* 1G */\
233 SIZE_CLASS(100, 30, 28, 1, no, 1) \
234 SIZE_CLASS(101, 30, 28, 2, no, 1) \
235 SIZE_CLASS(102, 30, 28, 3, no, 1) \
236 SIZE_CLASS(103, 30, 28, 4, no, 1) /* 2G */\
238 SIZE_CLASS(104, 31, 29, 1, no, 1) \
239 SIZE_CLASS(105, 31, 29, 2, no, 1) \
240 SIZE_CLASS(106, 31, 29, 3, no, 1) \
241 SIZE_CLASS(107, 31, 29, 4, no, 1) /* 4G */\
243 SIZE_CLASS(108, 32, 30, 1, no, 1) \
244 SIZE_CLASS(109, 32, 30, 2, no, 1) \
245 SIZE_CLASS(110, 32, 30, 3, no, 1) \
246 SIZE_CLASS(111, 32, 30, 4, no, 1) /* 8G */\
248 SIZE_CLASS(112, 33, 31, 1, no, 1) \
249 SIZE_CLASS(113, 33, 31, 2, no, 1) \
250 SIZE_CLASS(114, 33, 31, 3, no, 1) \
251 SIZE_CLASS(115, 33, 31, 4, no, 1) /* 16G */\
253 SIZE_CLASS(116, 34, 32, 1, no, 1) \
254 SIZE_CLASS(117, 34, 32, 2, no, 1) \
255 SIZE_CLASS(118, 34, 32, 3, no, 1) \
256 SIZE_CLASS(119, 34, 32, 4, no, 1) /* 32G */\
258 SIZE_CLASS(120, 35, 33, 1, no, 1) \
259 SIZE_CLASS(121, 35, 33, 2, no, 1) \
260 SIZE_CLASS(122, 35, 33, 3, no, 1) \
261 SIZE_CLASS(123, 35, 33, 4, no, 1) /* 64G */\
263 SIZE_CLASS(124, 36, 34, 1, no, 1) \
264 SIZE_CLASS(125, 36, 34, 2, no, 1) \
265 SIZE_CLASS(126, 36, 34, 3, no, 1) \
266 SIZE_CLASS(127, 36, 34, 4, no, 1) /* 128G */\
268 SIZE_CLASS(128, 37, 35, 1, no, 1) \
269 SIZE_CLASS(129, 37, 35, 2, no, 1) \
270 SIZE_CLASS(130, 37, 35, 3, no, 1) \
271 SIZE_CLASS(131, 37, 35, 4, no, 1) /* 256G */\
273 SIZE_CLASS(132, 38, 36, 1, no, 1) \
274 SIZE_CLASS(133, 38, 36, 2, no, 1) \
275 SIZE_CLASS(134, 38, 36, 3, no, 1) \
276 SIZE_CLASS(135, 38, 36, 4, no, 1) /* 512G */\
278 SIZE_CLASS(136, 39, 37, 1, no, 1) \
279 SIZE_CLASS(137, 39, 37, 2, no, 1) \
280 SIZE_CLASS(138, 39, 37, 3, no, 1) \
281 SIZE_CLASS(139, 39, 37, 4, no, 1) /* 1T */\
283 SIZE_CLASS(140, 40, 38, 1, no, 1) \
284 SIZE_CLASS(141, 40, 38, 2, no, 1) \
285 SIZE_CLASS(142, 40, 38, 3, no, 1) \
286 SIZE_CLASS(143, 40, 38, 4, no, 1) /* 2T */\
288 SIZE_CLASS(144, 41, 39, 1, no, 1) \
289 SIZE_CLASS(145, 41, 39, 2, no, 1) \
290 SIZE_CLASS(146, 41, 39, 3, no, 1) \
291 SIZE_CLASS(147, 41, 39, 4, no, 1) /* 4T */\
293 SIZE_CLASS(148, 42, 40, 1, no, 1) \
294 SIZE_CLASS(149, 42, 40, 2, no, 1) \
295 SIZE_CLASS(150, 42, 40, 3, no, 1) \
296 SIZE_CLASS(151, 42, 40, 4, no, 1) /* 8T */\
298 SIZE_CLASS(152, 43, 41, 1, no, 1) \
299 SIZE_CLASS(153, 43, 41, 2, no, 1) \
300 SIZE_CLASS(154, 43, 41, 3, no, 1) \
301 SIZE_CLASS(155, 43, 41, 4, no, 1) /* 16T */\
303 SIZE_CLASS(156, 44, 42, 1, no, 1) \
304 SIZE_CLASS(157, 44, 42, 2, no, 1) \
305 SIZE_CLASS(158, 44, 42, 3, no, 1) \
306 SIZE_CLASS(159, 44, 42, 4, no, 1) /* 32T */\
308 SIZE_CLASS(160, 45, 43, 1, no, 1) \
309 SIZE_CLASS(161, 45, 43, 2, no, 1) \
310 SIZE_CLASS(162, 45, 43, 3, no, 1) \
311 SIZE_CLASS(163, 45, 43, 4, no, 1) /* 64T */\
313 SIZE_CLASS(164, 46, 44, 1, no, 1) \
314 SIZE_CLASS(165, 46, 44, 2, no, 1) \
315 SIZE_CLASS(166, 46, 44, 3, no, 1) \
316 SIZE_CLASS(167, 46, 44, 4, no, 1) /* 128T */\
318 SIZE_CLASS(168, 47, 45, 1, no, 1) \
319 SIZE_CLASS(169, 47, 45, 2, no, 1) \
320 SIZE_CLASS(170, 47, 45, 3, no, 1) \
321 SIZE_CLASS(171, 47, 45, 4, no, 1) /* 256T */\
323 constexpr size_t kNumSizeClasses = 172;
325 alignas(64) constexpr uint8_t kSmallSize2Index
[] = {
327 #define S2I_5(i) S2I_4(i) S2I_4(i)
328 #define S2I_6(i) S2I_5(i) S2I_5(i)
329 #define S2I_7(i) S2I_6(i) S2I_6(i)
330 #define S2I_8(i) S2I_7(i) S2I_7(i)
331 #define S2I_9(i) S2I_8(i) S2I_8(i)
333 #define SIZE_CLASS(index, lg_grp, lg_delta, ndelta, lg_delta_lookup, ncontig) \
334 S2I_##lg_delta_lookup(index)
346 constexpr size_t kSizeIndex2Size
[] = {
347 #define SIZE_CLASS(index, lg_grp, lg_delta, ndelta, lg_delta_lookup, ncontig) \
348 ((size_t{1}<<lg_grp) + (size_t{ndelta}<<lg_delta)),
353 alignas(64) constexpr unsigned kNContigTab
[] = {
354 #define SIZE_CLASS(index, lg_grp, lg_delta, ndelta, lg_delta_lookup, ncontig) \
360 constexpr size_t kMaxSmallSizeLookup
= 4096;
362 constexpr unsigned kLgSlabSize
= 21;
363 constexpr uint32_t kSlabSize
= uint32_t{1} << kLgSlabSize
;
364 constexpr unsigned kLgSmallSizeQuantum
= 4;
365 constexpr size_t kSmallSizeAlign
= 1u << kLgSmallSizeQuantum
;
366 constexpr size_t kSmallSizeAlignMask
= kSmallSizeAlign
- 1;
368 constexpr unsigned kLgSizeClassesPerDoubling
= 2;
369 constexpr size_t kSizeClassesPerDoubling
= (1u << kLgSizeClassesPerDoubling
);
372 * The maximum size where we use our custom allocator for request-local memory.
374 * Allocations larger than this size go to the underlying malloc implementation,
375 * and certain specialized allocator functions have preconditions about the
376 * requested size being above or below this number to avoid checking at runtime.
378 * We want kMaxSmallSize to be the largest size-class less than kSlabSize.
380 constexpr size_t kNumSmallSizes
= 63;
381 static_assert(kNumSmallSizes
<= (1 << 6),
382 "only 6 bits available in HeapObject");
383 static_assert(kNumSmallSizes
< kNumSizeClasses
,
384 "small sizes should be a proper subset of all sizes");
385 static_assert(kNumSizeClasses
<= (sizeof(kSizeIndex2Size
) / sizeof(size_t)),
386 "Extend SIZE_CLASSES macro");
388 constexpr size_t kMaxSmallSize
= kSizeIndex2Size
[kNumSmallSizes
-1];
389 static_assert(kMaxSmallSize
> kSmallSizeAlign
* 2,
390 "Too few size classes");
391 static_assert(kMaxSmallSize
< kSlabSize
, "fix kNumSmallSizes or kLgSlabSize");
393 constexpr size_t kMaxSizeClass
= kSizeIndex2Size
[kNumSizeClasses
-1];
394 static_assert(kMaxSmallSize
< kMaxSizeClass
,
395 "largest small size should be smaller than largest overall size");
398 * Constants for the various debug junk-filling of different types of
401 * jemalloc uses 0x5a to fill freed memory, so we use 0x6a for the
402 * request-local allocator so it is easy to tell the difference when
403 * debugging. There's also 0x7a for junk-filling some cases of
404 * ex-TypedValue memory (evaluation stack).
406 constexpr char kSmallFreeFill
= 0x6a;
407 constexpr char kRDSTrashFill
= 0x6b; // used by RDS for "normal" section
408 constexpr char kTrashClsRef
= 0x6c; // used for class-ref slots
409 constexpr char kTrashCufIter
= 0x6d; // used for cuf-iters
410 constexpr char kTVTrashFill
= 0x7a; // used by interpreter
411 constexpr char kTVTrashFill2
= 0x7b; // used by req::ptr dtors
412 constexpr char kTVTrashJITStk
= 0x7c; // used by the JIT for stack slots
413 constexpr char kTVTrashJITFrame
= 0x7d; // used by the JIT for stack frames
414 constexpr char kTVTrashJITHeap
= 0x7e; // used by the JIT for heap
415 constexpr char kTVTrashJITRetVal
= 0x7f; // used by the JIT for ActRec::m_r
416 constexpr uintptr_t kSmallFreeWord
= 0x6a6a6a6a6a6a6a6aLL
;
417 constexpr uintptr_t kMallocFreeWord
= 0x5a5a5a5a5a5a5a5aLL
;
419 //////////////////////////////////////////////////////////////////////
421 // Header MemoryManager uses for StringDatas that wrap APCHandle
422 struct StringDataNode
{
423 StringDataNode
* next
;
424 StringDataNode
* prev
;
427 static_assert(std::numeric_limits
<type_scan::Index
>::max() <=
428 std::numeric_limits
<uint16_t>::max(),
429 "type_scan::Index must be no greater than 16-bits "
430 "to fit into HeapObject");
432 // This is the header MemoryManager uses to remember large allocations
433 // so they can be auto-freed in MemoryManager::reset(), as well as large/small
434 // req::malloc()'d blocks, which must track their size internally.
435 struct MallocNode
: HeapObject
{
437 uint32_t& index() { return m_aux32
; }
438 uint16_t& typeIndex() { return m_aux16
; }
439 uint16_t typeIndex() const { return m_aux16
; }
442 // all FreeList entries are parsed by inspecting this header.
443 struct FreeNode
: HeapObject
{
445 uint32_t& size() { return m_aux32
; }
446 uint32_t size() const { return m_aux32
; }
447 static FreeNode
* InitFrom(void* addr
, uint32_t size
, HeaderKind
);
448 static FreeNode
* UninitFrom(void* addr
, FreeNode
* next
);
451 static_assert(sizeof(FreeNode
) <= kSmallSizeAlign
,
452 "FreeNode must fit into the smallest size class");
454 // header for HNI objects with NativeData payloads. see native-data.h
455 // for details about memory layout.
456 struct NativeNode
: HeapObject
,
457 type_scan::MarkCollectable
<NativeNode
> {
458 NativeNode(HeaderKind k
, uint32_t off
) : obj_offset(off
) {
461 uint32_t sweep_index
; // index in MemoryManager::m_natives
462 uint32_t obj_offset
; // byte offset from this to ObjectData*
463 uint16_t& typeIndex() { return m_aux16
; }
464 uint16_t typeIndex() const { return m_aux16
; }
465 uint32_t arOff() const { return m_count
; } // from this to ActRec, or 0
468 // POD type for tracking arbitrary memory ranges
469 template<class T
> struct MemRange
{
471 size_t size
; // bytes
474 using MemBlock
= MemRange
<void*>;
475 using HdrBlock
= MemRange
<HeapObject
*>;
477 ///////////////////////////////////////////////////////////////////////////////
480 * Allocator for slabs and big blocks.
492 * Whether `ptr' refers to slab-allocated memory.
494 * Note that memory in big blocks is explicitly excluded.
496 bool contains(void* ptr
) const;
499 * Allocate a MemBlock of at least size bytes, track in m_slabs.
501 MemBlock
allocSlab(size_t size
, MemoryUsageStats
& stats
);
504 * Allocation API for big blocks.
506 MemBlock
allocBig(size_t size
, HeaderKind kind
,
507 type_scan::Index tyindex
, MemoryUsageStats
& stats
);
508 MemBlock
callocBig(size_t size
, HeaderKind kind
,
509 type_scan::Index tyindex
, MemoryUsageStats
& stats
);
510 MemBlock
resizeBig(void* p
, size_t size
, MemoryUsageStats
& stats
);
514 * Free all slabs and big blocks.
519 * Release auxiliary structures to prepare to be idle for a while.
526 * Iterate over all the slabs and big blocks, calling Fn on each block,
527 * including all of the blocks in each slab.
529 template<class Fn
> void iterate(Fn
);
532 * call OnBig() on each BigObj & BigMalloc header, and OnSlab() on
533 * each slab, without iterating the blocks within each slab.
535 template<class OnBig
, class OnSlab
> void iterate(OnBig
, OnSlab
);
538 * Find the HeapObject* which contains `p', else nullptr if `p' is
539 * not contained in any heap allocation.
541 HeapObject
* find(const void* p
);
544 * Sorts both slabs and big blocks.
549 void enlist(MallocNode
*, HeaderKind kind
, size_t size
, type_scan::Index
);
552 std::vector
<MemBlock
> m_slabs
;
553 std::vector
<MallocNode
*> m_bigs
;
557 * Contiguous heap allocator for chunks
559 struct ContiguousHeap
{
560 static constexpr size_t ChunkSize
= kSlabSize
; // 2MB
561 static constexpr size_t HeapCap
= 8 * 1024*1024*1024UL; // 8G
562 static constexpr size_t FreebitsSize
= HeapCap
/ ChunkSize
; // 4096
573 * Whether `ptr' refers to slab-allocated memory.
575 bool contains(void* ptr
) const;
578 * Allocate a MemBlock of at least size bytes.
580 MemBlock
allocSlab(size_t size
, MemoryUsageStats
& stats
);
583 * Allocation API for big blocks.
585 MemBlock
allocBig(size_t size
, HeaderKind kind
,
586 type_scan::Index tyindex
, MemoryUsageStats
& stats
);
587 MemBlock
callocBig(size_t size
, HeaderKind kind
,
588 type_scan::Index tyindex
, MemoryUsageStats
& stats
);
589 MemBlock
resizeBig(void* p
, size_t size
, MemoryUsageStats
& stats
);
598 * Release auxiliary structures to prepare to be idle for a while.
605 * Iterate over all the chunks.
607 template<class OnBig
, class OnSlab
> void iterate(OnBig
, OnSlab
);
608 template<class Fn
> void iterate(Fn
);
609 template<class Fn
> HeapObject
* find_if(bool, Fn
);
612 * Find the HeapObject* which contains `p'. If `p' is
613 * not contained in any heap allocation, it returns nullptr.
615 HeapObject
* find(const void* p
);
618 * Sorts both slabs and big blocks.
623 char* raw_alloc(size_t size
);
624 void raw_free(char* p
, size_t size
);
625 bool check_invariants() const;
626 char* grow(size_t size
);
627 size_t chunk_index(char* p
) const;
630 char* const m_base
; // lowest address in heap
631 char* const m_limit
; // limit of heap size
632 char* m_front
; // end of the allocated part of the heap
633 std::bitset
<FreebitsSize
> m_freebits
; // 1 for free, 0 for allocated
636 #ifdef USE_CONTIGUOUS_HEAP
637 using HeapImpl
= ContiguousHeap
;
639 using HeapImpl
= SparseHeap
;
641 ///////////////////////////////////////////////////////////////////////////////
643 struct MemoryManager
{
646 * This is an RAII wrapper to temporarily mask counting allocations from
647 * stats tracking in a scoped region.
650 * MemoryManager::MaskAlloc masker(tl_heap);
655 * An RAII wrapper to suppress OOM checking in a region.
660 MemoryManager(const MemoryManager
&) = delete;
661 MemoryManager
& operator=(const MemoryManager
&) = delete;
664 /////////////////////////////////////////////////////////////////////////////
668 * Return the size class for a given requested small-allocation size.
670 * The return value is greater than or equal to the parameter, and
671 * less than or equal to kMaxSmallSize.
673 * Pre: requested <= kMaxSmallSize
675 static size_t smallSizeClass(size_t requested
);
678 * Return a lower bound estimate of the capacity that will be returned for
679 * the requested size.
681 static size_t estimateCap(size_t requested
);
684 * Allocate/deallocate a small memory block in a given small size class.
685 * You must be able to tell the deallocation function how big the
688 * The size passed to mallocSmallSize does not need to be an exact
689 * size class (although stats accounting may undercount in this
690 * case). The size passed to freeSmallSize must be the exact size
691 * that was passed to mallocSmallSize for that allocation.
693 * The returned pointer is guaranteed to be 16-byte aligned.
695 * Pre: size > 0 && size <= kMaxSmallSize
697 void* mallocSmallSize(size_t size
);
698 void freeSmallSize(void* p
, size_t size
);
701 * Allocate/deallocate memory that is too big for the small size classes.
703 * Returns a pointer and the actual size of the allocation, which
704 * may be larger than the requested size. The returned pointer is
705 * guaranteed to be 16-byte aligned.
707 * Pre: size > kMaxSmallSize
709 enum MBS
{ Unzeroed
, Zeroed
};
711 void* mallocBigSize(size_t size
, HeaderKind kind
= HeaderKind::BigObj
,
712 type_scan::Index tyindex
= 0);
713 void freeBigSize(void* vp
);
714 void* resizeBig(MallocNode
* n
, size_t nbytes
);
717 * Allocate/deallocate objects when the size is not known to be
718 * above or below kMaxSmallSize without a runtime check.
720 * These functions use the same underlying allocator as
721 * malloc{Small,Big}Size, and it is safe to return allocations using
722 * one of those apis as long as the appropriate preconditions on the
725 * The size passed to objFree must be the size passed in to
730 void* objMalloc(size_t size
);
731 void objFree(void* vp
, size_t size
);
734 * Allocate/deallocate by size class index. This is useful when size
735 * class is already calculated at the call site.
737 void* mallocSmallIndex(size_t index
);
738 void freeSmallIndex(void* ptr
, size_t index
);
741 * Allocate/deallocate by size class index, when the index is not known to
742 * be < kNumSmallSizes This is useful when size class is already calculated
743 * at the call site, but might not be a small size class.
745 * The index passed to objFreeIndex must be the same one passed to
748 void* objMallocIndex(size_t index
);
749 void objFreeIndex(void* ptr
, size_t index
);
752 * These functions are useful when working directly with size classes outside
755 * Note that we intentionally use size_t for size class index here, so that
756 * gcc would not generate inefficient code.
758 static size_t computeSize2Index(size_t size
);
759 static size_t lookupSmallSize2Index(size_t size
);
760 static size_t smallSize2Index(size_t size
);
761 static size_t size2Index(size_t size
);
762 static size_t sizeIndex2Size(size_t index
);
764 /////////////////////////////////////////////////////////////////////////////
768 * Prepare for being idle for a while by releasing or madvising as much as
774 * Release all the request-local allocations.
776 * Zeros all the free lists and may return some underlying storage to the
777 * system allocator. This also resets all internally-stored memory usage
780 * This is called after sweep in the end-of-request path.
782 void resetAllocator();
785 * Reset all runtime options for MemoryManager.
787 void resetRuntimeOptions();
789 /////////////////////////////////////////////////////////////////////////////
790 // Heap introspection.
793 * Return true if there are no allocated slabs.
798 * Whether `p' points into memory owned by `m_heap'. checkContains() will
799 * assert that it does.
801 * Note that this explicitly excludes allocations that are made through the
804 bool contains(void* p
) const;
805 bool checkContains(void* p
) const;
808 * Heap iterator methods. `fn' takes a HeapObject* argument.
810 * initFree(): prepare to iterate by initializing free block headers,
811 * initializing dead space past m_front, and sorting slabs.
812 * reinitFree(): like initFree() but only update the freelists.
813 * iterate(): Raw iterator loop over every HeapObject in the heap.
814 * Skips BigObj because it's just a detail of which sub-heap we
815 * used to allocate something based on its size, and it can prefix
816 * almost any other header kind, and also skips Hole. Clients can
817 * call this directly to avoid unnecessary initFree()s.
818 * forEachHeapObject(): Like iterate(), but with an eager initFree().
819 * forEachObject(): Iterate just the ObjectDatas, including the kinds with
820 * prefixes (NativeData, AsyncFuncFrame, and ClosureHdr).
824 template<class Fn
> void iterate(Fn fn
);
825 template<class Fn
> void forEachHeapObject(Fn fn
);
826 template<class Fn
> void forEachObject(Fn fn
);
829 * Iterate over the roots owned by MemoryManager.
830 * call fn(ptr, size, type_scan::Index) for each root
832 template<class Fn
> void iterateRoots(Fn
) const;
835 * Find the HeapObject* which contains `p', else nullptr if `p' is
836 * not contained in any heap allocation.
838 HeapObject
* find(const void* p
);
840 /////////////////////////////////////////////////////////////////////////////
844 * Update the request-memory limit.
846 void setMemoryLimit(size_t limit
);
847 int64_t getMemoryLimit() const;
850 * Update the tracked stats in the MemoryManager object, then return
851 * a copy of the stats.
853 MemoryUsageStats
getStats();
856 * Get most recent stats data, as one would with getStats(), but without
857 * altering the underlying data stored in the MemoryManager, triggering
858 * OOM, or triggering the memory threshold callback. Used for obtaining
859 * allocation counters passively.
861 MemoryUsageStats
getStatsCopy();
864 * Open and close respectively a stats-tracking interval.
866 * Return whether or not the tracking state was changed as a result of the
869 bool startStatsInterval();
870 bool stopStatsInterval();
873 * How much memory this thread has allocated or deallocated.
875 int64_t getAllocated() const;
876 int64_t getDeallocated() const;
877 int64_t currentUsage() const;
880 * Reset all stats that are synchronzied externally from the memory manager.
882 * Used between sessions and to signal that external sync is now safe to
883 * begin (after shared structure initialization that should not be counted is
886 void resetExternalStats();
888 /////////////////////////////////////////////////////////////////////////////
892 * Whether an allocation of `size' would run the request out of memory.
894 * This behaves just like the OOM check in refreshStatsImpl(). If the
895 * m_couldOOM flag is already unset, we return false, but if otherwise we
896 * would exceed the limit, we unset the flag and register an OOM fatal
897 * (though we do not modify the MemoryManager's stats).
899 bool preAllocOOM(int64_t size
);
902 * Unconditionally register an OOM fatal. Still respects the m_couldOOM flag.
907 * Reset whether or not we should raise an OOM fatal if we exceed the memory
908 * limit for the request.
910 * After an OOM fatal, the memory manager refuses to raise another OOM error
911 * until this flag has been reset, to try to avoid getting OOMs during the
912 * initial OOM processing.
914 void resetCouldOOM(bool state
= true);
916 /////////////////////////////////////////////////////////////////////////////
920 * Returns true iff a sweep is in progress---i.e., is the current thread
921 * running inside a call to MemoryManager::sweep()?
923 * It is legal to call this function even when the current thread's
924 * MemoryManager may not be set up (i.e. between requests).
926 static bool sweeping();
927 static bool exiting();
928 static void setExiting();
931 * During session shutdown, before resetAllocator(), this phase runs through
932 * the sweep lists, running cleanup for anything that needs to run custom
933 * tear down logic before we throw away the request-local memory.
938 * Methods for maintaining dedicated sweep lists of sweepable NativeData
939 * objects, APCLocalArray instances, and Sweepables.
941 void addNativeObject(NativeNode
*);
942 void removeNativeObject(NativeNode
*);
943 void addApcArray(APCLocalArray
*);
944 void removeApcArray(APCLocalArray
*);
945 void addSweepable(Sweepable
*);
946 template<class Fn
> void sweepApcArrays(Fn fn
);
947 template<class Fn
> void sweepApcStrings(Fn fn
);
949 /////////////////////////////////////////////////////////////////////////////
950 // Request profiling.
953 * Trigger heap profiling in the next request.
955 * Allocate the s_trigger atomic so that the next request can consume it. If
956 * an unconsumed trigger exists, do nothing and return false; else return
959 static bool triggerProfiling(const std::string
& filename
);
962 * Installs a PHP callback for the specified peak memory watermarks
963 * Each request may have 1 memory callback for 1 specific threshold
966 void setMemThresholdCallback(size_t threshold
);
969 * Do per-request initialization.
971 * Attempt to consume the profiling trigger, and copy it to m_profctx if we
972 * are successful. Also enable jemalloc heap profiling.
974 static void requestInit();
977 * Do per-request shutdown.
979 * Dump a jemalloc heap profiling, then reset the profiler.
981 static void requestShutdown();
984 * Setup/teardown profiling for current request. This causes all allocation
985 * requests to be passed through to the underlying memory allocator so that
986 * heap profiling can capture backtraces for individual allocations rather
987 * than slab allocations.
989 static void setupProfiling();
990 static void teardownProfiling();
992 /////////////////////////////////////////////////////////////////////////////
993 // Garbage collection.
996 * Returns ptr to head node of m_strings linked list. This used by
997 * StringData during a reset, enlist, and delist
999 StringDataNode
& getStringList();
1002 * Run the experimental collector.
1004 void collect(const char* phase
);
1006 void updateNextGc();
1009 void setGCEnabled(bool isGCEnabled
);
1014 FreeNode
* head
{nullptr};
1016 using FreelistArray
= std::array
<FreeList
,kNumSmallSizes
>;
1019 * beginQuarantine() swaps out the normal freelists. endQuarantine()
1020 * fills everything freed with holes, then restores the original freelists.
1022 FreelistArray
beginQuarantine();
1023 void endQuarantine(FreelistArray
&&);
1026 * Run an integrity check on the heap
1028 void checkHeap(const char* phase
);
1030 /////////////////////////////////////////////////////////////////////////////
1033 friend struct req::root_handle
; // access m_root_handles
1035 // head node of the doubly-linked list of Sweepables
1036 struct SweepableList
: Sweepable
{
1037 SweepableList() : Sweepable(Init
{}) {}
1038 void sweep() override
{}
1039 void* owner() override
{ return nullptr; }
1043 * Request-local heap profiling context.
1045 struct ReqProfContext
{
1047 bool prof_active
{false};
1048 bool thread_prof_active
{false};
1049 std::string filename
{};
1052 /////////////////////////////////////////////////////////////////////////////
1055 void storeTail(void* tail
, uint32_t tailBytes
);
1056 void splitTail(void* tail
, uint32_t tailBytes
, unsigned nSplit
,
1057 uint32_t splitUsable
, unsigned splitInd
);
1058 void* slabAlloc(uint32_t bytes
, size_t index
);
1059 void* newSlab(uint32_t nbytes
);
1060 void* mallocSmallSizeSlow(size_t bytes
, size_t index
);
1061 void updateBigStats();
1063 static size_t bsrq(size_t x
);
1065 static void threadStatsInit();
1066 static void threadStats(uint64_t*&, uint64_t*&);
1067 void refreshStats();
1068 void refreshStatsImpl(MemoryUsageStats
& stats
);
1069 void refreshStatsHelperExceeded();
1070 void resetAllStats();
1071 void traceStats(const char* when
);
1073 static void initHole(void* ptr
, uint32_t size
);
1075 void requestEagerGC();
1076 void resetEagerGC();
1079 /////////////////////////////////////////////////////////////////////////////
1084 void* m_front
{nullptr};
1085 void* m_limit
{nullptr};
1086 FreelistArray m_freelists
;
1087 StringDataNode m_strings
; // in-place node is head of circular list
1088 std::vector
<APCLocalArray
*> m_apc_arrays
;
1089 int64_t m_nextGc
; // request gc when heap usage reaches this size
1090 int64_t m_usageLimit
; // OOM when m_stats.usage() > m_usageLimit
1091 MemoryUsageStats m_stats
;
1093 std::vector
<NativeNode
*> m_natives
;
1094 SweepableList m_sweepables
;
1096 mutable std::vector
<req::root_handle
*> m_root_handles
;
1098 bool m_exiting
{false};
1099 bool m_statsIntervalActive
;
1100 bool m_couldOOM
{true};
1101 bool m_bypassSlabAlloc
;
1102 bool m_gc_enabled
{RuntimeOption::EvalEnableGC
};
1103 bool m_enableStatsSync
{false};
1104 GCBits m_mark_version
{GCBits(0)};
1106 ReqProfContext m_profctx
;
1107 static std::atomic
<ReqProfContext
*> s_trigger
;
1109 // Peak memory threshold callback (installed via setMemThresholdCallback)
1110 size_t m_memThresholdCallbackPeakUsage
{SIZE_MAX
};
1112 // pointers to jemalloc-maintained allocation counters
1113 uint64_t* m_allocated
;
1114 uint64_t* m_deallocated
;
1116 // previous values of *m_[de]allocated from last resetStats()
1117 uint64_t m_resetAllocated
;
1118 uint64_t m_resetDeallocated
;
1120 // true if mallctlnametomib() setup succeeded, which requires jemalloc
1121 static bool s_statsEnabled
;
1123 int64_t m_req_start_micros
;
1125 TYPE_SCAN_IGNORE_ALL
; // heap-scan handles MemoryManager fields itself.
1128 extern THREAD_LOCAL_FLAT(MemoryManager
, tl_heap
);
1130 //////////////////////////////////////////////////////////////////////
1134 #include "hphp/runtime/base/memory-manager-inl.h"