@@ -30,21 +30,22 @@ class SlabAllocator;
3030template <typename PtrType, typename AllocatorContainer>
3131class PtrCompressor ;
3232
33- // the following are for pointer compression for the memory allocator. We
34- // compress pointers by storing the slab index and the alloc index of the
35- // allocation inside the slab. With slab worth kNumSlabBits of data, if we
36- // have the min allocation size as 64 bytes, that requires kNumSlabBits - 6
37- // bits for storing the alloc index. This leaves the remaining (32 -
38- // (kNumSlabBits - 6)) bits for the slab index. Hence we can index 256 GiB
39- // of memory in slabs and index anything more than 64 byte allocations inside
40- // the slab using a 32 bit representation.
41- //
4233// This CompressedPtr makes decompression fast by staying away from division and
43- // modulo arithmetic and doing those during the compression time. We most often
44- // decompress a CompressedPtr than compress a pointer while creating one.
34+ // modulo arithmetic and doing those during the compression time. We most often
35+ // decompress a CompressedPtr than compress a pointer while creating one. This
36+ // is used for pointer compression by the memory allocator.
37+
38+ // We compress pointers by storing the tier index, slab index and alloc index of
39+ // the allocation inside the slab. With slab worth kNumSlabBits (22 bits) of data,
40+ // if we have the min allocation size as 64 bytes, that requires kNumSlabBits - 6
41+ // = 16 bits for storing the alloc index. The tier id occupies the 32nd bit only
42+ // since its value cannot exceed kMaxTiers (2). This leaves the remaining
43+ // (32 - (kNumSlabBits - 6) - 1 bit for tier id) = 15 bits for the slab index.
44+ // Hence we can index 128 GiB of memory in slabs per tier and index anything more
45+ // than 64 byte allocations inside the slab using a 32 bit representation.
4546class CACHELIB_PACKED_ATTR CompressedPtr {
4647 public:
47- using PtrType = uint64_t ;
48+ using PtrType = uint32_t ;
4849 // Thrift doesn't support unsigned type
4950 using SerializedPtrType = int64_t ;
5051
@@ -65,9 +66,9 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
6566 return static_cast <uint32_t >(1 ) << (Slab::kMinAllocPower );
6667 }
6768
68- // maximum adressable memory for pointer compression to work.
69+ // maximum addressable memory for pointer compression to work.
6970 static constexpr size_t getMaxAddressableSize () noexcept {
70- return static_cast <size_t >(1 ) << (kNumSlabIdxBits + Slab::kNumSlabBits );
71+ return static_cast <size_t >(1 ) << (kNumSlabIdxBits + Slab::kNumSlabBits + 1 );
7172 }
7273
7374 // default construct to nullptr.
@@ -92,8 +93,8 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
9293 PtrType ptr_{kNull };
9394
9495 // create a compressed pointer for a valid memory allocation.
95- CompressedPtr (uint32_t slabIdx, uint32_t allocIdx, TierId tid = 0 )
96- : ptr_(compress(slabIdx, allocIdx, tid)) {}
96+ CompressedPtr (uint32_t slabIdx, uint32_t allocIdx, bool isMultiTiered, TierId tid = 0 )
97+ : ptr_(compress(slabIdx, allocIdx, isMultiTiered, tid)) {}
9798
9899 constexpr explicit CompressedPtr (PtrType ptr) noexcept : ptr_{ptr} {}
99100
@@ -103,45 +104,48 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
103104 static constexpr unsigned int kNumAllocIdxBits =
104105 Slab::kNumSlabBits - Slab::kMinAllocPower ;
105106
106- // Use topmost 32 bits for TierId
107- // XXX: optimize
108- static constexpr unsigned int kNumTierIdxOffset = 32 ;
107+ // Use 32nd bit position for TierId
108+ static constexpr unsigned int kNumTierIdxOffset = 31 ;
109109
110110 static constexpr PtrType kAllocIdxMask = ((PtrType)1 << kNumAllocIdxBits ) - 1 ;
111111
112112 // kNumTierIdxBits most significant bits
113- static constexpr PtrType kTierIdxMask = ((( PtrType)1 << kNumTierIdxOffset ) - 1 ) << (NumBits<PtrType>::value - kNumTierIdxOffset ) ;
113+ static constexpr PtrType kTierIdxMask = (PtrType)1 << kNumTierIdxOffset ;
114114
115115 // Number of bits for the slab index. This will be the top 16 bits of the
116116 // compressed ptr.
117117 static constexpr unsigned int kNumSlabIdxBits =
118- NumBits<PtrType>::value - kNumTierIdxOffset - kNumAllocIdxBits ;
118+ kNumTierIdxOffset - kNumAllocIdxBits ;
119119
120120 // Compress the given slabIdx and allocIdx into a 64-bit compressed
121121 // pointer.
122- static PtrType compress (uint32_t slabIdx, uint32_t allocIdx, TierId tid) noexcept {
122+ static PtrType compress (uint32_t slabIdx, uint32_t allocIdx, bool isMultiTiered, TierId tid) noexcept {
123123 XDCHECK_LE (allocIdx, kAllocIdxMask );
124+ if (!isMultiTiered) {
125+ XDCHECK_LT (slabIdx, (1u << (kNumSlabIdxBits +1 )) - 1 );
126+ return (slabIdx << kNumAllocIdxBits ) + allocIdx;
127+ }
124128 XDCHECK_LT (slabIdx, (1u << kNumSlabIdxBits ) - 1 );
125129 return (static_cast <uint64_t >(tid) << kNumTierIdxOffset ) + (slabIdx << kNumAllocIdxBits ) + allocIdx;
126130 }
127131
128132 // Get the slab index of the compressed ptr
129- uint32_t getSlabIdx () const noexcept {
133+ uint32_t getSlabIdx (bool isMultiTiered ) const noexcept {
130134 XDCHECK (!isNull ());
131- auto noTierIdPtr = ptr_ & ~kTierIdxMask ;
135+ auto noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask : ptr_ ;
132136 return static_cast <uint32_t >(noTierIdPtr >> kNumAllocIdxBits );
133137 }
134138
135139 // Get the allocation index of the compressed ptr
136- uint32_t getAllocIdx () const noexcept {
140+ uint32_t getAllocIdx (bool isMultiTiered ) const noexcept {
137141 XDCHECK (!isNull ());
138- auto noTierIdPtr = ptr_ & ~kTierIdxMask ;
142+ auto noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask : ptr_ ;
139143 return static_cast <uint32_t >(noTierIdPtr & kAllocIdxMask );
140144 }
141145
142- uint32_t getTierId () const noexcept {
146+ uint32_t getTierId (bool isMultiTiered ) const noexcept {
143147 XDCHECK (!isNull ());
144- return static_cast <uint32_t >(ptr_ >> kNumTierIdxOffset );
148+ return isMultiTiered ? static_cast <uint32_t >(ptr_ >> kNumTierIdxOffset ) : 0 ;
145149 }
146150
147151 void setTierId (TierId tid) noexcept {
@@ -160,11 +164,11 @@ class SingleTierPtrCompressor {
160164 : allocator_(allocator) {}
161165
162166 const CompressedPtr compress (const PtrType* uncompressed) const {
163- return allocator_.compress (uncompressed);
167+ return allocator_.compress (uncompressed, false );
164168 }
165169
166170 PtrType* unCompress (const CompressedPtr compressed) const {
167- return static_cast <PtrType*>(allocator_.unCompress (compressed));
171+ return static_cast <PtrType*>(allocator_.unCompress (compressed, false ));
168172 }
169173
170174 bool operator ==(const SingleTierPtrCompressor& rhs) const noexcept {
@@ -196,19 +200,21 @@ class PtrCompressor {
196200 break ;
197201 }
198202
199- auto cptr = allocators_[tid]->compress (uncompressed);
200- cptr.setTierId (tid);
201-
203+ bool isMultiTiered = allocators_.size () > 1 ;
204+ auto cptr = allocators_[tid]->compress (uncompressed, isMultiTiered);
205+ if (isMultiTiered) { // config has multiple tiers
206+ cptr.setTierId (tid);
207+ }
202208 return cptr;
203209 }
204210
205211 PtrType* unCompress (const CompressedPtr compressed) const {
206212 if (compressed.isNull ()) {
207213 return nullptr ;
208214 }
209-
210- auto &allocator = *allocators_[compressed.getTierId ()];
211- return static_cast <PtrType*>(allocator.unCompress (compressed));
215+ bool isMultiTiered = allocators_. size () > 1 ;
216+ auto &allocator = *allocators_[compressed.getTierId (isMultiTiered )];
217+ return static_cast <PtrType*>(allocator.unCompress (compressed, isMultiTiered ));
212218 }
213219
214220 bool operator ==(const PtrCompressor& rhs) const noexcept {
0 commit comments