From b5b099b1f7ed26d9ec63ee6013a516c89c58c98a Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Tue, 21 Oct 2025 16:17:20 +0200 Subject: [PATCH 01/15] Add heap_config to allow customizing segment limits and sizes --- include/hwmalloc/heap.hpp | 126 ++++++++++++------------------- include/hwmalloc/heap_config.hpp | 52 +++++++++++++ src/CMakeLists.txt | 2 + src/heap_config.cpp | 93 +++++++++++++++++++++++ 4 files changed, 194 insertions(+), 79 deletions(-) create mode 100644 include/hwmalloc/heap_config.hpp create mode 100644 src/heap_config.cpp diff --git a/include/hwmalloc/heap.hpp b/include/hwmalloc/heap.hpp index 8d400b8..34804ed 100644 --- a/include/hwmalloc/heap.hpp +++ b/include/hwmalloc/heap.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,9 @@ class heap template using unique_ptr = unique_ptr; + // Note: sizes below are defaults and can be changed through heap_config and + // environment variables. + // // There are 5 size classes that the heap uses. For each size class it relies on a // fixed_size_heap. The size classes are: // - tiny: heaps with linearly increasing block sizes, each heap backed by 16KiB segments @@ -98,44 +102,19 @@ class heap // : : m_huge_heaps: map private: - static constexpr std::size_t log2_c(std::size_t n) noexcept + static std::size_t tiny_bucket_index(std::size_t n, std::size_t tiny_increment, + std::size_t tiny_increment_shift) noexcept { - return ((n < 2) ? 1 : 1 + log2_c(n >> 1)); + return ((n + tiny_increment - 1) >> tiny_increment_shift) - 1; } - static const std::size_t s_tiny_limit = (1u << 7); // 128 - static const std::size_t s_small_limit = (1u << 10); // 1024 - static const std::size_t s_large_limit = (1u << 16); // 65536 - - static const std::size_t s_bucket_shift = log2_c(s_tiny_limit) - 1; - - static const std::size_t s_tiny_segment = 0x04000; // 16KiB - static const std::size_t s_small_segment = 0x08000; // 32KiB - static const std::size_t s_large_segment = 0x10000; // 64KiB - - static const std::size_t s_tiny_increment_shift = 3; - static const std::size_t s_tiny_increment = (1u << s_tiny_increment_shift); // = 8 - - static const std::size_t s_num_tiny_heaps = s_tiny_limit / s_tiny_increment; - static const std::size_t s_num_small_heaps = log2_c(s_small_limit) - log2_c(s_tiny_limit); - static const std::size_t s_num_large_heaps = log2_c(s_large_limit) - log2_c(s_small_limit); - - static std::size_t tiny_bucket_index(std::size_t n) noexcept + static std::size_t bucket_index(std::size_t n, std::size_t bucket_shift) noexcept { - return ((n + s_tiny_increment - 1) >> s_tiny_increment_shift) - 1; - } - - static std::size_t bucket_index(std::size_t n) noexcept - { - return log2_c((n - 1) >> s_bucket_shift) - 1; - } - - static constexpr std::size_t round_to_pow_of_2(std::size_t n) noexcept - { - return 1u << log2_c(n - 1); + return detail::log2_c((n - 1) >> bucket_shift) - 1; } private: + heap_config m_config; Context* m_context; std::size_t m_max_size; bool m_never_free; @@ -146,30 +125,39 @@ class heap std::mutex m_mutex; public: - heap(Context* context, bool never_free = false, std::size_t num_reserve_segments = 1) - : m_context{context} - , m_max_size(std::max(round_to_pow_of_2(s_large_limit * 2), s_large_limit)) + // TODO: never_free and num_reserve_segments in heap_config? + heap(Context* context, bool never_free = false, std::size_t num_reserve_segments = 1, + heap_config config = get_default_heap_config()) + : m_config{config} + , m_context{context} + , m_max_size( + std::max(detail::round_to_pow_of_2(m_config.m_large_limit * 2), m_config.m_large_limit)) , m_never_free{never_free} , m_num_reserve_segments{num_reserve_segments} - , m_tiny_heaps(s_tiny_limit / s_tiny_increment) - , m_heaps(bucket_index(m_max_size) + 1) + , m_tiny_heaps(m_config.m_tiny_limit / m_config.m_tiny_increment) + , m_heaps(bucket_index(m_max_size, m_config.m_bucket_shift) + 1) { for (std::size_t i = 0; i < m_tiny_heaps.size(); ++i) m_tiny_heaps[i] = std::make_unique(m_context, - s_tiny_increment * (i + 1), s_tiny_segment, m_never_free, m_num_reserve_segments); + m_config.m_tiny_increment * (i + 1), m_config.m_tiny_segment_size, m_never_free, + m_num_reserve_segments); - for (std::size_t i = 0; i < s_num_small_heaps; ++i) + for (std::size_t i = 0; i < m_config.m_num_small_heaps; ++i) m_heaps[i] = std::make_unique(m_context, - (s_tiny_limit << (i + 1)), s_small_segment, m_never_free, m_num_reserve_segments); + (m_config.m_tiny_limit << (i + 1)), m_config.m_small_segment_size, m_never_free, + m_num_reserve_segments); - for (std::size_t i = 0; i < s_num_large_heaps; ++i) - m_heaps[i + s_num_small_heaps] = std::make_unique(m_context, - (s_small_limit << (i + 1)), s_large_segment, m_never_free, m_num_reserve_segments); + for (std::size_t i = 0; i < m_config.m_num_large_heaps; ++i) + m_heaps[i + m_config.m_num_small_heaps] = std::make_unique( + m_context, (m_config.m_small_limit << (i + 1)), m_config.m_large_segment_size, + m_never_free, m_num_reserve_segments); - for (std::size_t i = 0; i < m_heaps.size() - (s_num_small_heaps + s_num_large_heaps); ++i) - m_heaps[i + s_num_small_heaps + s_num_large_heaps] = - std::make_unique(m_context, (s_large_limit << (i + 1)), - (s_large_limit << (i + 1)), m_never_free, m_num_reserve_segments); + for (std::size_t i = 0; + i < m_heaps.size() - (m_config.m_num_small_heaps + m_config.m_num_large_heaps); ++i) + m_heaps[i + m_config.m_num_small_heaps + m_config.m_num_large_heaps] = + std::make_unique(m_context, + (m_config.m_large_limit << (i + 1)), (m_config.m_large_limit << (i + 1)), + m_never_free, m_num_reserve_segments); } heap(heap const&) = delete; @@ -194,16 +182,18 @@ class heap pointer allocate(std::size_t size, std::size_t numa_node) { - if (size <= s_tiny_limit) - return {m_tiny_heaps[tiny_bucket_index(size)]->allocate(numa_node)}; + if (size <= m_config.m_tiny_limit) + return {m_tiny_heaps[tiny_bucket_index(size, m_config.m_tiny_increment, + m_config.m_tiny_increment_shift)] + ->allocate(numa_node)}; else if (size <= m_max_size) - return {m_heaps[bucket_index(size)]->allocate(numa_node)}; + return {m_heaps[bucket_index(size, m_config.m_bucket_shift)]->allocate(numa_node)}; else { fixed_size_heap_type* h; { std::lock_guard lock(m_mutex); - const auto s = round_to_pow_of_2(size); + const auto s = detail::round_to_pow_of_2(size); auto& u_ptr = m_huge_heaps[s]; if (!u_ptr) u_ptr = std::make_unique(m_context, s, s, m_never_free, @@ -223,16 +213,19 @@ class heap #if HWMALLOC_ENABLE_DEVICE pointer allocate(std::size_t size, std::size_t numa_node, int device_id) { - if (size <= s_tiny_limit) - return {m_tiny_heaps[tiny_bucket_index(size)]->allocate(numa_node, device_id)}; + if (size <= m_config.m_tiny_limit) + return {m_tiny_heaps[tiny_bucket_index(size, m_config.m_tiny_increment, + m_config.m_tiny_increment_shift)] + ->allocate(numa_node, device_id)}; else if (size <= m_max_size) - return {m_heaps[bucket_index(size)]->allocate(numa_node, device_id)}; + return {m_heaps[bucket_index(size, m_config.m_bucket_shift)]->allocate(numa_node, + device_id)}; else { fixed_size_heap_type* h; { std::lock_guard lock(m_mutex); - const auto s = round_to_pow_of_2(size); + const auto s = detail::round_to_pow_of_2(size); auto& u_ptr = m_huge_heaps[s]; if (!u_ptr) u_ptr = std::make_unique(m_context, s, s, m_never_free, @@ -293,29 +286,4 @@ class heap } }; -template -const std::size_t heap::s_tiny_limit; -template -const std::size_t heap::s_small_limit; -template -const std::size_t heap::s_large_limit; -template -const std::size_t heap::s_bucket_shift; -template -const std::size_t heap::s_tiny_segment; -template -const std::size_t heap::s_small_segment; -template -const std::size_t heap::s_large_segment; -template -const std::size_t heap::s_tiny_increment_shift; -template -const std::size_t heap::s_tiny_increment; -template -const std::size_t heap::s_num_tiny_heaps; -template -const std::size_t heap::s_num_small_heaps; -template -const std::size_t heap::s_num_large_heaps; - } // namespace hwmalloc diff --git a/include/hwmalloc/heap_config.hpp b/include/hwmalloc/heap_config.hpp new file mode 100644 index 0000000..bc58e41 --- /dev/null +++ b/include/hwmalloc/heap_config.hpp @@ -0,0 +1,52 @@ +/* + * ghex-org + * + * Copyright (c) 2014-2023, ETH Zurich + * All rights reserved. + * + * Please, refer to the LICENSE file in the root directory. + * SPDX-License-Identifier: BSD-3-Clause + */ +#pragma once + +#include + +namespace hwmalloc +{ +namespace detail +{ +inline constexpr std::size_t +log2_c(std::size_t n) noexcept +{ + return ((n < 2) ? 1 : 1 + log2_c(n >> 1)); +} + +inline constexpr std::size_t +round_to_pow_of_2(std::size_t n) noexcept +{ + return 1u << log2_c(n - 1); +} +} // namespace detail + +struct heap_config +{ + std::size_t m_tiny_limit; + std::size_t m_small_limit; + std::size_t m_large_limit; + std::size_t m_bucket_shift = detail::log2_c(m_tiny_limit) - 1; + std::size_t m_tiny_segment_size; + std::size_t m_small_segment_size; + std::size_t m_large_segment_size; + static constexpr std::size_t m_tiny_increment_shift = 3; + static constexpr std::size_t m_tiny_increment = (1u << m_tiny_increment_shift); + std::size_t m_num_tiny_heaps = m_tiny_limit / m_tiny_increment; + std::size_t m_num_small_heaps = detail::log2_c(m_small_limit) - detail::log2_c(m_tiny_limit); + std::size_t m_num_large_heaps = detail::log2_c(m_large_limit) - detail::log2_c(m_small_limit); + + heap_config(std::size_t tiny_limit, std::size_t small_limit, std::size_t large_limit, + std::size_t tiny_segment_size, std::size_t small_segment_size, + std::size_t large_segment_size); +}; + +heap_config const& get_default_heap_config(); +} // namespace hwmalloc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 66e14a6..042a508 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,5 @@ +target_sources(hwmalloc PRIVATE heap_config.cpp) + if (NUMA_LIBRARY) target_sources(hwmalloc PRIVATE numa.cpp) else() diff --git a/src/heap_config.cpp b/src/heap_config.cpp new file mode 100644 index 0000000..73bf249 --- /dev/null +++ b/src/heap_config.cpp @@ -0,0 +1,93 @@ +/* + * ghex-org + * + * Copyright (c) 2014-2023, ETH Zurich + * All rights reserved. + * + * Please, refer to the LICENSE file in the root directory. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#ifdef HWMALLOC_ENABLE_LOGGING +#include +#include +#endif + +#include +#include + +namespace hwmalloc +{ +namespace detail +{ +static std::size_t +get_env_size_t(const char* name, std::size_t default_value) noexcept +{ + const char* env_value = std::getenv(name); + if (env_value) + { + try + { + return std::stoul(env_value); + } + catch (...) + { +#ifdef HWMALLOC_ENABLE_LOGGING + HWMALLOC_LOG("failed to parse configuration option", name, "=", env_value, + ", using default =", default_value); +#endif + return default_value; + } + } + + return default_value; +} +} // namespace detail + +heap_config::heap_config(std::size_t tiny_limit, std::size_t small_limit, std::size_t large_limit, + std::size_t tiny_segment_size, std::size_t small_segment_size, std::size_t large_segment_size) +: m_tiny_limit{detail::round_to_pow_of_2(tiny_limit)} +, m_small_limit{detail::round_to_pow_of_2(small_limit)} +, m_large_limit{detail::round_to_pow_of_2(large_limit)} +, m_tiny_segment_size{detail::round_to_pow_of_2(tiny_segment_size)} +, m_small_segment_size{detail::round_to_pow_of_2(small_segment_size)} +, m_large_segment_size{detail::round_to_pow_of_2(large_segment_size)} +{ + // Validate that tiny_limit < small_limit < large_limit + if (!(m_tiny_limit < m_small_limit && m_small_limit < m_large_limit)) + { + // TODO: Print actual values + throw std::runtime_error( + "Invalid heap size configuration: " + "HWMALLOC_TINY_LIMIT < HWMALLOC_SMALL_LIMIT < HWMALLOC_LARGE_LIMIT must hold."); + } + + // Validate that limits are at most segment sizes + if (!(tiny_limit <= tiny_segment_size && small_limit <= small_segment_size && + large_limit <= large_segment_size)) + { + // TODO: Print actual values + throw std::runtime_error("Invalid heap size configuration: " + "Limits must be at most segment sizes."); + } +} + +heap_config const& +get_default_heap_config() +{ + // TODO: Add comment for sizes + static heap_config config{detail::get_env_size_t("HWMALLOC_TINY_LIMIT", (1u << 7)), + detail::get_env_size_t("HWMALLOC_SMALL_LIMIT", (1u << 10)), + detail::get_env_size_t("HWMALLOC_LARGE_LIMIT", (1u << 16)), + detail::get_env_size_t("HWMALLOC_TINY_SEGMENT_SIZE", 0x04000), + detail::get_env_size_t("HWMALLOC_SMALL_SEGMENT_SIZE", 0x08000), + detail::get_env_size_t("HWMALLOC_LARGE_SEGMENT_SIZE", 0x10000) + + }; + + return config; +} +} // namespace hwmalloc From 8b27a3e4dd166ebae4f97b921fe83669078bcc88 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Tue, 21 Oct 2025 16:18:45 +0200 Subject: [PATCH 02/15] Add tests for heap_config --- test/CMakeLists.txt | 3 + test/test_heap_config.cpp | 215 ++++++++++++++++++++++++++++++ test/test_heap_config_default.cpp | 42 ++++++ test/test_heap_config_invalid.cpp | 59 ++++++++ 4 files changed, 319 insertions(+) create mode 100644 test/test_heap_config.cpp create mode 100644 test/test_heap_config_default.cpp create mode 100644 test/test_heap_config_invalid.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f339a3c..859b97c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,9 @@ if (NUMA_LIBRARY AND NOT HWMALLOC_DISABLE_NUMA_TEST) endif() reg_test(test_ptr) reg_test(test_segment) +reg_test(test_heap_config) +reg_test(test_heap_config_default) +reg_test(test_heap_config_invalid) if (NUMA_LIBRARY) find_package(OpenMP REQUIRED) diff --git a/test/test_heap_config.cpp b/test/test_heap_config.cpp new file mode 100644 index 0000000..8f04253 --- /dev/null +++ b/test/test_heap_config.cpp @@ -0,0 +1,215 @@ +/* + * ghex-org + * + * Copyright (c) 2014-2025, ETH Zurich + * All rights reserved. + * + * Please, refer to the LICENSE file in the root directory. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include + +#include + +// These should change accordingly if the defaults in heap_config.cpp change. +// They are defined here for a little bit of convenience in the tests below. +inline constexpr std::size_t tiny_limit_default = 128u; +inline constexpr std::size_t small_limit_default = 1024u; +inline constexpr std::size_t large_limit_default = 65536u; +inline constexpr std::size_t bucket_shift_default = 7u; +inline constexpr std::size_t tiny_segment_size_default = 0x04000u; +inline constexpr std::size_t small_segment_size_default = 0x08000u; +inline constexpr std::size_t large_segment_size_default = 0x10000u; +inline constexpr std::size_t tiny_increment_shift_default = 3u; +inline constexpr std::size_t tiny_increment_default = 8u; +inline constexpr std::size_t num_tiny_heaps_default = 16u; +inline constexpr std::size_t num_small_heaps_default = 3u; +inline constexpr std::size_t num_large_heaps_default = 6u; + +// Check that the default configuration values are as expected. +TEST(heap_config, defaults) +{ + hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); + + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); +} + +// We try changing one parameter a time compared to the defaults and check that +// the derived values change accordingly. +TEST(heap_config, tiny_limit) +{ + hwmalloc::heap_config config{256u, small_limit_default, large_limit_default, + tiny_segment_size_default, small_segment_size_default, large_segment_size_default}; + + EXPECT_EQ(config.m_tiny_limit, 256u); // This changes to the literal value we set + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, 8u); // This changes based on tiny_limit + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, 32u); // This number doubles... + EXPECT_EQ(config.m_num_small_heaps, 2u); // While this is decreased by one + EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); +} + +TEST(heap_config, tiny_segment) +{ + hwmalloc::heap_config config{tiny_limit_default, small_limit_default, large_limit_default, + 8192u, small_segment_size_default, large_segment_size_default}; + + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, 8192u); // This changes to the literal value we set + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); +} + +TEST(heap_config, small_limit) +{ + hwmalloc::heap_config config{tiny_limit_default, 4096u, large_limit_default, + tiny_segment_size_default, small_segment_size_default, large_segment_size_default}; + + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, 4096u); // This changes to the literal value we set + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, 5u); // This is log2(4096)-log2(128) = 5... + EXPECT_EQ(config.m_num_large_heaps, 4u); // While this is decreased accordingly +} + +TEST(heap_config, small_segment) +{ + hwmalloc::heap_config config{tiny_limit_default, small_limit_default, large_limit_default, + tiny_segment_size_default, 16384u, large_segment_size_default}; + + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, 16384u); // This changes to the literal value we set + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); +} + +TEST(heap_config, large_limit) +{ + hwmalloc::heap_config config{tiny_limit_default, small_limit_default, 32768u, + tiny_segment_size_default, small_segment_size_default, large_segment_size_default}; + + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, 32768u); // This changes to the literal value we set + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, 5u); // This is increased accordingly +} + +TEST(heap_config, large_segment) +{ + hwmalloc::heap_config config{tiny_limit_default, small_limit_default, large_limit_default, + tiny_segment_size_default, small_segment_size_default, 131072u}; + + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, 131072u); // This changes to the literal value we set + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); +} + +// Check that setting non-power-of-two values results in rounding to power of two +TEST(heap_config, power_of_two) +{ + hwmalloc::heap_config config{200u, 500u, 20000u, 1000u, 3000u, 100000u}; + + EXPECT_EQ(config.m_tiny_limit, 256u); // Rounded up from 200 + EXPECT_EQ(config.m_small_limit, 512u); // Rounded up from 500 + EXPECT_EQ(config.m_large_limit, 32768u); // Rounded up from 20000 + EXPECT_EQ(config.m_tiny_segment_size, 1024u); // Rounded up from 1000 + EXPECT_EQ(config.m_small_segment_size, 4096u); // Rounded up from 3000 + EXPECT_EQ(config.m_large_segment_size, 131072u); // Rounded up from 100000 +} + +// Check that setting invalid values results in exceptions +TEST(heap_config, validate_tiny_small_limit) +{ + EXPECT_THROW( + (hwmalloc::heap_config{2048u, 1024u, large_limit_default, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}), + std::runtime_error); +} + +TEST(heap_config, validate_small_large_limit) +{ + EXPECT_THROW( + (hwmalloc::heap_config{tiny_limit_default, 131072u, 65536u, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}), + std::runtime_error); +} + +TEST(heap_config, validate_tiny_limit_segment_size) +{ + EXPECT_THROW((hwmalloc::heap_config{2048u, small_limit_default, large_limit_default, 1024u, + small_segment_size_default, large_segment_size_default}), + std::runtime_error); +} + +TEST(heap_config, validate_small_limit_segment_size) +{ + EXPECT_THROW((hwmalloc::heap_config{tiny_limit_default, 131072u, large_limit_default, + tiny_segment_size_default, 65536u, large_segment_size_default}), + std::runtime_error); +} + +TEST(heap_config, validate_large_limit_segment_size) +{ + EXPECT_THROW((hwmalloc::heap_config{tiny_limit_default, small_limit_default, 262144u, + tiny_segment_size_default, small_segment_size_default, 131072u}), + std::runtime_error); +} diff --git a/test/test_heap_config_default.cpp b/test/test_heap_config_default.cpp new file mode 100644 index 0000000..e70ead5 --- /dev/null +++ b/test/test_heap_config_default.cpp @@ -0,0 +1,42 @@ +/* + * ghex-org + * + * Copyright (c) 2014-2025, ETH Zurich + * All rights reserved. + * + * Please, refer to the LICENSE file in the root directory. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include + +#include + +// Check that we can change the default configuration values through environment +// variables. +TEST(config, defaults) +{ + ::setenv("HWMALLOC_TINY_LIMIT", "512", 1); + ::setenv("HWMALLOC_SMALL_LIMIT", "2000", 1); + ::setenv("HWMALLOC_LARGE_LIMIT", "131072", 1); + ::setenv("HWMALLOC_TINY_SEGMENT_SIZE", "16384", 1); + ::setenv("HWMALLOC_SMALL_SEGMENT_SIZE", "32768", 1); + ::setenv("HWMALLOC_LARGE_SEGMENT_SIZE", "262144", 1); + + hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); + + EXPECT_EQ(config.m_tiny_limit, 512u); + EXPECT_EQ(config.m_small_limit, 2048); + EXPECT_EQ(config.m_large_limit, 131072u); + EXPECT_EQ(config.m_bucket_shift, 9u); + EXPECT_EQ(config.m_tiny_segment_size, 16384u); + EXPECT_EQ(config.m_small_segment_size, 32768u); + EXPECT_EQ(config.m_large_segment_size, 262144u); + EXPECT_EQ(config.m_tiny_increment_shift, 3u); + EXPECT_EQ(config.m_tiny_increment, 8u); + EXPECT_EQ(config.m_num_tiny_heaps, 64u); + EXPECT_EQ(config.m_num_small_heaps, 2u); + EXPECT_EQ(config.m_num_large_heaps, 6u); +} + diff --git a/test/test_heap_config_invalid.cpp b/test/test_heap_config_invalid.cpp new file mode 100644 index 0000000..9073593 --- /dev/null +++ b/test/test_heap_config_invalid.cpp @@ -0,0 +1,59 @@ +/* + * ghex-org + * + * Copyright (c) 2014-2025, ETH Zurich + * All rights reserved. + * + * Please, refer to the LICENSE file in the root directory. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include + +#include + +// These should change accordingly if the defaults in heap_config.cpp change. +// They are defined here for a little bit of convenience in the tests below. +inline constexpr std::size_t tiny_limit_default = 128u; +inline constexpr std::size_t small_limit_default = 1024u; +inline constexpr std::size_t large_limit_default = 65536u; +inline constexpr std::size_t bucket_shift_default = 7u; +inline constexpr std::size_t tiny_segment_size_default = 0x04000u; +inline constexpr std::size_t small_segment_size_default = 0x08000u; +inline constexpr std::size_t large_segment_size_default = 0x10000u; +inline constexpr std::size_t tiny_increment_shift_default = 3u; +inline constexpr std::size_t tiny_increment_default = 8u; +inline constexpr std::size_t num_tiny_heaps_default = 16u; +inline constexpr std::size_t num_small_heaps_default = 3u; +inline constexpr std::size_t num_large_heaps_default = 6u; + +// Test that config falls back to defaults if environment variables are given +// non-numeric values. +// +// A warning is printed if logging is enabled. +TEST(config, defaults) +{ + ::setenv("HWMALLOC_TINY_LIMIT", "abcd", 1); + ::setenv("HWMALLOC_SMALL_LIMIT", "2048", 1); + ::setenv("HWMALLOC_LARGE_LIMIT", "foo", 1); + ::setenv("HWMALLOC_TINY_SEGMENT_SIZE", "16384", 1); + ::setenv("HWMALLOC_SMALL_SEGMENT_SIZE", "bar", 1); + ::setenv("HWMALLOC_LARGE_SEGMENT_SIZE", "262144", 1); + + hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); + + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, 2048); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, 262144u); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, 4u); + EXPECT_EQ(config.m_num_large_heaps, 5u); +} + From ceed1c81c4e58a9d21dc8eaaefaf35c7a523044d Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Wed, 22 Oct 2025 11:31:14 +0200 Subject: [PATCH 03/15] Print invalid values in heap_config --- src/heap_config.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/heap_config.cpp b/src/heap_config.cpp index 73bf249..fabac99 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -13,6 +13,8 @@ #ifdef HWMALLOC_ENABLE_LOGGING #include + +#include #include #endif @@ -59,19 +61,27 @@ heap_config::heap_config(std::size_t tiny_limit, std::size_t small_limit, std::s // Validate that tiny_limit < small_limit < large_limit if (!(m_tiny_limit < m_small_limit && m_small_limit < m_large_limit)) { - // TODO: Print actual values - throw std::runtime_error( - "Invalid heap size configuration: " - "HWMALLOC_TINY_LIMIT < HWMALLOC_SMALL_LIMIT < HWMALLOC_LARGE_LIMIT must hold."); + std::ostringstream os; + os << "Invalid heap size configuration: HWMALLOC_TINY_LIMIT < HWMALLOC_SMALL_LIMIT < HWMALLOC_LARGE_LIMIT must hold."; + os << "Got HWMALLOC_TINY_LIMIT=" << m_tiny_limit + << ", HWMALLOC_SMALL_LIMIT=" << m_small_limit + << ", HWMALLOC_LARGE_LIMIT=" << m_large_limit << "."; + throw std::runtime_error(os.str()); } // Validate that limits are at most segment sizes if (!(tiny_limit <= tiny_segment_size && small_limit <= small_segment_size && large_limit <= large_segment_size)) { - // TODO: Print actual values - throw std::runtime_error("Invalid heap size configuration: " - "Limits must be at most segment sizes."); + std::ostringstream os; + os << "Invalid heap size configuration: Limits must be at most segment sizes."; + os << "Got HWMALLOC_TINY_LIMIT=" << m_tiny_limit + << ", HWMALLOC_TINY_SEGMENT_SIZE=" << m_tiny_segment_size + << ", HWMALLOC_SMALL_LIMIT=" << m_small_limit + << ", HWMALLOC_SMALL_SEGMENT_SIZE=" << m_small_segment_size + << ", HWMALLOC_LARGE_LIMIT=" << m_large_limit + << ", HWMALLOC_LARGE_SEGMENT_SIZE=" << m_large_segment_size << "."; + throw std::runtime_error(os.str()); } } From a42ff84d727a078ac854f33a8f78f7ca66e9088a Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Wed, 22 Oct 2025 11:39:23 +0200 Subject: [PATCH 04/15] Specify segment sizes same way as limits --- src/heap_config.cpp | 15 ++++++++------- test/test_heap_config.cpp | 6 +++--- test/test_heap_config_invalid.cpp | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/heap_config.cpp b/src/heap_config.cpp index fabac99..6d3ccf8 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -88,13 +88,14 @@ heap_config::heap_config(std::size_t tiny_limit, std::size_t small_limit, std::s heap_config const& get_default_heap_config() { - // TODO: Add comment for sizes - static heap_config config{detail::get_env_size_t("HWMALLOC_TINY_LIMIT", (1u << 7)), - detail::get_env_size_t("HWMALLOC_SMALL_LIMIT", (1u << 10)), - detail::get_env_size_t("HWMALLOC_LARGE_LIMIT", (1u << 16)), - detail::get_env_size_t("HWMALLOC_TINY_SEGMENT_SIZE", 0x04000), - detail::get_env_size_t("HWMALLOC_SMALL_SEGMENT_SIZE", 0x08000), - detail::get_env_size_t("HWMALLOC_LARGE_SEGMENT_SIZE", 0x10000) + static heap_config config{ + // TODO: Increase limits and sizes + detail::get_env_size_t("HWMALLOC_TINY_LIMIT", (1u << 7)), // 128B + detail::get_env_size_t("HWMALLOC_SMALL_LIMIT", (1u << 10)), // 1KiB + detail::get_env_size_t("HWMALLOC_LARGE_LIMIT", (1u << 16)), // 64KiB + detail::get_env_size_t("HWMALLOC_TINY_SEGMENT_SIZE", (1u << 14)), // 16KiB + detail::get_env_size_t("HWMALLOC_SMALL_SEGMENT_SIZE", (1u << 15)), // 32KiB + detail::get_env_size_t("HWMALLOC_LARGE_SEGMENT_SIZE", (1u << 16)) // 64KiB }; diff --git a/test/test_heap_config.cpp b/test/test_heap_config.cpp index 8f04253..a0b3b55 100644 --- a/test/test_heap_config.cpp +++ b/test/test_heap_config.cpp @@ -19,9 +19,9 @@ inline constexpr std::size_t tiny_limit_default = 128u; inline constexpr std::size_t small_limit_default = 1024u; inline constexpr std::size_t large_limit_default = 65536u; inline constexpr std::size_t bucket_shift_default = 7u; -inline constexpr std::size_t tiny_segment_size_default = 0x04000u; -inline constexpr std::size_t small_segment_size_default = 0x08000u; -inline constexpr std::size_t large_segment_size_default = 0x10000u; +inline constexpr std::size_t tiny_segment_size_default = 16384u; +inline constexpr std::size_t small_segment_size_default = 32768u; +inline constexpr std::size_t large_segment_size_default = 65536u; inline constexpr std::size_t tiny_increment_shift_default = 3u; inline constexpr std::size_t tiny_increment_default = 8u; inline constexpr std::size_t num_tiny_heaps_default = 16u; diff --git a/test/test_heap_config_invalid.cpp b/test/test_heap_config_invalid.cpp index 9073593..668430d 100644 --- a/test/test_heap_config_invalid.cpp +++ b/test/test_heap_config_invalid.cpp @@ -19,9 +19,9 @@ inline constexpr std::size_t tiny_limit_default = 128u; inline constexpr std::size_t small_limit_default = 1024u; inline constexpr std::size_t large_limit_default = 65536u; inline constexpr std::size_t bucket_shift_default = 7u; -inline constexpr std::size_t tiny_segment_size_default = 0x04000u; -inline constexpr std::size_t small_segment_size_default = 0x08000u; -inline constexpr std::size_t large_segment_size_default = 0x10000u; +inline constexpr std::size_t tiny_segment_size_default = 16384u; +inline constexpr std::size_t small_segment_size_default = 32768u; +inline constexpr std::size_t large_segment_size_default = 65536u; inline constexpr std::size_t tiny_increment_shift_default = 3u; inline constexpr std::size_t tiny_increment_default = 8u; inline constexpr std::size_t num_tiny_heaps_default = 16u; From ca54f36411ddb2b0690d0948d73bf6129d5132cc Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Wed, 22 Oct 2025 11:41:50 +0200 Subject: [PATCH 05/15] Update copyright years --- include/hwmalloc/heap.hpp | 2 +- include/hwmalloc/heap_config.hpp | 2 +- src/heap_config.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/hwmalloc/heap.hpp b/include/hwmalloc/heap.hpp index 34804ed..4ab79c4 100644 --- a/include/hwmalloc/heap.hpp +++ b/include/hwmalloc/heap.hpp @@ -1,7 +1,7 @@ /* * ghex-org * - * Copyright (c) 2014-2023, ETH Zurich + * Copyright (c) 2014-2025, ETH Zurich * All rights reserved. * * Please, refer to the LICENSE file in the root directory. diff --git a/include/hwmalloc/heap_config.hpp b/include/hwmalloc/heap_config.hpp index bc58e41..1970af2 100644 --- a/include/hwmalloc/heap_config.hpp +++ b/include/hwmalloc/heap_config.hpp @@ -1,7 +1,7 @@ /* * ghex-org * - * Copyright (c) 2014-2023, ETH Zurich + * Copyright (c) 2014-2025, ETH Zurich * All rights reserved. * * Please, refer to the LICENSE file in the root directory. diff --git a/src/heap_config.cpp b/src/heap_config.cpp index 6d3ccf8..2cf8954 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -1,7 +1,7 @@ /* * ghex-org * - * Copyright (c) 2014-2023, ETH Zurich + * Copyright (c) 2014-2025, ETH Zurich * All rights reserved. * * Please, refer to the LICENSE file in the root directory. From ffefcefea4a0cc889a3aebf69e5bed21d681cfc3 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Wed, 22 Oct 2025 11:52:49 +0200 Subject: [PATCH 06/15] Put sstream include in right place --- src/heap_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/heap_config.cpp b/src/heap_config.cpp index 2cf8954..0747b3a 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -14,11 +14,11 @@ #ifdef HWMALLOC_ENABLE_LOGGING #include -#include #include #endif #include +#include #include namespace hwmalloc From 752dfafcdcadb10611bd7e2ab7ad7a3f452fc6e4 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 24 Oct 2025 10:48:15 +0200 Subject: [PATCH 07/15] Add missing spaces to log messages --- include/hwmalloc/heap.hpp | 28 +++++++++-------------- include/hwmalloc/heap_config.hpp | 8 ++++--- src/heap_config.cpp | 38 +++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/include/hwmalloc/heap.hpp b/include/hwmalloc/heap.hpp index 4ab79c4..76b28cc 100644 --- a/include/hwmalloc/heap.hpp +++ b/include/hwmalloc/heap.hpp @@ -117,47 +117,41 @@ class heap heap_config m_config; Context* m_context; std::size_t m_max_size; - bool m_never_free; - std::size_t m_num_reserve_segments; heap_vector m_tiny_heaps; heap_vector m_heaps; heap_map m_huge_heaps; std::mutex m_mutex; public: - // TODO: never_free and num_reserve_segments in heap_config? - heap(Context* context, bool never_free = false, std::size_t num_reserve_segments = 1, - heap_config config = get_default_heap_config()) + heap(Context* context, heap_config const& config = get_default_heap_config()) : m_config{config} , m_context{context} , m_max_size( std::max(detail::round_to_pow_of_2(m_config.m_large_limit * 2), m_config.m_large_limit)) - , m_never_free{never_free} - , m_num_reserve_segments{num_reserve_segments} , m_tiny_heaps(m_config.m_tiny_limit / m_config.m_tiny_increment) , m_heaps(bucket_index(m_max_size, m_config.m_bucket_shift) + 1) { for (std::size_t i = 0; i < m_tiny_heaps.size(); ++i) m_tiny_heaps[i] = std::make_unique(m_context, - m_config.m_tiny_increment * (i + 1), m_config.m_tiny_segment_size, m_never_free, - m_num_reserve_segments); + m_config.m_tiny_increment * (i + 1), m_config.m_tiny_segment_size, + m_config.m_never_free, m_config.m_num_reserve_segments); for (std::size_t i = 0; i < m_config.m_num_small_heaps; ++i) m_heaps[i] = std::make_unique(m_context, - (m_config.m_tiny_limit << (i + 1)), m_config.m_small_segment_size, m_never_free, - m_num_reserve_segments); + (m_config.m_tiny_limit << (i + 1)), m_config.m_small_segment_size, + m_config.m_never_free, m_config.m_num_reserve_segments); for (std::size_t i = 0; i < m_config.m_num_large_heaps; ++i) m_heaps[i + m_config.m_num_small_heaps] = std::make_unique( m_context, (m_config.m_small_limit << (i + 1)), m_config.m_large_segment_size, - m_never_free, m_num_reserve_segments); + m_config.m_never_free, m_config.m_num_reserve_segments); for (std::size_t i = 0; i < m_heaps.size() - (m_config.m_num_small_heaps + m_config.m_num_large_heaps); ++i) m_heaps[i + m_config.m_num_small_heaps + m_config.m_num_large_heaps] = std::make_unique(m_context, (m_config.m_large_limit << (i + 1)), (m_config.m_large_limit << (i + 1)), - m_never_free, m_num_reserve_segments); + m_config.m_never_free, m_config.m_num_reserve_segments); } heap(heap const&) = delete; @@ -196,8 +190,8 @@ class heap const auto s = detail::round_to_pow_of_2(size); auto& u_ptr = m_huge_heaps[s]; if (!u_ptr) - u_ptr = std::make_unique(m_context, s, s, m_never_free, - m_num_reserve_segments); + u_ptr = std::make_unique(m_context, s, s, + m_config.m_never_free, m_config.m_num_reserve_segments); h = u_ptr.get(); } return {h->allocate(numa_node)}; @@ -228,8 +222,8 @@ class heap const auto s = detail::round_to_pow_of_2(size); auto& u_ptr = m_huge_heaps[s]; if (!u_ptr) - u_ptr = std::make_unique(m_context, s, s, m_never_free, - m_num_reserve_segments); + u_ptr = std::make_unique(m_context, s, s, + m_config.m_never_free, m_config.m_num_reserve_segments); h = u_ptr.get(); } return {h->allocate(numa_node, device_id)}; diff --git a/include/hwmalloc/heap_config.hpp b/include/hwmalloc/heap_config.hpp index 1970af2..886eb31 100644 --- a/include/hwmalloc/heap_config.hpp +++ b/include/hwmalloc/heap_config.hpp @@ -30,6 +30,8 @@ round_to_pow_of_2(std::size_t n) noexcept struct heap_config { + bool m_never_free; + std::size_t m_num_reserve_segments; std::size_t m_tiny_limit; std::size_t m_small_limit; std::size_t m_large_limit; @@ -43,9 +45,9 @@ struct heap_config std::size_t m_num_small_heaps = detail::log2_c(m_small_limit) - detail::log2_c(m_tiny_limit); std::size_t m_num_large_heaps = detail::log2_c(m_large_limit) - detail::log2_c(m_small_limit); - heap_config(std::size_t tiny_limit, std::size_t small_limit, std::size_t large_limit, - std::size_t tiny_segment_size, std::size_t small_segment_size, - std::size_t large_segment_size); + heap_config(bool never_free, std::size_t num_reserve_segments, std::size_t tiny_limit, + std::size_t small_limit, std::size_t large_limit, std::size_t tiny_segment_size, + std::size_t small_segment_size, std::size_t large_segment_size); }; heap_config const& get_default_heap_config(); diff --git a/src/heap_config.cpp b/src/heap_config.cpp index 0747b3a..27db9d6 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -25,6 +25,29 @@ namespace hwmalloc { namespace detail { +static bool +get_env_bool(const char* name, bool default_value) noexcept +{ + const char* env_value = std::getenv(name); + if (env_value) + { + try + { + return std::stoul(env_value) != 0; + } + catch (...) + { +#ifdef HWMALLOC_ENABLE_LOGGING + HWMALLOC_LOG("failed to parse boolean configuration option", name, "=", env_value, + "(expected 0 or 1), using default =", default_value); +#endif + return default_value; + } + } + + return default_value; +} + static std::size_t get_env_size_t(const char* name, std::size_t default_value) noexcept { @@ -49,9 +72,12 @@ get_env_size_t(const char* name, std::size_t default_value) noexcept } } // namespace detail -heap_config::heap_config(std::size_t tiny_limit, std::size_t small_limit, std::size_t large_limit, - std::size_t tiny_segment_size, std::size_t small_segment_size, std::size_t large_segment_size) -: m_tiny_limit{detail::round_to_pow_of_2(tiny_limit)} +heap_config::heap_config(bool never_free, std::size_t num_reserve_segments, std::size_t tiny_limit, + std::size_t small_limit, std::size_t large_limit, std::size_t tiny_segment_size, + std::size_t small_segment_size, std::size_t large_segment_size) +: m_never_free{never_free} +, m_num_reserve_segments{num_reserve_segments} +, m_tiny_limit{detail::round_to_pow_of_2(tiny_limit)} , m_small_limit{detail::round_to_pow_of_2(small_limit)} , m_large_limit{detail::round_to_pow_of_2(large_limit)} , m_tiny_segment_size{detail::round_to_pow_of_2(tiny_segment_size)} @@ -62,7 +88,7 @@ heap_config::heap_config(std::size_t tiny_limit, std::size_t small_limit, std::s if (!(m_tiny_limit < m_small_limit && m_small_limit < m_large_limit)) { std::ostringstream os; - os << "Invalid heap size configuration: HWMALLOC_TINY_LIMIT < HWMALLOC_SMALL_LIMIT < HWMALLOC_LARGE_LIMIT must hold."; + os << "Invalid heap size configuration: HWMALLOC_TINY_LIMIT < HWMALLOC_SMALL_LIMIT < HWMALLOC_LARGE_LIMIT must hold. "; os << "Got HWMALLOC_TINY_LIMIT=" << m_tiny_limit << ", HWMALLOC_SMALL_LIMIT=" << m_small_limit << ", HWMALLOC_LARGE_LIMIT=" << m_large_limit << "."; @@ -74,7 +100,7 @@ heap_config::heap_config(std::size_t tiny_limit, std::size_t small_limit, std::s large_limit <= large_segment_size)) { std::ostringstream os; - os << "Invalid heap size configuration: Limits must be at most segment sizes."; + os << "Invalid heap size configuration: Limits must be at most segment sizes. "; os << "Got HWMALLOC_TINY_LIMIT=" << m_tiny_limit << ", HWMALLOC_TINY_SEGMENT_SIZE=" << m_tiny_segment_size << ", HWMALLOC_SMALL_LIMIT=" << m_small_limit @@ -90,6 +116,8 @@ get_default_heap_config() { static heap_config config{ // TODO: Increase limits and sizes + detail::get_env_bool("HWMALLOC_NEVER_FREE", false), + detail::get_env_size_t("HWMALLOC_NUM_RESERVE_SEGMENTS", 1u), detail::get_env_size_t("HWMALLOC_TINY_LIMIT", (1u << 7)), // 128B detail::get_env_size_t("HWMALLOC_SMALL_LIMIT", (1u << 10)), // 1KiB detail::get_env_size_t("HWMALLOC_LARGE_LIMIT", (1u << 16)), // 64KiB From 251320ffeee711c6114de7d1a3ed5a4099273a71 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 24 Oct 2025 11:07:48 +0200 Subject: [PATCH 08/15] Update default heap_config and tests accordingly --- src/heap_config.cpp | 13 ++- test/test_heap_config.cpp | 147 ++++++++++++++++++++++-------- test/test_heap_config_default.cpp | 5 +- test/test_heap_config_invalid.cpp | 35 ++++--- 4 files changed, 139 insertions(+), 61 deletions(-) diff --git a/src/heap_config.cpp b/src/heap_config.cpp index 27db9d6..9bd3e5f 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -115,15 +115,14 @@ heap_config const& get_default_heap_config() { static heap_config config{ - // TODO: Increase limits and sizes detail::get_env_bool("HWMALLOC_NEVER_FREE", false), - detail::get_env_size_t("HWMALLOC_NUM_RESERVE_SEGMENTS", 1u), + detail::get_env_size_t("HWMALLOC_NUM_RESERVE_SEGMENTS", 16u), detail::get_env_size_t("HWMALLOC_TINY_LIMIT", (1u << 7)), // 128B - detail::get_env_size_t("HWMALLOC_SMALL_LIMIT", (1u << 10)), // 1KiB - detail::get_env_size_t("HWMALLOC_LARGE_LIMIT", (1u << 16)), // 64KiB - detail::get_env_size_t("HWMALLOC_TINY_SEGMENT_SIZE", (1u << 14)), // 16KiB - detail::get_env_size_t("HWMALLOC_SMALL_SEGMENT_SIZE", (1u << 15)), // 32KiB - detail::get_env_size_t("HWMALLOC_LARGE_SEGMENT_SIZE", (1u << 16)) // 64KiB + detail::get_env_size_t("HWMALLOC_SMALL_LIMIT", (1u << 12)), // 4KiB + detail::get_env_size_t("HWMALLOC_LARGE_LIMIT", (1u << 21)), // 2MiB + detail::get_env_size_t("HWMALLOC_TINY_SEGMENT_SIZE", (1u << 16)), // 64KiB + detail::get_env_size_t("HWMALLOC_SMALL_SEGMENT_SIZE", (1u << 16)), // 64KiB + detail::get_env_size_t("HWMALLOC_LARGE_SEGMENT_SIZE", (1u << 21)) // 2MiB }; diff --git a/test/test_heap_config.cpp b/test/test_heap_config.cpp index a0b3b55..851592c 100644 --- a/test/test_heap_config.cpp +++ b/test/test_heap_config.cpp @@ -15,24 +15,28 @@ // These should change accordingly if the defaults in heap_config.cpp change. // They are defined here for a little bit of convenience in the tests below. +inline constexpr bool never_free_default = false; +inline constexpr std::size_t num_reserve_segments_default = 16u; inline constexpr std::size_t tiny_limit_default = 128u; -inline constexpr std::size_t small_limit_default = 1024u; -inline constexpr std::size_t large_limit_default = 65536u; +inline constexpr std::size_t small_limit_default = 4096u; +inline constexpr std::size_t large_limit_default = 2097152u; inline constexpr std::size_t bucket_shift_default = 7u; -inline constexpr std::size_t tiny_segment_size_default = 16384u; -inline constexpr std::size_t small_segment_size_default = 32768u; -inline constexpr std::size_t large_segment_size_default = 65536u; +inline constexpr std::size_t tiny_segment_size_default = 65536u; +inline constexpr std::size_t small_segment_size_default = 65536u; +inline constexpr std::size_t large_segment_size_default = 2097152u; inline constexpr std::size_t tiny_increment_shift_default = 3u; inline constexpr std::size_t tiny_increment_default = 8u; inline constexpr std::size_t num_tiny_heaps_default = 16u; -inline constexpr std::size_t num_small_heaps_default = 3u; -inline constexpr std::size_t num_large_heaps_default = 6u; +inline constexpr std::size_t num_small_heaps_default = 5u; +inline constexpr std::size_t num_large_heaps_default = 9u; // Check that the default configuration values are as expected. TEST(heap_config, defaults) { hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); EXPECT_EQ(config.m_small_limit, small_limit_default); EXPECT_EQ(config.m_large_limit, large_limit_default); @@ -49,11 +53,58 @@ TEST(heap_config, defaults) // We try changing one parameter a time compared to the defaults and check that // the derived values change accordingly. +TEST(heap_config, never_free) +{ + hwmalloc::heap_config config{true, num_reserve_segments_default, tiny_limit_default, + small_limit_default, large_limit_default, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}; + + EXPECT_EQ(config.m_never_free, true); // This changes to the literal value we set + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); +} + +TEST(heap_config, num_reserve_segments) +{ + hwmalloc::heap_config config{never_free_default, 7, tiny_limit_default, small_limit_default, + large_limit_default, tiny_segment_size_default, small_segment_size_default, + large_segment_size_default}; + + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, 7u); // This changes to the literal value we set + EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); +} + TEST(heap_config, tiny_limit) { - hwmalloc::heap_config config{256u, small_limit_default, large_limit_default, - tiny_segment_size_default, small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, 256u, + small_limit_default, large_limit_default, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}; + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, 256u); // This changes to the literal value we set EXPECT_EQ(config.m_small_limit, small_limit_default); EXPECT_EQ(config.m_large_limit, large_limit_default); @@ -64,15 +115,18 @@ TEST(heap_config, tiny_limit) EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, 32u); // This number doubles... - EXPECT_EQ(config.m_num_small_heaps, 2u); // While this is decreased by one + EXPECT_EQ(config.m_num_small_heaps, 4u); // While this is decreased by one EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); } TEST(heap_config, tiny_segment) { - hwmalloc::heap_config config{tiny_limit_default, small_limit_default, large_limit_default, - 8192u, small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, + tiny_limit_default, small_limit_default, large_limit_default, 8192u, + small_segment_size_default, large_segment_size_default}; + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); EXPECT_EQ(config.m_small_limit, small_limit_default); EXPECT_EQ(config.m_large_limit, large_limit_default); @@ -89,11 +143,14 @@ TEST(heap_config, tiny_segment) TEST(heap_config, small_limit) { - hwmalloc::heap_config config{tiny_limit_default, 4096u, large_limit_default, - tiny_segment_size_default, small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, + tiny_limit_default, 8192u, large_limit_default, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}; + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, 4096u); // This changes to the literal value we set + EXPECT_EQ(config.m_small_limit, 8192u); // This changes to the literal value we set EXPECT_EQ(config.m_large_limit, large_limit_default); EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); @@ -102,15 +159,18 @@ TEST(heap_config, small_limit) EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, 5u); // This is log2(4096)-log2(128) = 5... - EXPECT_EQ(config.m_num_large_heaps, 4u); // While this is decreased accordingly + EXPECT_EQ(config.m_num_small_heaps, 6u); // This is log2(8192)-log2(128) = 6... + EXPECT_EQ(config.m_num_large_heaps, 8u); // While this is decreased accordingly } TEST(heap_config, small_segment) { - hwmalloc::heap_config config{tiny_limit_default, small_limit_default, large_limit_default, - tiny_segment_size_default, 16384u, large_segment_size_default}; + hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, + tiny_limit_default, small_limit_default, large_limit_default, tiny_segment_size_default, + 16384u, large_segment_size_default}; + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); EXPECT_EQ(config.m_small_limit, small_limit_default); EXPECT_EQ(config.m_large_limit, large_limit_default); @@ -127,9 +187,12 @@ TEST(heap_config, small_segment) TEST(heap_config, large_limit) { - hwmalloc::heap_config config{tiny_limit_default, small_limit_default, 32768u, - tiny_segment_size_default, small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, + tiny_limit_default, small_limit_default, 32768u, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}; + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); EXPECT_EQ(config.m_small_limit, small_limit_default); EXPECT_EQ(config.m_large_limit, 32768u); // This changes to the literal value we set @@ -141,21 +204,24 @@ TEST(heap_config, large_limit) EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); - EXPECT_EQ(config.m_num_large_heaps, 5u); // This is increased accordingly + EXPECT_EQ(config.m_num_large_heaps, 3u); // This is decreased accordingly } TEST(heap_config, large_segment) { - hwmalloc::heap_config config{tiny_limit_default, small_limit_default, large_limit_default, - tiny_segment_size_default, small_segment_size_default, 131072u}; + hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, + tiny_limit_default, small_limit_default, large_limit_default, tiny_segment_size_default, + small_segment_size_default, 4194304u}; + EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); EXPECT_EQ(config.m_small_limit, small_limit_default); EXPECT_EQ(config.m_large_limit, large_limit_default); EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, 131072u); // This changes to the literal value we set + EXPECT_EQ(config.m_large_segment_size, 4194304u); // This changes to the literal value we set EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); @@ -166,8 +232,10 @@ TEST(heap_config, large_segment) // Check that setting non-power-of-two values results in rounding to power of two TEST(heap_config, power_of_two) { - hwmalloc::heap_config config{200u, 500u, 20000u, 1000u, 3000u, 100000u}; + hwmalloc::heap_config config{never_free_default, 17u, 200u, 500u, 20000u, 1000u, 3000u, + 100000u}; + EXPECT_EQ(config.m_num_reserve_segments, 17u); // Not rounded up EXPECT_EQ(config.m_tiny_limit, 256u); // Rounded up from 200 EXPECT_EQ(config.m_small_limit, 512u); // Rounded up from 500 EXPECT_EQ(config.m_large_limit, 32768u); // Rounded up from 20000 @@ -179,37 +247,40 @@ TEST(heap_config, power_of_two) // Check that setting invalid values results in exceptions TEST(heap_config, validate_tiny_small_limit) { - EXPECT_THROW( - (hwmalloc::heap_config{2048u, 1024u, large_limit_default, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, 2048u, + 1024u, large_limit_default, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_small_large_limit) { - EXPECT_THROW( - (hwmalloc::heap_config{tiny_limit_default, 131072u, 65536u, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, + tiny_limit_default, 131072u, 65536u, tiny_segment_size_default, + small_segment_size_default, large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_tiny_limit_segment_size) { - EXPECT_THROW((hwmalloc::heap_config{2048u, small_limit_default, large_limit_default, 1024u, - small_segment_size_default, large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, 2048u, + small_limit_default, large_limit_default, 1024u, small_segment_size_default, + large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_small_limit_segment_size) { - EXPECT_THROW((hwmalloc::heap_config{tiny_limit_default, 131072u, large_limit_default, - tiny_segment_size_default, 65536u, large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, + tiny_limit_default, 131072u, large_limit_default, tiny_segment_size_default, + 65536u, large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_large_limit_segment_size) { - EXPECT_THROW((hwmalloc::heap_config{tiny_limit_default, small_limit_default, 262144u, - tiny_segment_size_default, small_segment_size_default, 131072u}), + EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, + tiny_limit_default, small_limit_default, 262144u, tiny_segment_size_default, + small_segment_size_default, 131072u}), std::runtime_error); } diff --git a/test/test_heap_config_default.cpp b/test/test_heap_config_default.cpp index e70ead5..885be0d 100644 --- a/test/test_heap_config_default.cpp +++ b/test/test_heap_config_default.cpp @@ -17,6 +17,8 @@ // variables. TEST(config, defaults) { + ::setenv("HWMALLOC_NEVER_FREE", "1", 1); + ::setenv("HWMALLOC_NUM_RESERVE_SEGMENTS", "19", 1); ::setenv("HWMALLOC_TINY_LIMIT", "512", 1); ::setenv("HWMALLOC_SMALL_LIMIT", "2000", 1); ::setenv("HWMALLOC_LARGE_LIMIT", "131072", 1); @@ -26,6 +28,8 @@ TEST(config, defaults) hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); + EXPECT_EQ(config.m_never_free, true); + EXPECT_EQ(config.m_num_reserve_segments, 19u); EXPECT_EQ(config.m_tiny_limit, 512u); EXPECT_EQ(config.m_small_limit, 2048); EXPECT_EQ(config.m_large_limit, 131072u); @@ -39,4 +43,3 @@ TEST(config, defaults) EXPECT_EQ(config.m_num_small_heaps, 2u); EXPECT_EQ(config.m_num_large_heaps, 6u); } - diff --git a/test/test_heap_config_invalid.cpp b/test/test_heap_config_invalid.cpp index 668430d..dd30e09 100644 --- a/test/test_heap_config_invalid.cpp +++ b/test/test_heap_config_invalid.cpp @@ -15,18 +15,20 @@ // These should change accordingly if the defaults in heap_config.cpp change. // They are defined here for a little bit of convenience in the tests below. +inline constexpr bool never_free_default = false; +inline constexpr std::size_t num_reserve_segments_default = 16u; inline constexpr std::size_t tiny_limit_default = 128u; -inline constexpr std::size_t small_limit_default = 1024u; -inline constexpr std::size_t large_limit_default = 65536u; +inline constexpr std::size_t small_limit_default = 4096u; +inline constexpr std::size_t large_limit_default = 2097152u; inline constexpr std::size_t bucket_shift_default = 7u; -inline constexpr std::size_t tiny_segment_size_default = 16384u; -inline constexpr std::size_t small_segment_size_default = 32768u; -inline constexpr std::size_t large_segment_size_default = 65536u; +inline constexpr std::size_t tiny_segment_size_default = 65536u; +inline constexpr std::size_t small_segment_size_default = 65536u; +inline constexpr std::size_t large_segment_size_default = 2097152u; inline constexpr std::size_t tiny_increment_shift_default = 3u; inline constexpr std::size_t tiny_increment_default = 8u; inline constexpr std::size_t num_tiny_heaps_default = 16u; -inline constexpr std::size_t num_small_heaps_default = 3u; -inline constexpr std::size_t num_large_heaps_default = 6u; +inline constexpr std::size_t num_small_heaps_default = 5u; +inline constexpr std::size_t num_large_heaps_default = 9u; // Test that config falls back to defaults if environment variables are given // non-numeric values. @@ -34,26 +36,29 @@ inline constexpr std::size_t num_large_heaps_default = 6u; // A warning is printed if logging is enabled. TEST(config, defaults) { + ::setenv("HWMALLOC_NEVER_FREE", "foo", 1); + ::setenv("HWMALLOC_NUM_RESERVE_SEGMENTS", "9", 1); ::setenv("HWMALLOC_TINY_LIMIT", "abcd", 1); - ::setenv("HWMALLOC_SMALL_LIMIT", "2048", 1); + ::setenv("HWMALLOC_SMALL_LIMIT", "8192", 1); ::setenv("HWMALLOC_LARGE_LIMIT", "foo", 1); ::setenv("HWMALLOC_TINY_SEGMENT_SIZE", "16384", 1); ::setenv("HWMALLOC_SMALL_SEGMENT_SIZE", "bar", 1); - ::setenv("HWMALLOC_LARGE_SEGMENT_SIZE", "262144", 1); + ::setenv("HWMALLOC_LARGE_SEGMENT_SIZE", "4194304", 1); hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); + EXPECT_EQ(config.m_never_free, false); + EXPECT_EQ(config.m_num_reserve_segments, 9u); EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, 2048); + EXPECT_EQ(config.m_small_limit, 8192); EXPECT_EQ(config.m_large_limit, large_limit_default); EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, 16384u); EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, 262144u); + EXPECT_EQ(config.m_large_segment_size, 4194304u); EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, 4u); - EXPECT_EQ(config.m_num_large_heaps, 5u); + EXPECT_EQ(config.m_num_small_heaps, 6u); + EXPECT_EQ(config.m_num_large_heaps, 8u); } - From 827c9f034c51031b879cf22360cbb8fb5ba3d90c Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 24 Oct 2025 11:08:10 +0200 Subject: [PATCH 09/15] Update test_omp to use heap_config --- test/test_omp.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/test_omp.cpp b/test/test_omp.cpp index c4b38ca..439d1ad 100644 --- a/test/test_omp.cpp +++ b/test/test_omp.cpp @@ -73,8 +73,13 @@ register_memory(context&, void* ptr, std::size_t size) TEST(spread, neverfree) { using heap_t = hwmalloc::heap; + using heap_config_t = hwmalloc::heap_config; context c; - heap_t h(&c, 1024, true); + + heap_config_t hc = hwmalloc::get_default_heap_config(); + hc.m_never_free = true; + hc.m_num_reserve_segments = 1024; + heap_t h(&c, hc); n_registrations = 0; #pragma omp parallel @@ -144,8 +149,13 @@ TEST(spread, neverfree) TEST(close, neverfree) { using heap_t = hwmalloc::heap; + using heap_config_t = hwmalloc::heap_config; context c; - heap_t h(&c, 1024, true); + + heap_config_t hc = hwmalloc::get_default_heap_config(); + hc.m_never_free = true; + hc.m_num_reserve_segments = 1024; + heap_t h(&c, hc); n_registrations = 0; #pragma omp parallel From 29e9f3be4cc20a35c1e9f7c8142683eb024f7418 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 24 Oct 2025 11:21:09 +0200 Subject: [PATCH 10/15] Use EXPECT_EQ instead of EXPECT_TRUE in test_omp --- test/test_omp.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/test_omp.cpp b/test/test_omp.cpp index 439d1ad..3febceb 100644 --- a/test/test_omp.cpp +++ b/test/test_omp.cpp @@ -285,8 +285,7 @@ TEST(spread, free) #pragma omp master { printf("SPREAD, free :: n_registrations %d\n", n_registrations); - EXPECT_TRUE( - n_registrations == (thr_per_node * NITER * nnodes * (NBUFFERS - 1) + nnodes)); + EXPECT_EQ(n_registrations, (thr_per_node * NITER * nnodes * (NBUFFERS - 1) + nnodes)); } } } @@ -353,7 +352,7 @@ TEST(close, free) #pragma omp master { printf("CLOSE, free :: n_registrations %d\n", n_registrations); - EXPECT_TRUE(n_registrations == (nthr * NITER * (NBUFFERS - 1) + nused_nodes)); + EXPECT_EQ(n_registrations, (nthr * NITER * (NBUFFERS - 1) + nused_nodes)); } } } From 2078a51ef862ba22705f3c28f4d399d78980604b Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 24 Oct 2025 11:23:55 +0200 Subject: [PATCH 11/15] Keep fewer segments in test_omp *.free tests so that buffers are reallocated more frequently --- test/test_omp.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/test_omp.cpp b/test/test_omp.cpp index 3febceb..fb59fc3 100644 --- a/test/test_omp.cpp +++ b/test/test_omp.cpp @@ -222,8 +222,13 @@ TEST(close, neverfree) TEST(spread, free) { using heap_t = hwmalloc::heap; + using heap_config_t = hwmalloc::heap_config; context c; - heap_t h(&c); + + heap_config_t hc = hwmalloc::get_default_heap_config(); + hc.m_never_free = false; + hc.m_num_reserve_segments = 1; + heap_t h(&c, hc); n_registrations = 0; #pragma omp parallel @@ -293,8 +298,13 @@ TEST(spread, free) TEST(close, free) { using heap_t = hwmalloc::heap; + using heap_config_t = hwmalloc::heap_config; context c; - heap_t h(&c); + + heap_config_t hc = hwmalloc::get_default_heap_config(); + hc.m_never_free = false; + hc.m_num_reserve_segments = 1; + heap_t h(&c, hc); n_registrations = 0; #pragma omp parallel From 6ddd2f042b9d3ad46db732a725b4dc8693ccf499 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Mon, 3 Nov 2025 11:25:45 +0100 Subject: [PATCH 12/15] Reduce duplication in the environment variable parsing --- src/heap_config.cpp | 57 +++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/src/heap_config.cpp b/src/heap_config.cpp index 9bd3e5f..c865792 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -25,44 +25,35 @@ namespace hwmalloc { namespace detail { -static bool -get_env_bool(const char* name, bool default_value) noexcept +template +T +parse_value(const char* env_value) { - const char* env_value = std::getenv(name); - if (env_value) - { - try - { - return std::stoul(env_value) != 0; - } - catch (...) - { -#ifdef HWMALLOC_ENABLE_LOGGING - HWMALLOC_LOG("failed to parse boolean configuration option", name, "=", env_value, - "(expected 0 or 1), using default =", default_value); -#endif - return default_value; - } - } - - return default_value; + // This currently only supports the types needed within this file. If this + // should be used elsewhere this can be generalized to something that can be + // extended e.g. with template specializations instead a hardcoded list with + // if-constexpr. + if constexpr (std::is_same_v) { return std::stoul(env_value); } + else if constexpr (std::is_same_v) { return std::stoul(env_value) != 0; } + else { static_assert(sizeof(T) == 0, "Unsupported type for parse_value"); } } -static std::size_t -get_env_size_t(const char* name, std::size_t default_value) noexcept +template +bool +get_env(const char* name, T default_value) noexcept { const char* env_value = std::getenv(name); if (env_value) { try { - return std::stoul(env_value); + return parse_value(env_value); } catch (...) { #ifdef HWMALLOC_ENABLE_LOGGING - HWMALLOC_LOG("failed to parse configuration option", name, "=", env_value, - ", using default =", default_value); + HWMALLOC_LOG("failed to parse boolean configuration option", name, "=", env_value, + "(expected 0 or 1), using default =", default_value); #endif return default_value; } @@ -115,14 +106,14 @@ heap_config const& get_default_heap_config() { static heap_config config{ - detail::get_env_bool("HWMALLOC_NEVER_FREE", false), - detail::get_env_size_t("HWMALLOC_NUM_RESERVE_SEGMENTS", 16u), - detail::get_env_size_t("HWMALLOC_TINY_LIMIT", (1u << 7)), // 128B - detail::get_env_size_t("HWMALLOC_SMALL_LIMIT", (1u << 12)), // 4KiB - detail::get_env_size_t("HWMALLOC_LARGE_LIMIT", (1u << 21)), // 2MiB - detail::get_env_size_t("HWMALLOC_TINY_SEGMENT_SIZE", (1u << 16)), // 64KiB - detail::get_env_size_t("HWMALLOC_SMALL_SEGMENT_SIZE", (1u << 16)), // 64KiB - detail::get_env_size_t("HWMALLOC_LARGE_SEGMENT_SIZE", (1u << 21)) // 2MiB + detail::get_env("HWMALLOC_NEVER_FREE", false), + detail::get_env("HWMALLOC_NUM_RESERVE_SEGMENTS", 16u), + detail::get_env("HWMALLOC_TINY_LIMIT", (1u << 7)), // 128B + detail::get_env("HWMALLOC_SMALL_LIMIT", (1u << 12)), // 4KiB + detail::get_env("HWMALLOC_LARGE_LIMIT", (1u << 21)), // 2MiB + detail::get_env("HWMALLOC_TINY_SEGMENT_SIZE", (1u << 16)), // 64KiB + detail::get_env("HWMALLOC_SMALL_SEGMENT_SIZE", (1u << 16)), // 64KiB + detail::get_env("HWMALLOC_LARGE_SEGMENT_SIZE", (1u << 21)) // 2MiB }; From 32105b750c20cc390ea31d357785098398f352b6 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Mon, 3 Nov 2025 11:45:47 +0100 Subject: [PATCH 13/15] Move expected heap_config values to shared header for use in multiple tests --- test/CMakeLists.txt | 1 + test/heap_config_defaults.hpp | 34 +++ test/test_heap_config.cpp | 344 +++++++++++++++--------------- test/test_heap_config_invalid.cpp | 31 +-- 4 files changed, 218 insertions(+), 192 deletions(-) create mode 100644 test/heap_config_defaults.hpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 859b97c..84f7a2f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -21,6 +21,7 @@ function(reg_test t) target_link_libraries(${t} PRIVATE gtest_main) target_link_libraries(${t} PRIVATE hwmalloc) target_link_libraries(${t} PRIVATE Boost::boost) + target_include_directories(${t} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") add_test(NAME ${t} COMMAND $) endfunction() diff --git a/test/heap_config_defaults.hpp b/test/heap_config_defaults.hpp new file mode 100644 index 0000000..742ab36 --- /dev/null +++ b/test/heap_config_defaults.hpp @@ -0,0 +1,34 @@ +/* + * ghex-org + * + * Copyright (c) 2014-2025, ETH Zurich + * All rights reserved. + * + * Please, refer to the LICENSE file in the root directory. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +namespace hwmalloc::test +{ +// These should change accordingly if the defaults in heap_config.cpp change. +// They are defined here for convencience for tests. + +// These can be set directly. +inline constexpr bool never_free_default = false; +inline constexpr std::size_t num_reserve_segments_default = 16u; +inline constexpr std::size_t tiny_limit_default = 128u; +inline constexpr std::size_t small_limit_default = 4096u; +inline constexpr std::size_t large_limit_default = 2097152u; +inline constexpr std::size_t tiny_segment_size_default = 65536u; +inline constexpr std::size_t small_segment_size_default = 65536u; +inline constexpr std::size_t large_segment_size_default = 2097152u; + +// These are derived from above. +inline constexpr std::size_t bucket_shift_default = 7u; +inline constexpr std::size_t tiny_increment_shift_default = 3u; +inline constexpr std::size_t tiny_increment_default = 8u; +inline constexpr std::size_t num_tiny_heaps_default = 16u; +inline constexpr std::size_t num_small_heaps_default = 5u; +inline constexpr std::size_t num_large_heaps_default = 9u; +} // namespace hwmalloc::test diff --git a/test/test_heap_config.cpp b/test/test_heap_config.cpp index 851592c..e3c4944 100644 --- a/test/test_heap_config.cpp +++ b/test/test_heap_config.cpp @@ -13,227 +13,222 @@ #include -// These should change accordingly if the defaults in heap_config.cpp change. -// They are defined here for a little bit of convenience in the tests below. -inline constexpr bool never_free_default = false; -inline constexpr std::size_t num_reserve_segments_default = 16u; -inline constexpr std::size_t tiny_limit_default = 128u; -inline constexpr std::size_t small_limit_default = 4096u; -inline constexpr std::size_t large_limit_default = 2097152u; -inline constexpr std::size_t bucket_shift_default = 7u; -inline constexpr std::size_t tiny_segment_size_default = 65536u; -inline constexpr std::size_t small_segment_size_default = 65536u; -inline constexpr std::size_t large_segment_size_default = 2097152u; -inline constexpr std::size_t tiny_increment_shift_default = 3u; -inline constexpr std::size_t tiny_increment_default = 8u; -inline constexpr std::size_t num_tiny_heaps_default = 16u; -inline constexpr std::size_t num_small_heaps_default = 5u; -inline constexpr std::size_t num_large_heaps_default = 9u; +#include // Check that the default configuration values are as expected. TEST(heap_config, defaults) { hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); - EXPECT_EQ(config.m_never_free, never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, small_limit_default); - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); - EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, hwmalloc::test::num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, hwmalloc::test::num_large_heaps_default); } // We try changing one parameter a time compared to the defaults and check that // the derived values change accordingly. TEST(heap_config, never_free) { - hwmalloc::heap_config config{true, num_reserve_segments_default, tiny_limit_default, - small_limit_default, large_limit_default, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{true, hwmalloc::test::num_reserve_segments_default, + hwmalloc::test::tiny_limit_default, hwmalloc::test::small_limit_default, + hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; EXPECT_EQ(config.m_never_free, true); // This changes to the literal value we set - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, small_limit_default); - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); - EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, hwmalloc::test::num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, hwmalloc::test::num_large_heaps_default); } TEST(heap_config, num_reserve_segments) { - hwmalloc::heap_config config{never_free_default, 7, tiny_limit_default, small_limit_default, - large_limit_default, tiny_segment_size_default, small_segment_size_default, - large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, 7, + hwmalloc::test::tiny_limit_default, hwmalloc::test::small_limit_default, + hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, never_free_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); EXPECT_EQ(config.m_num_reserve_segments, 7u); // This changes to the literal value we set - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, small_limit_default); - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); - EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, hwmalloc::test::num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, hwmalloc::test::num_large_heaps_default); } TEST(heap_config, tiny_limit) { - hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, 256u, - small_limit_default, large_limit_default, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, 256u, hwmalloc::test::small_limit_default, + hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, 256u); // This changes to the literal value we set - EXPECT_EQ(config.m_small_limit, small_limit_default); - EXPECT_EQ(config.m_large_limit, large_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); EXPECT_EQ(config.m_bucket_shift, 8u); // This changes based on tiny_limit - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, 32u); // This number doubles... EXPECT_EQ(config.m_num_small_heaps, 4u); // While this is decreased by one - EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, hwmalloc::test::num_large_heaps_default); } TEST(heap_config, tiny_segment) { - hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, - tiny_limit_default, small_limit_default, large_limit_default, 8192u, - small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, + hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, 8192u, + hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, small_limit_default); - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); EXPECT_EQ(config.m_tiny_segment_size, 8192u); // This changes to the literal value we set - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); - EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, hwmalloc::test::num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, hwmalloc::test::num_large_heaps_default); } TEST(heap_config, small_limit) { - hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, - tiny_limit_default, 8192u, large_limit_default, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, 8192u, + hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); EXPECT_EQ(config.m_small_limit, 8192u); // This changes to the literal value we set - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); EXPECT_EQ(config.m_num_small_heaps, 6u); // This is log2(8192)-log2(128) = 6... EXPECT_EQ(config.m_num_large_heaps, 8u); // While this is decreased accordingly } TEST(heap_config, small_segment) { - hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, - tiny_limit_default, small_limit_default, large_limit_default, tiny_segment_size_default, - 16384u, large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, + hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, + hwmalloc::test::tiny_segment_size_default, 16384u, + hwmalloc::test::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, small_limit_default); - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); EXPECT_EQ(config.m_small_segment_size, 16384u); // This changes to the literal value we set - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); - EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, hwmalloc::test::num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, hwmalloc::test::num_large_heaps_default); } TEST(heap_config, large_limit) { - hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, - tiny_limit_default, small_limit_default, 32768u, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, + hwmalloc::test::small_limit_default, 32768u, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, small_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); EXPECT_EQ(config.m_large_limit, 32768u); // This changes to the literal value we set - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, large_segment_size_default); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, hwmalloc::test::num_small_heaps_default); EXPECT_EQ(config.m_num_large_heaps, 3u); // This is decreased accordingly } TEST(heap_config, large_segment) { - hwmalloc::heap_config config{never_free_default, num_reserve_segments_default, - tiny_limit_default, small_limit_default, large_limit_default, tiny_segment_size_default, - small_segment_size_default, 4194304u}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, + hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, + hwmalloc::test::tiny_segment_size_default, hwmalloc::test::small_segment_size_default, + 4194304u}; - EXPECT_EQ(config.m_never_free, never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); - EXPECT_EQ(config.m_small_limit, small_limit_default); - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); EXPECT_EQ(config.m_large_segment_size, 4194304u); // This changes to the literal value we set - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); - EXPECT_EQ(config.m_num_small_heaps, num_small_heaps_default); - EXPECT_EQ(config.m_num_large_heaps, num_large_heaps_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); + EXPECT_EQ(config.m_num_small_heaps, hwmalloc::test::num_small_heaps_default); + EXPECT_EQ(config.m_num_large_heaps, hwmalloc::test::num_large_heaps_default); } // Check that setting non-power-of-two values results in rounding to power of two TEST(heap_config, power_of_two) { - hwmalloc::heap_config config{never_free_default, 17u, 200u, 500u, 20000u, 1000u, 3000u, - 100000u}; + hwmalloc::heap_config config{hwmalloc::test::never_free_default, 17u, 200u, 500u, 20000u, 1000u, + 3000u, 100000u}; EXPECT_EQ(config.m_num_reserve_segments, 17u); // Not rounded up EXPECT_EQ(config.m_tiny_limit, 256u); // Rounded up from 200 @@ -247,40 +242,51 @@ TEST(heap_config, power_of_two) // Check that setting invalid values results in exceptions TEST(heap_config, validate_tiny_small_limit) { - EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, 2048u, - 1024u, large_limit_default, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, 2048u, 1024u, + hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, + hwmalloc::test::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_small_large_limit) { - EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, - tiny_limit_default, 131072u, 65536u, tiny_segment_size_default, - small_segment_size_default, large_segment_size_default}), + EXPECT_THROW( + (hwmalloc::heap_config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, + 131072u, 65536u, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, + hwmalloc::test::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_tiny_limit_segment_size) { - EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, 2048u, - small_limit_default, large_limit_default, 1024u, small_segment_size_default, - large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, 2048u, + hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, + 1024u, hwmalloc::test::small_segment_size_default, + hwmalloc::test::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_small_limit_segment_size) { - EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, - tiny_limit_default, 131072u, large_limit_default, tiny_segment_size_default, - 65536u, large_segment_size_default}), + EXPECT_THROW( + (hwmalloc::heap_config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, + 131072u, hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, + 65536u, hwmalloc::test::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_large_limit_segment_size) { - EXPECT_THROW((hwmalloc::heap_config{never_free_default, num_reserve_segments_default, - tiny_limit_default, small_limit_default, 262144u, tiny_segment_size_default, - small_segment_size_default, 131072u}), + EXPECT_THROW( + (hwmalloc::heap_config{hwmalloc::test::never_free_default, + hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, + hwmalloc::test::small_limit_default, 262144u, hwmalloc::test::tiny_segment_size_default, + hwmalloc::test::small_segment_size_default, 131072u}), std::runtime_error); } diff --git a/test/test_heap_config_invalid.cpp b/test/test_heap_config_invalid.cpp index dd30e09..efe4cef 100644 --- a/test/test_heap_config_invalid.cpp +++ b/test/test_heap_config_invalid.cpp @@ -13,22 +13,7 @@ #include -// These should change accordingly if the defaults in heap_config.cpp change. -// They are defined here for a little bit of convenience in the tests below. -inline constexpr bool never_free_default = false; -inline constexpr std::size_t num_reserve_segments_default = 16u; -inline constexpr std::size_t tiny_limit_default = 128u; -inline constexpr std::size_t small_limit_default = 4096u; -inline constexpr std::size_t large_limit_default = 2097152u; -inline constexpr std::size_t bucket_shift_default = 7u; -inline constexpr std::size_t tiny_segment_size_default = 65536u; -inline constexpr std::size_t small_segment_size_default = 65536u; -inline constexpr std::size_t large_segment_size_default = 2097152u; -inline constexpr std::size_t tiny_increment_shift_default = 3u; -inline constexpr std::size_t tiny_increment_default = 8u; -inline constexpr std::size_t num_tiny_heaps_default = 16u; -inline constexpr std::size_t num_small_heaps_default = 5u; -inline constexpr std::size_t num_large_heaps_default = 9u; +#include // Test that config falls back to defaults if environment variables are given // non-numeric values. @@ -49,16 +34,16 @@ TEST(config, defaults) EXPECT_EQ(config.m_never_free, false); EXPECT_EQ(config.m_num_reserve_segments, 9u); - EXPECT_EQ(config.m_tiny_limit, tiny_limit_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); EXPECT_EQ(config.m_small_limit, 8192); - EXPECT_EQ(config.m_large_limit, large_limit_default); - EXPECT_EQ(config.m_bucket_shift, bucket_shift_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); EXPECT_EQ(config.m_tiny_segment_size, 16384u); - EXPECT_EQ(config.m_small_segment_size, small_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); EXPECT_EQ(config.m_large_segment_size, 4194304u); - EXPECT_EQ(config.m_tiny_increment_shift, tiny_increment_shift_default); - EXPECT_EQ(config.m_tiny_increment, tiny_increment_default); - EXPECT_EQ(config.m_num_tiny_heaps, num_tiny_heaps_default); + EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); + EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); + EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); EXPECT_EQ(config.m_num_small_heaps, 6u); EXPECT_EQ(config.m_num_large_heaps, 8u); } From f74ae0a55c358069fefb59cfb7dd19a5eb0d7e9f Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Mon, 3 Nov 2025 14:42:48 +0100 Subject: [PATCH 14/15] Move heap_config defaults (input parameters) into heap_config.hpp --- include/hwmalloc/heap_config.hpp | 9 + src/heap_config.cpp | 20 ++- test/heap_config_defaults.hpp | 17 +- test/test_heap_config.cpp | 270 ++++++++++++++++-------------- test/test_heap_config_invalid.cpp | 6 +- 5 files changed, 171 insertions(+), 151 deletions(-) diff --git a/include/hwmalloc/heap_config.hpp b/include/hwmalloc/heap_config.hpp index 886eb31..39d71ef 100644 --- a/include/hwmalloc/heap_config.hpp +++ b/include/hwmalloc/heap_config.hpp @@ -30,6 +30,15 @@ round_to_pow_of_2(std::size_t n) noexcept struct heap_config { + static constexpr bool never_free_default = false; + static constexpr std::size_t num_reserve_segments_default = 16u; + static constexpr std::size_t tiny_limit_default = 128u; // 128B + static constexpr std::size_t small_limit_default = 4096u; // 4KiB + static constexpr std::size_t large_limit_default = 2097152u; // 2MiB + static constexpr std::size_t tiny_segment_size_default = 65536u; // 64KiB + static constexpr std::size_t small_segment_size_default = 65536u; // 64KiB + static constexpr std::size_t large_segment_size_default = 2097152u; // 2MiB + bool m_never_free; std::size_t m_num_reserve_segments; std::size_t m_tiny_limit; diff --git a/src/heap_config.cpp b/src/heap_config.cpp index c865792..136a212 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -106,14 +106,18 @@ heap_config const& get_default_heap_config() { static heap_config config{ - detail::get_env("HWMALLOC_NEVER_FREE", false), - detail::get_env("HWMALLOC_NUM_RESERVE_SEGMENTS", 16u), - detail::get_env("HWMALLOC_TINY_LIMIT", (1u << 7)), // 128B - detail::get_env("HWMALLOC_SMALL_LIMIT", (1u << 12)), // 4KiB - detail::get_env("HWMALLOC_LARGE_LIMIT", (1u << 21)), // 2MiB - detail::get_env("HWMALLOC_TINY_SEGMENT_SIZE", (1u << 16)), // 64KiB - detail::get_env("HWMALLOC_SMALL_SEGMENT_SIZE", (1u << 16)), // 64KiB - detail::get_env("HWMALLOC_LARGE_SEGMENT_SIZE", (1u << 21)) // 2MiB + detail::get_env("HWMALLOC_NEVER_FREE", heap_config::never_free_default), + detail::get_env("HWMALLOC_NUM_RESERVE_SEGMENTS", + heap_config::num_reserve_segments_default), + detail::get_env("HWMALLOC_TINY_LIMIT", heap_config::tiny_limit_default), + detail::get_env("HWMALLOC_SMALL_LIMIT", heap_config::small_limit_default), + detail::get_env("HWMALLOC_LARGE_LIMIT", heap_config::large_limit_default), + detail::get_env("HWMALLOC_TINY_SEGMENT_SIZE", + heap_config::tiny_segment_size_default), + detail::get_env("HWMALLOC_SMALL_SEGMENT_SIZE", + heap_config::small_segment_size_default), + detail::get_env("HWMALLOC_LARGE_SEGMENT_SIZE", + heap_config::large_segment_size_default) }; diff --git a/test/heap_config_defaults.hpp b/test/heap_config_defaults.hpp index 742ab36..048bfbd 100644 --- a/test/heap_config_defaults.hpp +++ b/test/heap_config_defaults.hpp @@ -11,20 +11,9 @@ namespace hwmalloc::test { -// These should change accordingly if the defaults in heap_config.cpp change. -// They are defined here for convencience for tests. - -// These can be set directly. -inline constexpr bool never_free_default = false; -inline constexpr std::size_t num_reserve_segments_default = 16u; -inline constexpr std::size_t tiny_limit_default = 128u; -inline constexpr std::size_t small_limit_default = 4096u; -inline constexpr std::size_t large_limit_default = 2097152u; -inline constexpr std::size_t tiny_segment_size_default = 65536u; -inline constexpr std::size_t small_segment_size_default = 65536u; -inline constexpr std::size_t large_segment_size_default = 2097152u; - -// These are derived from above. +// These should change accordingly if the defaults in heap_config.hpp change. +// They are defined here for convencience for tests. They are derived from +// heap_config defaults. inline constexpr std::size_t bucket_shift_default = 7u; inline constexpr std::size_t tiny_increment_shift_default = 3u; inline constexpr std::size_t tiny_increment_default = 8u; diff --git a/test/test_heap_config.cpp b/test/test_heap_config.cpp index e3c4944..030b755 100644 --- a/test/test_heap_config.cpp +++ b/test/test_heap_config.cpp @@ -20,15 +20,15 @@ TEST(heap_config, defaults) { hwmalloc::heap_config config = hwmalloc::get_default_heap_config(); - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); @@ -40,20 +40,22 @@ TEST(heap_config, defaults) // the derived values change accordingly. TEST(heap_config, never_free) { - hwmalloc::heap_config config{true, hwmalloc::test::num_reserve_segments_default, - hwmalloc::test::tiny_limit_default, hwmalloc::test::small_limit_default, - hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; + hwmalloc::heap_config config{true, hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, hwmalloc::heap_config::small_limit_default, + hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}; EXPECT_EQ(config.m_never_free, true); // This changes to the literal value we set - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); @@ -63,20 +65,22 @@ TEST(heap_config, never_free) TEST(heap_config, num_reserve_segments) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, 7, - hwmalloc::test::tiny_limit_default, hwmalloc::test::small_limit_default, - hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, 7, + hwmalloc::heap_config::tiny_limit_default, hwmalloc::heap_config::small_limit_default, + hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); EXPECT_EQ(config.m_num_reserve_segments, 7u); // This changes to the literal value we set - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); @@ -86,20 +90,22 @@ TEST(heap_config, num_reserve_segments) TEST(heap_config, tiny_limit) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, 256u, hwmalloc::test::small_limit_default, - hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, 256u, + hwmalloc::heap_config::small_limit_default, hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); EXPECT_EQ(config.m_tiny_limit, 256u); // This changes to the literal value we set - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, 8u); // This changes based on tiny_limit - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, 32u); // This number doubles... @@ -109,20 +115,22 @@ TEST(heap_config, tiny_limit) TEST(heap_config, tiny_segment) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, - hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, 8192u, - hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, hwmalloc::heap_config::small_limit_default, + hwmalloc::heap_config::large_limit_default, 8192u, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); EXPECT_EQ(config.m_tiny_segment_size, 8192u); // This changes to the literal value we set - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); @@ -132,20 +140,23 @@ TEST(heap_config, tiny_segment) TEST(heap_config, small_limit) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, 8192u, - hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, 8192u, + hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); EXPECT_EQ(config.m_small_limit, 8192u); // This changes to the literal value we set - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); @@ -155,21 +166,22 @@ TEST(heap_config, small_limit) TEST(heap_config, small_segment) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, - hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, - hwmalloc::test::tiny_segment_size_default, 16384u, - hwmalloc::test::large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, hwmalloc::heap_config::small_limit_default, + hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, 16384u, + hwmalloc::heap_config::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); EXPECT_EQ(config.m_small_segment_size, 16384u); // This changes to the literal value we set - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); @@ -179,20 +191,22 @@ TEST(heap_config, small_segment) TEST(heap_config, large_limit) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, - hwmalloc::test::small_limit_default, 32768u, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, hwmalloc::test::large_segment_size_default}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, hwmalloc::heap_config::small_limit_default, 32768u, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}; - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); EXPECT_EQ(config.m_large_limit, 32768u); // This changes to the literal value we set EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); - EXPECT_EQ(config.m_large_segment_size, hwmalloc::test::large_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); + EXPECT_EQ(config.m_large_segment_size, hwmalloc::heap_config::large_segment_size_default); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); EXPECT_EQ(config.m_num_tiny_heaps, hwmalloc::test::num_tiny_heaps_default); @@ -202,20 +216,21 @@ TEST(heap_config, large_limit) TEST(heap_config, large_segment) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, - hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, - hwmalloc::test::tiny_segment_size_default, hwmalloc::test::small_segment_size_default, - 4194304u}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, hwmalloc::heap_config::small_limit_default, + hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, 4194304u}; - EXPECT_EQ(config.m_never_free, hwmalloc::test::never_free_default); - EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::test::num_reserve_segments_default); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); - EXPECT_EQ(config.m_small_limit, hwmalloc::test::small_limit_default); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_never_free, hwmalloc::heap_config::never_free_default); + EXPECT_EQ(config.m_num_reserve_segments, hwmalloc::heap_config::num_reserve_segments_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); + EXPECT_EQ(config.m_small_limit, hwmalloc::heap_config::small_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); - EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::test::tiny_segment_size_default); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_tiny_segment_size, hwmalloc::heap_config::tiny_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); EXPECT_EQ(config.m_large_segment_size, 4194304u); // This changes to the literal value we set EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); @@ -227,8 +242,8 @@ TEST(heap_config, large_segment) // Check that setting non-power-of-two values results in rounding to power of two TEST(heap_config, power_of_two) { - hwmalloc::heap_config config{hwmalloc::test::never_free_default, 17u, 200u, 500u, 20000u, 1000u, - 3000u, 100000u}; + hwmalloc::heap_config config{hwmalloc::heap_config::never_free_default, 17u, 200u, 500u, 20000u, + 1000u, 3000u, 100000u}; EXPECT_EQ(config.m_num_reserve_segments, 17u); // Not rounded up EXPECT_EQ(config.m_tiny_limit, 256u); // Rounded up from 200 @@ -242,51 +257,54 @@ TEST(heap_config, power_of_two) // Check that setting invalid values results in exceptions TEST(heap_config, validate_tiny_small_limit) { - EXPECT_THROW((hwmalloc::heap_config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, 2048u, 1024u, - hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, - hwmalloc::test::large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, 2048u, 1024u, + hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_small_large_limit) { - EXPECT_THROW( - (hwmalloc::heap_config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, - 131072u, 65536u, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, - hwmalloc::test::large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, 131072u, 65536u, + hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_tiny_limit_segment_size) { - EXPECT_THROW((hwmalloc::heap_config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, 2048u, - hwmalloc::test::small_limit_default, hwmalloc::test::large_limit_default, - 1024u, hwmalloc::test::small_segment_size_default, - hwmalloc::test::large_segment_size_default}), + EXPECT_THROW( + (hwmalloc::heap_config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, 2048u, + hwmalloc::heap_config::small_limit_default, hwmalloc::heap_config::large_limit_default, 1024u, + hwmalloc::heap_config::small_segment_size_default, + hwmalloc::heap_config::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_small_limit_segment_size) { - EXPECT_THROW( - (hwmalloc::heap_config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, - 131072u, hwmalloc::test::large_limit_default, hwmalloc::test::tiny_segment_size_default, - 65536u, hwmalloc::test::large_segment_size_default}), + EXPECT_THROW((hwmalloc::heap_config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, 131072u, + hwmalloc::heap_config::large_limit_default, + hwmalloc::heap_config::tiny_segment_size_default, 65536u, + hwmalloc::heap_config::large_segment_size_default}), std::runtime_error); } TEST(heap_config, validate_large_limit_segment_size) { - EXPECT_THROW( - (hwmalloc::heap_config{hwmalloc::test::never_free_default, - hwmalloc::test::num_reserve_segments_default, hwmalloc::test::tiny_limit_default, - hwmalloc::test::small_limit_default, 262144u, hwmalloc::test::tiny_segment_size_default, - hwmalloc::test::small_segment_size_default, 131072u}), + EXPECT_THROW((hwmalloc::heap_config{hwmalloc::heap_config::never_free_default, + hwmalloc::heap_config::num_reserve_segments_default, + hwmalloc::heap_config::tiny_limit_default, hwmalloc::heap_config::small_limit_default, + 262144u, hwmalloc::heap_config::tiny_segment_size_default, + hwmalloc::heap_config::small_segment_size_default, 131072u}), std::runtime_error); } diff --git a/test/test_heap_config_invalid.cpp b/test/test_heap_config_invalid.cpp index efe4cef..6a739f3 100644 --- a/test/test_heap_config_invalid.cpp +++ b/test/test_heap_config_invalid.cpp @@ -34,12 +34,12 @@ TEST(config, defaults) EXPECT_EQ(config.m_never_free, false); EXPECT_EQ(config.m_num_reserve_segments, 9u); - EXPECT_EQ(config.m_tiny_limit, hwmalloc::test::tiny_limit_default); + EXPECT_EQ(config.m_tiny_limit, hwmalloc::heap_config::tiny_limit_default); EXPECT_EQ(config.m_small_limit, 8192); - EXPECT_EQ(config.m_large_limit, hwmalloc::test::large_limit_default); + EXPECT_EQ(config.m_large_limit, hwmalloc::heap_config::large_limit_default); EXPECT_EQ(config.m_bucket_shift, hwmalloc::test::bucket_shift_default); EXPECT_EQ(config.m_tiny_segment_size, 16384u); - EXPECT_EQ(config.m_small_segment_size, hwmalloc::test::small_segment_size_default); + EXPECT_EQ(config.m_small_segment_size, hwmalloc::heap_config::small_segment_size_default); EXPECT_EQ(config.m_large_segment_size, 4194304u); EXPECT_EQ(config.m_tiny_increment_shift, hwmalloc::test::tiny_increment_shift_default); EXPECT_EQ(config.m_tiny_increment, hwmalloc::test::tiny_increment_default); From 83b17119c59f44738b424ecaca01eabfcadb47fc Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Mon, 3 Nov 2025 15:38:18 +0100 Subject: [PATCH 15/15] Fix return type get_env --- src/heap_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/heap_config.cpp b/src/heap_config.cpp index 136a212..ebd89ad 100644 --- a/src/heap_config.cpp +++ b/src/heap_config.cpp @@ -39,7 +39,7 @@ parse_value(const char* env_value) } template -bool +T get_env(const char* name, T default_value) noexcept { const char* env_value = std::getenv(name);