@@ -31,20 +31,32 @@ template <typename PtrType, typename AllocatorContainer>
3131class PtrCompressor ;
3232
3333// 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- //
34+ // compress pointers by storing the tier index, slab index and alloc index
35+ // of the allocation inside the slab. With slab worth kNumSlabBits (22 bits)
36+ // of data, if we have the min allocation size as 64 bytes, that requires
37+ // kNumSlabBits - 6 = 16 bits for storing the alloc index. The tier id
38+ // occupies the 32nd bit only since its value cannot exceed kMaxTiers (2).
39+ // This leaves the remaining (32 -(kNumSlabBits - 6) - 1 bit for tier id) =
40+ // 15 bits for the slab index. Hence we can index 128 GiB of memory in slabs
41+ // per tier and index anything more than 64 byte allocations inside the slab
42+ // using a 32 bit representation.
43+
4244// This CompressedPtr makes decompression fast by staying away from division and
4345// modulo arithmetic and doing those during the compression time. We most often
4446// decompress a CompressedPtr than compress a pointer while creating one.
47+ // the following are for pointer compression for the memory allocator. We
48+ // compress pointers by storing the tier index, slab index and alloc index
49+ // of the allocation inside the slab. With slab worth kNumSlabBits (22 bits)
50+ // of data, if we have the min allocation size as 64 bytes, that requires
51+ // kNumSlabBits - 6 = 16 bits for storing the alloc index. The tier id
52+ // occupies the 32nd bit only since its value cannot exceed kMaxTiers (2).
53+ // This leaves the remaining (32 -(kNumSlabBits - 6) - 1 bit for tier id) =
54+ // 15 bits for the slab index. Hence we can index 128 GiB of memory in slabs
55+ // per tier and index anything more than 64 byte allocations inside the slab
56+ // using a 32 bit representation.
4557class CACHELIB_PACKED_ATTR CompressedPtr {
4658 public:
47- using PtrType = uint64_t ;
59+ using PtrType = uint32_t ;
4860 // Thrift doesn't support unsigned type
4961 using SerializedPtrType = int64_t ;
5062
@@ -67,7 +79,7 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
6779
6880 // maximum adressable memory for pointer compression to work.
6981 static constexpr size_t getMaxAddressableSize () noexcept {
70- return static_cast <size_t >(1 ) << (kNumSlabIdxBits + Slab::kNumSlabBits );
82+ return static_cast <size_t >(1 ) << (kNumSlabIdxBits + Slab::kNumSlabBits + 1 );
7183 }
7284
7385 // default construct to nullptr.
@@ -92,8 +104,8 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
92104 PtrType ptr_{kNull };
93105
94106 // 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)) {}
107+ CompressedPtr (uint32_t slabIdx, uint32_t allocIdx, bool isMultiTiered, TierId tid = 0 )
108+ : ptr_(compress(slabIdx, allocIdx, isMultiTiered, tid)) {}
97109
98110 constexpr explicit CompressedPtr (PtrType ptr) noexcept : ptr_{ptr} {}
99111
@@ -103,45 +115,48 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
103115 static constexpr unsigned int kNumAllocIdxBits =
104116 Slab::kNumSlabBits - Slab::kMinAllocPower ;
105117
106- // Use topmost 32 bits for TierId
107- // XXX: optimize
108- static constexpr unsigned int kNumTierIdxOffset = 32 ;
118+ // Use 32nd bit position for TierId
119+ static constexpr unsigned int kNumTierIdxOffset = 31 ;
109120
110121 static constexpr PtrType kAllocIdxMask = ((PtrType)1 << kNumAllocIdxBits ) - 1 ;
111122
112123 // kNumTierIdxBits most significant bits
113- static constexpr PtrType kTierIdxMask = ((( PtrType)1 << kNumTierIdxOffset ) - 1 ) << (NumBits<PtrType>::value - kNumTierIdxOffset ) ;
124+ static constexpr PtrType kTierIdxMask = (PtrType)1 << kNumTierIdxOffset ;
114125
115126 // Number of bits for the slab index. This will be the top 16 bits of the
116127 // compressed ptr.
117128 static constexpr unsigned int kNumSlabIdxBits =
118- NumBits<PtrType>::value - kNumTierIdxOffset - kNumAllocIdxBits ;
129+ kNumTierIdxOffset - kNumAllocIdxBits ;
119130
120131 // Compress the given slabIdx and allocIdx into a 64-bit compressed
121132 // pointer.
122- static PtrType compress (uint32_t slabIdx, uint32_t allocIdx, TierId tid) noexcept {
133+ static PtrType compress (uint32_t slabIdx, uint32_t allocIdx, bool isMultiTiered, TierId tid) noexcept {
123134 XDCHECK_LE (allocIdx, kAllocIdxMask );
135+ if (!isMultiTiered) {
136+ XDCHECK_LT (slabIdx, (1u << (kNumSlabIdxBits +1 )) - 1 );
137+ return (slabIdx << kNumAllocIdxBits ) + allocIdx;
138+ }
124139 XDCHECK_LT (slabIdx, (1u << kNumSlabIdxBits ) - 1 );
125140 return (static_cast <uint64_t >(tid) << kNumTierIdxOffset ) + (slabIdx << kNumAllocIdxBits ) + allocIdx;
126141 }
127142
128143 // Get the slab index of the compressed ptr
129- uint32_t getSlabIdx () const noexcept {
144+ uint32_t getSlabIdx (bool isMultiTiered ) const noexcept {
130145 XDCHECK (!isNull ());
131- auto noTierIdPtr = ptr_ & ~kTierIdxMask ;
146+ auto noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask : ptr_ ;
132147 return static_cast <uint32_t >(noTierIdPtr >> kNumAllocIdxBits );
133148 }
134149
135150 // Get the allocation index of the compressed ptr
136- uint32_t getAllocIdx () const noexcept {
151+ uint32_t getAllocIdx (bool isMultiTiered ) const noexcept {
137152 XDCHECK (!isNull ());
138- auto noTierIdPtr = ptr_ & ~kTierIdxMask ;
153+ auto noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask : ptr_ ;
139154 return static_cast <uint32_t >(noTierIdPtr & kAllocIdxMask );
140155 }
141156
142- uint32_t getTierId () const noexcept {
157+ uint32_t getTierId (bool isMultiTiered ) const noexcept {
143158 XDCHECK (!isNull ());
144- return static_cast <uint32_t >(ptr_ >> kNumTierIdxOffset );
159+ return isMultiTiered ? static_cast <uint32_t >(ptr_ >> kNumTierIdxOffset ) : 0 ;
145160 }
146161
147162 void setTierId (TierId tid) noexcept {
@@ -160,11 +175,11 @@ class SingleTierPtrCompressor {
160175 : allocator_(allocator) {}
161176
162177 const CompressedPtr compress (const PtrType* uncompressed) const {
163- return allocator_.compress (uncompressed);
178+ return allocator_.compress (uncompressed, false );
164179 }
165180
166181 PtrType* unCompress (const CompressedPtr compressed) const {
167- return static_cast <PtrType*>(allocator_.unCompress (compressed));
182+ return static_cast <PtrType*>(allocator_.unCompress (compressed, false ));
168183 }
169184
170185 bool operator ==(const SingleTierPtrCompressor& rhs) const noexcept {
@@ -196,19 +211,21 @@ class PtrCompressor {
196211 break ;
197212 }
198213
199- auto cptr = allocators_[tid]->compress (uncompressed);
200- cptr.setTierId (tid);
201-
214+ bool isMultiTiered = allocators_.size () > 1 ? true : false ;
215+ auto cptr = allocators_[tid]->compress (uncompressed, isMultiTiered);
216+ if (allocators_.size () > 1 ) { // config has multiple tiers
217+ cptr.setTierId (tid);
218+ }
202219 return cptr;
203220 }
204221
205222 PtrType* unCompress (const CompressedPtr compressed) const {
206223 if (compressed.isNull ()) {
207224 return nullptr ;
208225 }
209-
210- auto &allocator = *allocators_[compressed.getTierId ()];
211- return static_cast <PtrType*>(allocator.unCompress (compressed));
226+ bool isMultiTiered = allocators_. size () > 1 ? true : false ;
227+ auto &allocator = *allocators_[compressed.getTierId (isMultiTiered )];
228+ return static_cast <PtrType*>(allocator.unCompress (compressed, isMultiTiered ));
212229 }
213230
214231 bool operator ==(const PtrCompressor& rhs) const noexcept {
0 commit comments