Use iterator adapters in decl_class_parents
[hiphop-php.git] / hphp / util / managed-arena.cpp
blob796d2d5eb37202dde5a2d8f33f0b3cf63a6b7318
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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 #include "hphp/util/managed-arena.h"
19 #include "hphp/util/address-range.h"
20 #include "hphp/util/assertions.h"
22 #if USE_JEMALLOC_EXTENT_HOOKS
24 namespace HPHP::alloc {
26 static_assert(sizeof(RangeState) <= 64, "");
27 static_assert(alignof(RangeState) <= 64, "");
28 using RangeStateStorage = std::aligned_storage<sizeof(RangeState), 64>::type;
30 RangeArenaStorage g_lowerArena{};
31 RangeArenaStorage g_lowArena{};
32 RangeArenaStorage g_highArena{};
33 RangeArenaStorage g_coldArena{};
34 RangeArenaStorage g_lowColdArena{};
35 RangeStateStorage g_ranges[5];
36 ArenaArray g_arenas;
37 PreMappedArena* g_arena0; // arena 0, if we end up injecting pages
38 std::vector<PreMappedArena*> g_local_arenas; // keyed by numa node id
40 NEVER_INLINE RangeState& getRange(AddrRangeClass index) {
41 auto result = reinterpret_cast<RangeState*>(g_ranges + index);
42 if (!result->low()) {
43 static std::atomic_flag lock = ATOMIC_FLAG_INIT;
44 while (lock.test_and_set(std::memory_order_acquire)) {
45 // Spin while another thread initializes the ranges. We don't really reach
46 // here, because the function is called very early during process
47 // initialization when there is only one thread. Do it just for extra
48 // safety in case someone starts to abuse the code.
50 if (!result->high()) {
51 new (&(g_ranges[AddrRangeClass::VeryLow]))
52 RangeState(lowArenaMinAddr(), 2ull << 30);
53 new (&(g_ranges[AddrRangeClass::Low]))
54 RangeState(2ull << 30, kLowArenaMaxAddr - kLowEmergencySize);
55 new (&(g_ranges[AddrRangeClass::LowEmergency]))
56 RangeState(kLowArenaMaxAddr - kLowEmergencySize, kLowArenaMaxAddr);
57 new (&(g_ranges[AddrRangeClass::Uncounted]))
58 RangeState(kLowArenaMaxAddr, kHighArenaMaxAddr);
59 new (&(g_ranges[AddrRangeClass::UncountedCold]))
60 RangeState(kHighArenaMaxAddr, kUncountedMaxAddr);
62 lock.clear(std::memory_order_release);
63 assertx(result->high());
65 return *result;
68 //////////////////////////////////////////////////////////////////////
70 template<typename ExtentAllocator>
71 std::string ManagedArena<ExtentAllocator>::reportStats() {
72 char buffer[128];
73 using Traits = extent_allocator_traits<ExtentAllocator>;
74 std::snprintf(buffer, sizeof(buffer),
75 "Arena %d: capacity %zd, max_capacity %zd, used %zd\n",
76 id(),
77 ExtentAllocator::allocatedSize(),
78 ExtentAllocator::maxCapacity(),
79 s_pageSize * mallctl_pactive(id()));
80 return std::string{buffer};
83 template<typename ExtentAllocator>
84 size_t ManagedArena<ExtentAllocator>::unusedSize() {
85 auto const active = s_pageSize * mallctl_pactive(id());
86 return ExtentAllocator::allocatedSize() - active;
89 template<typename ExtentAllocator>
90 void ManagedArena<ExtentAllocator>::create() {
91 using Traits = extent_allocator_traits<ExtentAllocator>;
92 assertx(m_arenaId == kInvalidArena);
93 size_t idSize = sizeof(m_arenaId);
94 if (mallctl("arenas.create", &m_arenaId, &idSize, nullptr, 0)) {
95 throw std::runtime_error{"arenas.create"};
97 char command[32];
98 ssize_t decay_ms = Traits::get_decay_ms();
99 std::snprintf(command, sizeof(command),
100 "arena.%d.dirty_decay_ms", m_arenaId);
101 if (mallctl(command, nullptr, nullptr, &decay_ms, sizeof(decay_ms))) {
102 throw std::runtime_error{command};
107 template<typename ExtentAllocator>
108 void ManagedArena<ExtentAllocator>::updateHook() {
109 using Traits = extent_allocator_traits<ExtentAllocator>;
110 if (auto hooks_ptr = Traits::get_hooks()) {
111 // We need to do `GetByArenaId()` in custom extent hooks, so register the
112 // arena in the global list. It is important that we do this before actually
113 // updating the hooks.
114 assertx(GetByArenaId<ManagedArena>(m_arenaId) == nullptr);
115 bool registered = false;
116 for (auto& i : g_arenas) {
117 if (!i.second) {
118 i.first = m_arenaId;
119 i.second = this;
120 registered = true;
121 break;
124 if (!registered) {
125 throw std::out_of_range{
126 "too many ManagedArena's, check MAX_MANAGED_ARENA_COUNT"};
129 char command[32];
130 std::snprintf(command, sizeof(command), "arena.%d.extent_hooks", m_arenaId);
131 auto fallback = Traits::get_fallback(this);
132 size_t oldSize = sizeof(extent_hooks_t*);
133 if (mallctl(command, fallback, (fallback ? &oldSize : nullptr),
134 &hooks_ptr, sizeof(hooks_ptr))) {
135 throw std::runtime_error{command};
137 #if (JEMALLOC_VERSION_MAJOR > 5) || \
138 ((JEMALLOC_VERSION_MAJOR == 5) && (JEMALLOC_VERSION_MINOR >= 1))
139 // Avoid asking excessive memory through the hook, in order to make better
140 // use of preallocated pages.
141 std::snprintf(command, sizeof(command),
142 "arena.%d.retain_grow_limit", m_arenaId);
143 size_t limit = 16ull << 20;
144 if (mallctl(command, nullptr, nullptr, &limit, sizeof(limit))) {
145 throw std::runtime_error{command};
148 #endif
151 template void ManagedArena<MultiRangeExtentAllocator>::create();
152 template void ManagedArena<MultiRangeExtentAllocator>::updateHook();
153 template size_t ManagedArena<MultiRangeExtentAllocator>::unusedSize();
154 template std::string ManagedArena<MultiRangeExtentAllocator>::reportStats();
156 template void ManagedArena<DefaultExtentAllocator>::create();
157 template void ManagedArena<DefaultExtentAllocator>::updateHook();
158 template void ManagedArena<RangeFallbackExtentAllocator>::create();
159 template void ManagedArena<RangeFallbackExtentAllocator>::updateHook();
163 #endif