diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2023-05-22 12:13:33 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2023-05-22 18:45:28 +0000 |
commit | 36a5736f2b4dc485d3ad25435a651d93cd6585d0 (patch) | |
tree | 9ff9d4ad6ef06b0d2f1d3fca28c7df7327258b1b | |
parent | 0e1213e917bc26e7ff62cc83d83df40bd49483ed (diff) |
Pack Node ptr and idx into 8 bytes.
Tak advantage that maximum number of bits for a pointer is 57 bits (Intel IceLake), and 48 on other architectures on linux.
57 bits for the pointer and 7 bits for the idx.
-rw-r--r-- | vespalib/src/tests/btree/btree_test.cpp | 6 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/btree/btreeiterator.h | 68 |
2 files changed, 44 insertions, 30 deletions
diff --git a/vespalib/src/tests/btree/btree_test.cpp b/vespalib/src/tests/btree/btree_test.cpp index 6305eca41ac..b2f9f01e517 100644 --- a/vespalib/src/tests/btree/btree_test.cpp +++ b/vespalib/src/tests/btree/btree_test.cpp @@ -297,9 +297,9 @@ BTreeTest::assertMemoryUsage(const vespalib::MemoryUsage & exp, const vespalib:: } TEST_F(BTreeTest, control_iterator_size) { - EXPECT_EQ(208u, sizeof(BTreeIteratorBase<uint32_t, uint32_t, NoAggregated>)); - EXPECT_EQ(208u, sizeof(BTreeIteratorBase<uint32_t, BTreeNoLeafData, NoAggregated>)); - EXPECT_EQ(544u, sizeof(MyTree::Iterator)); + EXPECT_EQ(120u, sizeof(BTreeIteratorBase<uint32_t, uint32_t, NoAggregated>)); + EXPECT_EQ(120u, sizeof(BTreeIteratorBase<uint32_t, BTreeNoLeafData, NoAggregated>)); + EXPECT_EQ(288u, sizeof(MyTree::Iterator)); } TEST_F(BTreeTest, require_that_node_insert_works) diff --git a/vespalib/src/vespa/vespalib/btree/btreeiterator.h b/vespalib/src/vespa/vespalib/btree/btreeiterator.h index b3a0ebe2490..ebcf068ffb5 100644 --- a/vespalib/src/vespa/vespalib/btree/btreeiterator.h +++ b/vespalib/src/vespa/vespalib/btree/btreeiterator.h @@ -35,59 +35,73 @@ class NodeElement using NodeType = NodeT; using KeyType = typename NodeType::KeyType; using DataType = typename NodeType::DataType; - const NodeType *_node; - uint32_t _idx; + uint64_t _nodeAndIdx; + + NodeType * getWNode() const { return const_cast<NodeType *>(getNode()); } + static constexpr uint8_t NODE_BITS = 57; + static constexpr uint8_t IDX_BITS = 64 - NODE_BITS; + static constexpr uint64_t NODE_MASK = (1ul << NODE_BITS) - 1ul; + static constexpr uint64_t IDX_MASK = (1ul << IDX_BITS) - 1ul; + static constexpr uint8_t IDX_SHIFT = NODE_BITS; - NodeType * getWNode() const { return const_cast<NodeType *>(_node); } public: - NodeElement() : _node(nullptr), _idx(0u) { } - NodeElement(const NodeType *node, uint32_t idx) : _node(node), _idx(idx) { } + NodeElement() : _nodeAndIdx(0ul) { } + NodeElement(const NodeType *node, uint32_t idx) : _nodeAndIdx(uint64_t(node) | uint64_t(idx) << IDX_SHIFT) { + assert((uint64_t(node) & ~NODE_MASK) == 0ul); + assert(idx <= IDX_MASK); + } - void invalidate() { _node = nullptr; _idx = 0; } - void setNode(const NodeType *node) { _node = node; } - const NodeType * getNode() const { return _node; } - void setIdx(uint32_t idx) { _idx = idx; } - uint32_t getIdx() const { return _idx; } - void incIdx() { ++_idx; } - void decIdx() { --_idx; } + void invalidate() { _nodeAndId = 0; } + void setNode(const NodeType *node) { + assert((uint64_t(node) & ~NODE_MASK) == 0ul); + _nodeAndIdx = (_nodeAndIdx & ~NODE_MASK) | uint64_t(node); + } + const NodeType * getNode() const { return reinterpret_cast<const NodeType *>(_nodeAndIdx & NODE_MASK); } + void setIdx(uint32_t idx) { + assert(idx <= IDX_MASK); + _nodeAndIdx = (_nodeAndIdx & NODE_MASK) | (uint64_t(idx) << IDX_SHIFT); + } + uint32_t getIdx() const { return _nodeAndIdx >> IDX_SHIFT; } + void incIdx() { setIdx(getIdx() + 1); } + void decIdx() { setIdx(getIdx() - 1); } void setNodeAndIdx(const NodeType *node, uint32_t idx) { - _node = node; - _idx = idx; + assert((uint64_t(node) & ~NODE_MASK) == 0ul); + assert(idx <= IDX_MASK); + _nodeAndIdx = uint64_t(node) | uint64_t(idx) << IDX_SHIFT; } - const KeyType & getKey() const { return _node->getKey(_idx); } - const DataType & getData() const { return _node->getData(_idx); } + const KeyType & getKey() const { return getNode()->getKey(getIdx()); } + const DataType & getData() const { return getNode()->getData(getIdx()); } // Only use during compaction when changing reference to moved value - DataType &getWData() { return getWNode()->getWData(_idx); } - bool valid() const { return _node != nullptr; } + DataType &getWData() { return getWNode()->getWData(getIdx()); } + bool valid() const { return _nodeAndIdx != 0; } void adjustLeftVictimKilled() { - assert(_idx > 0); - --_idx; + assert(getIdx() > 0); + decIdx(); } void adjustSteal(uint32_t stolen) { - assert(_idx + stolen < _node->validSlots()); - _idx += stolen; + assert(getIdx() + stolen < getNode()->validSlots()); + setIdx(getIdx() + stolen); } void adjustSplit(bool inRightSplit) { if (inRightSplit) - ++_idx; + incIdx(); } bool adjustSplit(bool inRightSplit, const NodeType *splitNode) { adjustSplit(inRightSplit); - if (_idx >= _node->validSlots()) { - _idx -= _node->validSlots(); - _node = splitNode; + if (getIdx() >= getNode()->validSlots()) { + setNodeAndIdx(splitNode, getIdx() - getNode()->validSlots()); return true; } return false; } bool operator!=(const NodeElement &rhs) const { - return (_node != rhs._node) || (_idx != rhs._idx); + return _nodeAndIdx != rhs._nodeAndIdx; } }; |