diff --git a/include/psi/vm/containers/b+tree.hpp b/include/psi/vm/containers/b+tree.hpp index 69632ea..8c3bd7d 100644 --- a/include/psi/vm/containers/b+tree.hpp +++ b/include/psi/vm/containers/b+tree.hpp @@ -85,8 +85,27 @@ class bptree_base bool has_attached_storage() const noexcept { return nodes_.has_attached_storage(); } - storage_result map_file ( auto const file, flags::named_object_construction_policy const policy ) noexcept { return init_header( nodes_.map_file ( file, policy ) ); } - storage_result map_memory( std::uint32_t const initial_capacity_as_number_of_nodes = 0 ) noexcept { return init_header( nodes_.map_memory( initial_capacity_as_number_of_nodes ) ); } + storage_result map_file( auto const file, flags::named_object_construction_policy const policy ) noexcept + { + storage_result success{ nodes_.map_file( file, policy ) }; + if ( std::move( success ) && nodes_.empty() ) + hdr() = {}; + return success; + } + storage_result map_memory( std::uint32_t const initial_capacity_as_number_of_nodes = 0 ) noexcept + { + storage_result success{ nodes_.map_memory( initial_capacity_as_number_of_nodes ) }; + //if ( std::move( success ) ) + { + hdr() = {}; + BOOST_ASSERT( !hdr().free_list_ ); + BOOST_ASSERT( !hdr().free_node_count_ ); + if ( initial_capacity_as_number_of_nodes ) { + assign_nodes_to_free_pool( 0 ); + } + } + return success; + } protected: static constexpr auto node_size{ page_size }; @@ -150,7 +169,7 @@ class bptree_base class base_iterator; class base_random_access_iterator; - struct header + struct header // or persisted data members { node_slot root_; node_slot first_leaf_; @@ -306,7 +325,7 @@ class bptree_base private: auto header_data() noexcept { return detail::header_data
( nodes_.user_header_data() ); } - storage_result init_header( storage_result ) noexcept; + void assign_nodes_to_free_pool( node_slot::value_type starting_node ) noexcept; protected: node_pool nodes_; @@ -739,8 +758,8 @@ class bptree_base_wkey : public bptree_base leaf_slot = leaf.right; else { - hdr.free_list_ = leaf.right; node( leaf.right ).left = {}; + hdr.free_list_ = leaf.right; leaf.right = {}; return std::make_pair( begin, iter_pos{ leaf_slot, size_to_copy } ); } @@ -1421,6 +1440,7 @@ class bp_tree [[ using gnu: pure, hot, noinline, sysv_abi ]] find_pos find( Key const keys[], node_size_type const num_vals, key_const_arg value ) const noexcept { + // TODO branchless binary search, Alexandrescu's ideas, https://orlp.net/blog/bitwise-binary-search ... BOOST_ASSUME( num_vals > 0 ); auto const & __restrict comp{ this->comp() }; node_size_type pos_idx; diff --git a/include/psi/vm/vector.hpp b/include/psi/vm/vector.hpp index 8efaa5c..2c7953f 100644 --- a/include/psi/vm/vector.hpp +++ b/include/psi/vm/vector.hpp @@ -1084,7 +1084,7 @@ class vector /////////////////////////////////////////////////////////////////////////// auto map_file ( auto const file, flags::named_object_construction_policy const policy ) noexcept { BOOST_ASSERT( !has_attached_storage() ); return storage_.map_file ( file, policy ); } - auto map_memory( size_type const initial_capacity = 0 ) noexcept { BOOST_ASSERT( !has_attached_storage() ); return storage_.map_memory( to_byte_sz( initial_capacity ) ); } + auto map_memory( size_type const initial_size = 0 ) noexcept { BOOST_ASSERT( !has_attached_storage() ); return storage_.map_memory( to_byte_sz( initial_size ) ); } bool has_attached_storage() const noexcept { return static_cast( storage_ ); } diff --git a/src/containers/b+tree.cpp b/src/containers/b+tree.cpp index b62c2b3..1eb3028 100644 --- a/src/containers/b+tree.cpp +++ b/src/containers/b+tree.cpp @@ -40,24 +40,46 @@ bptree_base::user_header_data() noexcept { return header_data().second; } bptree_base::header & bptree_base::hdr() noexcept { return *header_data().first; } -bptree_base::storage_result -bptree_base::init_header( storage_result success ) noexcept -{ - if ( std::move( success ) && nodes_.empty() ) - hdr() = {}; - return success; -} - void bptree_base::reserve( node_slot::value_type additional_nodes ) { auto const preallocated_count{ hdr().free_node_count_ }; additional_nodes -= std::min( preallocated_count, additional_nodes ); + if ( !preallocated_count ) + { + BOOST_ASSUME( !preallocated_count ); + BOOST_ASSUME( !hdr().free_list_ ); + BOOST_ASSUME( !hdr().free_node_count_ ); + } auto const current_size{ nodes_.size() }; + if ( !preallocated_count ) + { + BOOST_ASSUME( !preallocated_count ); + BOOST_ASSUME( !hdr().free_list_ ); + BOOST_ASSUME( !hdr().free_node_count_ ); + } nodes_.grow_by( additional_nodes, value_init ); + if ( !preallocated_count ) + { + BOOST_ASSUME( !preallocated_count ); + BOOST_ASSUME( !hdr().free_list_ ); + BOOST_ASSUME( !hdr().free_node_count_ ); + } #ifndef NDEBUG hdr_ = &hdr(); #endif - for ( auto & n : std::views::reverse( std::span{ nodes_ }.subspan( current_size ) ) ) + if ( !preallocated_count ) + { + BOOST_ASSUME( !preallocated_count ); + BOOST_ASSUME( !hdr().free_list_ ); + BOOST_ASSUME( !hdr().free_node_count_ ); + } + + assign_nodes_to_free_pool( static_cast( current_size ) ); +} + +void bptree_base::assign_nodes_to_free_pool( node_slot::value_type const starting_node ) noexcept +{ + for ( auto & n : std::views::reverse( std::span{ nodes_ }.subspan( starting_node ) ) ) free( n ); } @@ -315,10 +337,20 @@ void bptree_base::free( node_header & node ) noexcept BOOST_ASSERT( this->node( free_node.right ).left != free_node_slot ); #endif free_node.left = {}; - if ( free_list ) { BOOST_ASSUME( hdr.free_node_count_ ); free_node.right = free_list; this->node( free_list ).left = free_node_slot; } - else { BOOST_ASSUME( !hdr.free_node_count_ ); free_node.right = {} ; } + if ( free_list ) + { + BOOST_ASSUME( hdr.free_node_count_ ); + free_node.right = free_list; + this->node( free_list ).left = free_node_slot; + } + else + { + BOOST_ASSUME( !hdr.free_node_count_ ); + free_node.right = {}; + } free_list = free_node_slot; ++hdr.free_node_count_; + BOOST_ASSUME( hdr.free_node_count_ ); } bptree_base::node_slot diff --git a/test/b+tree.cpp b/test/b+tree.cpp index e09ba89..5068e8b 100644 --- a/test/b+tree.cpp +++ b/test/b+tree.cpp @@ -21,7 +21,7 @@ TEST( bp_tree, playground ) { std::println( "Generating test data." ); #ifdef NDEBUG - auto const test_size{ 1553735 }; + auto const test_size{ 3553735 }; #else auto const test_size{ 158735 }; #endif @@ -33,6 +33,7 @@ TEST( bp_tree, playground ) std::println( "B+tree in memory..." ); bp_tree bpt; bpt.map_memory(); + std::println( " ...reservation" ); bpt.reserve( numbers.size() ); std::println( " ...insertion" ); {