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 #include "hphp/runtime/base/slab-manager.h"
19 #include "hphp/runtime/base/runtime-option.h"
20 #include "hphp/util/alloc.h"
21 #include "hphp/util/hugetlb.h"
22 #include "hphp/util/logger.h"
23 #include "hphp/util/numa.h"
25 #include <folly/portability/SysMman.h>
30 std::vector
<SlabManager
*> SlabManager::s_slabManagers
;
32 void TaggedSlabList::addRange(void* ptr
, std::size_t size
) {
34 while (size
>= kSlabSize
) {
37 ptr
= reinterpret_cast<char*>(ptr
) + kSlabSize
;
41 void SlabManager::init() {
42 if (!s_slabManagers
.empty()) return;
44 unsigned max_node
= numa_max_node();
46 unsigned constexpr max_node
= 0;
48 const unsigned numNodes
= num_numa_nodes(); // number of NUMA node allowed
49 s_slabManagers
.reserve(max_node
+ 1);
51 unsigned num1GPages
= RuntimeOption::EvalNum1GPagesForSlabs
;
52 unsigned num2MPages
= RuntimeOption::EvalNum2MPagesForSlabs
;
54 auto perNode1G
= num1GPages
/ numNodes
;
55 if (auto const excessive
= num1GPages
% numNodes
) {
56 Logger::Warning("uneven distribution of %u 1G huge pages "
57 "(Eval.Num1GPagesForSlabs) to %u NUMA nodes, "
58 "excessive %u pages not used",
59 num1GPages
, numNodes
, excessive
);
61 num1GPages
= perNode1G
;
62 auto perNode2M
= num2MPages
/ numNodes
;
63 if (auto const excessive
= num2MPages
% numNodes
) {
64 Logger::Warning("uneven distribution of %u 2M huge pages "
65 "(Eval.Num1MPagesForSlabs) to %u NUMA nodes, "
66 "excessive %u pages not used",
67 num2MPages
, numNodes
, excessive
);
69 num2MPages
= perNode2M
;
72 for (unsigned node
= 0; node
<= max_node
; ++node
) {
73 if (!numa_node_allowed(node
)) {
74 s_slabManagers
.push_back(nullptr);
77 constexpr auto kCacheLineSize
= 64u;
78 static_assert(sizeof(SlabManager
) <= kCacheLineSize
, "");
79 auto ptr
= mallocx_on_node(kCacheLineSize
, node
, kCacheLineSize
); // leaked
80 auto slabManager
= new (ptr
) SlabManager
;
81 s_slabManagers
.push_back(slabManager
);
82 unsigned actual1g
= 0, actual2m
= 0;
83 for (int i
= 0; i
< num1GPages
; ++i
) {
84 auto ptr
= mmap_1g(nullptr, node
);
86 Logger::Warning("Insufficient 1G huge pages for slabs "
87 "on NUMA node %u, desired %u, actual %u",
88 node
, num1GPages
, actual1g
);
92 slabManager
->addRange(ptr
, size1g
);
94 for (unsigned i
= 0; i
< num2MPages
; ++i
) {
95 auto ptr
= mmap_2m(nullptr, PROT_READ
| PROT_WRITE
, node
);
97 Logger::Warning("Insufficient 2M huge pages for slabs "
98 "on NUMA node %u, desired %u, actual %u",
99 node
, num2MPages
, actual2m
);
103 slabManager
->addRange(ptr
, size2m
);