11/*
22 * ghex-org
33 *
4- * Copyright (c) 2014-2023 , ETH Zurich
4+ * Copyright (c) 2014-2025 , ETH Zurich
55 * All rights reserved.
66 *
77 * Please, refer to the LICENSE file in the root directory.
1414#include < hwmalloc/fancy_ptr/void_ptr.hpp>
1515#include < hwmalloc/fancy_ptr/const_void_ptr.hpp>
1616#include < hwmalloc/fancy_ptr/unique_ptr.hpp>
17+ #include < hwmalloc/heap_config.hpp>
1718#include < hwmalloc/allocator.hpp>
1819#include < vector>
1920#include < unordered_map>
@@ -56,6 +57,9 @@ class heap
5657 template <typename T>
5758 using unique_ptr = unique_ptr<T, block_type>;
5859
60+ // Note: sizes below are defaults and can be changed through heap_config and
61+ // environment variables.
62+ //
5963 // There are 5 size classes that the heap uses. For each size class it relies on a
6064 // fixed_size_heap. The size classes are:
6165 // - tiny: heaps with linearly increasing block sizes, each heap backed by 16KiB segments
@@ -98,78 +102,56 @@ class heap
98102 // : : m_huge_heaps: map
99103
100104 private:
101- static constexpr std::size_t log2_c (std::size_t n) noexcept
105+ static std::size_t tiny_bucket_index (std::size_t n, std::size_t tiny_increment,
106+ std::size_t tiny_increment_shift) noexcept
102107 {
103- return ((n < 2 ) ? 1 : 1 + log2_c (n >> 1 )) ;
108+ return ((n + tiny_increment - 1 ) >> tiny_increment_shift) - 1 ;
104109 }
105110
106- static const std::size_t s_tiny_limit = (1u << 7 ); // 128
107- static const std::size_t s_small_limit = (1u << 10 ); // 1024
108- static const std::size_t s_large_limit = (1u << 16 ); // 65536
109-
110- static const std::size_t s_bucket_shift = log2_c(s_tiny_limit) - 1 ;
111-
112- static const std::size_t s_tiny_segment = 0x04000 ; // 16KiB
113- static const std::size_t s_small_segment = 0x08000 ; // 32KiB
114- static const std::size_t s_large_segment = 0x10000 ; // 64KiB
115-
116- static const std::size_t s_tiny_increment_shift = 3 ;
117- static const std::size_t s_tiny_increment = (1u << s_tiny_increment_shift); // = 8
118-
119- static const std::size_t s_num_tiny_heaps = s_tiny_limit / s_tiny_increment;
120- static const std::size_t s_num_small_heaps = log2_c(s_small_limit) - log2_c(s_tiny_limit);
121- static const std::size_t s_num_large_heaps = log2_c(s_large_limit) - log2_c(s_small_limit);
122-
123- static std::size_t tiny_bucket_index (std::size_t n) noexcept
111+ static std::size_t bucket_index (std::size_t n, std::size_t bucket_shift) noexcept
124112 {
125- return ((n + s_tiny_increment - 1 ) >> s_tiny_increment_shift) - 1 ;
126- }
127-
128- static std::size_t bucket_index (std::size_t n) noexcept
129- {
130- return log2_c ((n - 1 ) >> s_bucket_shift) - 1 ;
131- }
132-
133- static constexpr std::size_t round_to_pow_of_2 (std::size_t n) noexcept
134- {
135- return 1u << log2_c (n - 1 );
113+ return detail::log2_c ((n - 1 ) >> bucket_shift) - 1 ;
136114 }
137115
138116 private:
117+ heap_config m_config;
139118 Context* m_context;
140119 std::size_t m_max_size;
141- bool m_never_free;
142- std::size_t m_num_reserve_segments;
143120 heap_vector m_tiny_heaps;
144121 heap_vector m_heaps;
145122 heap_map m_huge_heaps;
146123 std::mutex m_mutex;
147124
148125 public:
149- heap (Context* context, bool never_free = false , std:: size_t num_reserve_segments = 1 )
150- : m_context{context }
151- , m_max_size(std::max(round_to_pow_of_2(s_large_limit * 2 ), s_large_limit))
152- , m_never_free{never_free}
153- , m_num_reserve_segments{num_reserve_segments}
154- , m_tiny_heaps(s_tiny_limit / s_tiny_increment )
155- , m_heaps(bucket_index(m_max_size) + 1 )
126+ heap (Context* context, heap_config const & config = get_default_heap_config() )
127+ : m_config{config }
128+ , m_context{context}
129+ , m_max_size(
130+ std::max (detail::round_to_pow_of_2(m_config.m_large_limit * 2 ), m_config.m_large_limit))
131+ , m_tiny_heaps(m_config.m_tiny_limit / m_config.m_tiny_increment )
132+ , m_heaps(bucket_index(m_max_size, m_config.m_bucket_shift ) + 1 )
156133 {
157134 for (std::size_t i = 0 ; i < m_tiny_heaps.size (); ++i)
158135 m_tiny_heaps[i] = std::make_unique<fixed_size_heap_type>(m_context,
159- s_tiny_increment * (i + 1 ), s_tiny_segment, m_never_free, m_num_reserve_segments);
136+ m_config.m_tiny_increment * (i + 1 ), m_config.m_tiny_segment_size ,
137+ m_config.m_never_free , m_config.m_num_reserve_segments );
160138
161- for (std::size_t i = 0 ; i < s_num_small_heaps ; ++i)
139+ for (std::size_t i = 0 ; i < m_config. m_num_small_heaps ; ++i)
162140 m_heaps[i] = std::make_unique<fixed_size_heap_type>(m_context,
163- (s_tiny_limit << (i + 1 )), s_small_segment, m_never_free, m_num_reserve_segments);
141+ (m_config.m_tiny_limit << (i + 1 )), m_config.m_small_segment_size ,
142+ m_config.m_never_free , m_config.m_num_reserve_segments );
164143
165- for (std::size_t i = 0 ; i < s_num_large_heaps; ++i)
166- m_heaps[i + s_num_small_heaps] = std::make_unique<fixed_size_heap_type>(m_context,
167- (s_small_limit << (i + 1 )), s_large_segment, m_never_free, m_num_reserve_segments);
144+ for (std::size_t i = 0 ; i < m_config.m_num_large_heaps ; ++i)
145+ m_heaps[i + m_config.m_num_small_heaps ] = std::make_unique<fixed_size_heap_type>(
146+ m_context, (m_config.m_small_limit << (i + 1 )), m_config.m_large_segment_size ,
147+ m_config.m_never_free , m_config.m_num_reserve_segments );
168148
169- for (std::size_t i = 0 ; i < m_heaps.size () - (s_num_small_heaps + s_num_large_heaps); ++i)
170- m_heaps[i + s_num_small_heaps + s_num_large_heaps] =
171- std::make_unique<fixed_size_heap_type>(m_context, (s_large_limit << (i + 1 )),
172- (s_large_limit << (i + 1 )), m_never_free, m_num_reserve_segments);
149+ for (std::size_t i = 0 ;
150+ i < m_heaps.size () - (m_config.m_num_small_heaps + m_config.m_num_large_heaps ); ++i)
151+ m_heaps[i + m_config.m_num_small_heaps + m_config.m_num_large_heaps ] =
152+ std::make_unique<fixed_size_heap_type>(m_context,
153+ (m_config.m_large_limit << (i + 1 )), (m_config.m_large_limit << (i + 1 )),
154+ m_config.m_never_free , m_config.m_num_reserve_segments );
173155 }
174156
175157 heap (heap const &) = delete ;
@@ -194,20 +176,22 @@ class heap
194176
195177 pointer allocate (std::size_t size, std::size_t numa_node)
196178 {
197- if (size <= s_tiny_limit)
198- return {m_tiny_heaps[tiny_bucket_index (size)]->allocate (numa_node)};
179+ if (size <= m_config.m_tiny_limit )
180+ return {m_tiny_heaps[tiny_bucket_index (size, m_config.m_tiny_increment ,
181+ m_config.m_tiny_increment_shift )]
182+ ->allocate (numa_node)};
199183 else if (size <= m_max_size)
200- return {m_heaps[bucket_index (size)]->allocate (numa_node)};
184+ return {m_heaps[bucket_index (size, m_config. m_bucket_shift )]->allocate (numa_node)};
201185 else
202186 {
203187 fixed_size_heap_type* h;
204188 {
205189 std::lock_guard<std::mutex> lock (m_mutex);
206- const auto s = round_to_pow_of_2 (size);
190+ const auto s = detail:: round_to_pow_of_2 (size);
207191 auto & u_ptr = m_huge_heaps[s];
208192 if (!u_ptr)
209- u_ptr = std::make_unique<fixed_size_heap_type>(m_context, s, s, m_never_free,
210- m_num_reserve_segments);
193+ u_ptr = std::make_unique<fixed_size_heap_type>(m_context, s, s,
194+ m_config. m_never_free , m_config. m_num_reserve_segments );
211195 h = u_ptr.get ();
212196 }
213197 return {h->allocate (numa_node)};
@@ -223,20 +207,23 @@ class heap
223207#if HWMALLOC_ENABLE_DEVICE
224208 pointer allocate (std::size_t size, std::size_t numa_node, int device_id)
225209 {
226- if (size <= s_tiny_limit)
227- return {m_tiny_heaps[tiny_bucket_index (size)]->allocate (numa_node, device_id)};
210+ if (size <= m_config.m_tiny_limit )
211+ return {m_tiny_heaps[tiny_bucket_index (size, m_config.m_tiny_increment ,
212+ m_config.m_tiny_increment_shift )]
213+ ->allocate (numa_node, device_id)};
228214 else if (size <= m_max_size)
229- return {m_heaps[bucket_index (size)]->allocate (numa_node, device_id)};
215+ return {m_heaps[bucket_index (size, m_config.m_bucket_shift )]->allocate (numa_node,
216+ device_id)};
230217 else
231218 {
232219 fixed_size_heap_type* h;
233220 {
234221 std::lock_guard<std::mutex> lock (m_mutex);
235- const auto s = round_to_pow_of_2 (size);
222+ const auto s = detail:: round_to_pow_of_2 (size);
236223 auto & u_ptr = m_huge_heaps[s];
237224 if (!u_ptr)
238- u_ptr = std::make_unique<fixed_size_heap_type>(m_context, s, s, m_never_free,
239- m_num_reserve_segments);
225+ u_ptr = std::make_unique<fixed_size_heap_type>(m_context, s, s,
226+ m_config. m_never_free , m_config. m_num_reserve_segments );
240227 h = u_ptr.get ();
241228 }
242229 return {h->allocate (numa_node, device_id)};
@@ -293,29 +280,4 @@ class heap
293280 }
294281};
295282
296- template <typename Context>
297- const std::size_t heap<Context>::s_tiny_limit;
298- template <typename Context>
299- const std::size_t heap<Context>::s_small_limit;
300- template <typename Context>
301- const std::size_t heap<Context>::s_large_limit;
302- template <typename Context>
303- const std::size_t heap<Context>::s_bucket_shift;
304- template <typename Context>
305- const std::size_t heap<Context>::s_tiny_segment;
306- template <typename Context>
307- const std::size_t heap<Context>::s_small_segment;
308- template <typename Context>
309- const std::size_t heap<Context>::s_large_segment;
310- template <typename Context>
311- const std::size_t heap<Context>::s_tiny_increment_shift;
312- template <typename Context>
313- const std::size_t heap<Context>::s_tiny_increment;
314- template <typename Context>
315- const std::size_t heap<Context>::s_num_tiny_heaps;
316- template <typename Context>
317- const std::size_t heap<Context>::s_num_small_heaps;
318- template <typename Context>
319- const std::size_t heap<Context>::s_num_large_heaps;
320-
321283} // namespace hwmalloc
0 commit comments