From 29a3c3a74f96497fefb2027fcf6d89656a827603 Mon Sep 17 00:00:00 2001 From: Yuya Asano <64895419+sukeya@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:17:49 +0900 Subject: [PATCH] Optimize btree value shifts for trivially copyable types --- benchmark/btree_bench.cpp | 9 ++++++++ include/platanus/internal/btree_base_node.hpp | 21 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/benchmark/btree_bench.cpp b/benchmark/btree_bench.cpp index d362d74..a81d19b 100644 --- a/benchmark/btree_bench.cpp +++ b/benchmark/btree_bench.cpp @@ -296,9 +296,18 @@ using STLMultiMap = std::multimap; REGISTER_BENCHMARK_FUNCTIONS(container, std::int64_t); \ REGISTER_BENCHMARK_FUNCTIONS(container, std::string); +#define REGISTER_TRIVIAL_SHIFT_BENCHMARKS(container, type) \ + STL_AND_BTREE_BENCHMARK(container, type, Insert); \ + STL_AND_BTREE_BENCHMARK(container, type, Delete); + REGISTER_BENCHMARK_TYPES(Set); REGISTER_BENCHMARK_TYPES(MultiSet); REGISTER_BENCHMARK_TYPES(Map); REGISTER_BENCHMARK_TYPES(MultiMap); +REGISTER_TRIVIAL_SHIFT_BENCHMARKS(Set, int); +REGISTER_TRIVIAL_SHIFT_BENCHMARKS(Set, std::pair); +REGISTER_TRIVIAL_SHIFT_BENCHMARKS(Map, int); +REGISTER_TRIVIAL_SHIFT_BENCHMARKS(Map, std::pair); + BENCHMARK_MAIN(); diff --git a/include/platanus/internal/btree_base_node.hpp b/include/platanus/internal/btree_base_node.hpp index 179f790..223a250 100644 --- a/include/platanus/internal/btree_base_node.hpp +++ b/include/platanus/internal/btree_base_node.hpp @@ -32,7 +32,10 @@ #include #include #include +#include #include +#include +#include #include "btree_node_fwd.hpp" #include "btree_util.hpp" @@ -287,7 +290,14 @@ class btree_base_node { assert(last + shift <= max_values_count()); auto begin = std::next(begin_values(), first); auto end = std::next(begin_values(), last); - std::move_backward(begin, end, std::next(end, shift)); + if constexpr (std::is_trivially_copyable_v) { + auto* src = std::to_address(begin); + // std::memmove handles overlapping ranges, so right shifts (destination starts inside source) + // remain well-defined for trivially copyable values. + std::memmove(src + shift, src, static_cast(last - first) * sizeof(*src)); + } else { + std::move_backward(begin, end, std::next(end, shift)); + } } // Shift values from first to last by shift toward left. @@ -299,7 +309,14 @@ class btree_base_node { assert(0 <= first - shift); auto begin = std::next(begin_values(), first); auto end = std::next(begin_values(), last); - std::move(begin, end, std::prev(begin, shift)); + if constexpr (std::is_trivially_copyable_v) { + auto* src = std::to_address(begin); + // std::memmove handles overlapping ranges, so left shifts (destination ends inside source) + // remain well-defined for trivially copyable values. + std::memmove(src - shift, src, static_cast(last - first) * sizeof(*src)); + } else { + std::move(begin, end, std::prev(begin, shift)); + } } private: