From b452924c56fd8ce0bc746a0268832a99ca5e39de Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Sun, 22 Feb 2026 10:16:38 +0000 Subject: [PATCH 1/3] Benchmark for repeated large deallocations. --- src/test/perf/large_alloc/large_alloc.cc | 83 ++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/test/perf/large_alloc/large_alloc.cc diff --git a/src/test/perf/large_alloc/large_alloc.cc b/src/test/perf/large_alloc/large_alloc.cc new file mode 100644 index 000000000..2532b41e3 --- /dev/null +++ b/src/test/perf/large_alloc/large_alloc.cc @@ -0,0 +1,83 @@ +#include +#include +#include + +using namespace snmalloc; + +static constexpr size_t ALLOC_SIZE = 800 * 1024; // 800 KB +static constexpr size_t ITERATIONS = 100000; + +void test_alloc_dealloc_cycle() +{ + { + MeasureTime m; + m << "Alloc/dealloc 800KB x " << ITERATIONS; + + for (size_t i = 0; i < ITERATIONS; i++) + { + void* p = snmalloc::alloc(ALLOC_SIZE); + SNMALLOC_CHECK(p != nullptr); + snmalloc::dealloc(p); + } + } + + snmalloc::debug_check_empty(); +} + +void test_batch_alloc_then_dealloc() +{ + static constexpr size_t BATCH = 128; + + void* ptrs[BATCH]; + + MeasureTime m; + m << "Batch alloc then dealloc 800KB x " << BATCH; + for (size_t j = 0; j < ITERATIONS / BATCH; j++) + { + for (size_t i = 0; i < BATCH; i++) + { + ptrs[i] = snmalloc::alloc(ALLOC_SIZE); + SNMALLOC_CHECK(ptrs[i] != nullptr); + } + + for (size_t i = 0; i < BATCH; i++) + { + snmalloc::dealloc(ptrs[i]); + } + } + + snmalloc::debug_check_empty(); +} + +void test_alloc_dealloc_with_touch() +{ + { + MeasureTime m; + m << "Alloc/touch/dealloc 800KB x " << ITERATIONS; + + for (size_t i = 0; i < ITERATIONS; i++) + { + char* p = static_cast(snmalloc::alloc(ALLOC_SIZE)); + SNMALLOC_CHECK(p != nullptr); + // Touch every 4KiB and last bytes to ensure pages are faulted in + for (size_t offset = 0; offset < ALLOC_SIZE; offset += 4096) + { + p[offset] = 1; + } + snmalloc::dealloc(p); + } + } + + snmalloc::debug_check_empty(); +} + +int main(int, char**) +{ + setup(); + + test_alloc_dealloc_cycle(); + test_batch_alloc_then_dealloc(); + test_alloc_dealloc_with_touch(); + + return 0; +} From 5d8b9f170e1054116272b2909e246902fef9d88a Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Sun, 22 Feb 2026 15:57:43 +0000 Subject: [PATCH 2/3] Remove unnecessary init from fast path --- src/snmalloc/ds_core/redblacktree.h | 11 +++++++++-- src/snmalloc/mem/metadata.h | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/snmalloc/ds_core/redblacktree.h b/src/snmalloc/ds_core/redblacktree.h index ec212fa23..aaffe95cf 100644 --- a/src/snmalloc/ds_core/redblacktree.h +++ b/src/snmalloc/ds_core/redblacktree.h @@ -101,7 +101,7 @@ namespace snmalloc H ptr; public: - ChildRef() : ptr(nullptr) {} + constexpr ChildRef() = default; ChildRef(H p) : ptr(p) {} @@ -232,7 +232,14 @@ namespace snmalloc struct RBStep { ChildRef node; - bool dir = false; + bool dir; + + // Default constructor needed for Array. + constexpr RBStep() = default; + + // Remove copy constructors to avoid accidentally copying and mutating the path. + RBStep(const RBStep& other) = delete; + RBStep& operator=(const RBStep& other) = delete; /** * Update the step to point to a new node and direction. diff --git a/src/snmalloc/mem/metadata.h b/src/snmalloc/mem/metadata.h index d034f5f3b..0284e8a5d 100644 --- a/src/snmalloc/mem/metadata.h +++ b/src/snmalloc/mem/metadata.h @@ -282,6 +282,11 @@ namespace snmalloc uintptr_t* val; public: + /** + * Uninitialised constructor. + */ + BackendStateWordRef() = default; + /** * Constructor, wraps a `uintptr_t`. Note that this may be used outside * of the meta entry by code wishing to provide uniform storage to things From 29034a2969abd995390a6171b309561db35ca652 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Thu, 26 Feb 2026 12:02:58 +0000 Subject: [PATCH 3/3] Clangformat --- src/snmalloc/ds_core/redblacktree.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/snmalloc/ds_core/redblacktree.h b/src/snmalloc/ds_core/redblacktree.h index aaffe95cf..e6ce73c24 100644 --- a/src/snmalloc/ds_core/redblacktree.h +++ b/src/snmalloc/ds_core/redblacktree.h @@ -237,7 +237,8 @@ namespace snmalloc // Default constructor needed for Array. constexpr RBStep() = default; - // Remove copy constructors to avoid accidentally copying and mutating the path. + // Remove copy constructors to avoid accidentally copying and mutating the + // path. RBStep(const RBStep& other) = delete; RBStep& operator=(const RBStep& other) = delete;