bps: add 2-way support for logarithmic offsets
The current tree does not allow to find offset of an element or create an iterator to an element based on its offset. This patch is meant to fix this by expanding the data structure with additional information and introducing methods using it: subtree cardinalities. A subtree cardinality is the amount of elements in it. For example, cardinality of a leaf block is count of elements in it (effectively it equals to leaf.header.size), cardinality of an inner block is the sum of cardinalities of its chlidren. The patch includes two chosable ways to store this information: `BPS_INNER_CARD` and `BPS_INNER_CHILD_CARDS`. The first implementation sores block cardinality in each inner block. This implementation has minimal memory overhead (it just introduces a new 64-bit field in `struct bps_inner`), but calculation of offsets is not that fast, since in order to find an offset of a particular child of an inner node we have to look into each of its children prior to the looking one. The second one sores an array of children cardinalities in inner blocks. The memory overhead of this implementation is visible since it significantly decreases the children capacity of inner blocks. The max count in inner block is decreased from 42 to 25 for tree of 8-byte elements with 512-byte blocks and from 25 to 18 for tree of 16-byte elements with 512-byte blocks. Offset calcluations are faster though. It's possible (though impractical) to enable both solutions, the tree will use the best ways to perform offset-based tasks, but will have to maintain both children cardinality array and inner own cardinalities. Along with the theoretical support this patch introduces a bunch of functions using it: - `iterator_at(t, offset)`: gives an iterator to an element of a tree or tree view by its offset; - `find_get_offset(t, key, offset_ptr)`: the same as `find` but also provides to the user the offset of the found element in the output parameter; - `[lower|upper]_bound[_elem]_get_offset(t, key, exact, offset_ptr)`: the same as upper/lower bound functions but provide to the user the offset to the found position (end of the tree included). - `insert_get_offset(t, new_elem, replaced, offset_ptr)`: the same as `insert`, but also provides the offset to the inserted element. - `delete_get_offset(t, elem, offset_ptr)`: same as `delete`, but also returns offset to the deleted element prior to the deletion in the output parameter. Another new function introduced is bps_tree_view_debug_check(t). This function is similar to the bps_tree_debug_check(t), but is applicable to tree views. It's used to adopt default tree view tests to the new tree variations. Each new implementation is tested by old tree tests (these now support several tree variations selected with a C definition, the definitions are specified in the test/unit/CMakeLists.txt). New offset API-related test introduced (this one tests both of two tree variations - BPS_INNER_CARD and BPS_INNER_CHILD_CARDS). Part of #8204 NO_DOC=internal NO_CHANGELOG=internal
Showing
- src/lib/salad/bps_tree.h 1676 additions, 189 deletionssrc/lib/salad/bps_tree.h
- test/unit/CMakeLists.txt 47 additions, 3 deletionstest/unit/CMakeLists.txt
- test/unit/bps_tree.cc 24 additions, 4 deletionstest/unit/bps_tree.cc
- test/unit/bps_tree_iterator.cc 13 additions, 1 deletiontest/unit/bps_tree_iterator.cc
- test/unit/bps_tree_offset_api.cc 457 additions, 0 deletionstest/unit/bps_tree_offset_api.cc
- test/unit/bps_tree_view.c 52 additions, 22 deletionstest/unit/bps_tree_view.c
Loading
Please register or sign in to comment