@@ -27,18 +27,20 @@ namespace cachelib {
2727
2828class SlabAllocator ;
2929
30- // the following are for pointer compression for the memory allocator. We
31- // compress pointers by storing the slab index and the alloc index of the
32- // allocation inside the slab. With slab worth kNumSlabBits of data, if we
33- // have the min allocation size as 64 bytes, that requires kNumSlabBits - 6
34- // bits for storing the alloc index. This leaves the remaining (32 -
35- // (kNumSlabBits - 6)) bits for the slab index. Hence we can index 256 GiB
36- // of memory in slabs and index anything more than 64 byte allocations inside
37- // the slab using a 32 bit representation.
38- //
3930// This CompressedPtr makes decompression fast by staying away from division and
40- // modulo arithmetic and doing those during the compression time. We most often
41- // decompress a CompressedPtr than compress a pointer while creating one.
31+ // modulo arithmetic and doing those during the compression time. We most often
32+ // decompress a CompressedPtr than compress a pointer while creating one. This
33+ // is used for pointer compression by the memory allocator.
34+
35+ // We compress pointers by storing the tier index, slab index and alloc index of
36+ // the allocation inside the slab. With slab worth kNumSlabBits (22 bits) of
37+ // data, if we have the min allocation size as 64 bytes, that requires
38+ // kNumSlabBits - 6 = 16 bits for storing the alloc index. The tier id occupies
39+ // the 32nd bit only since its value cannot exceed kMaxTiers (2). This leaves
40+ // the remaining (32 - (kNumSlabBits - 6) - 1 bit for tier id) = 15 bits for
41+ // the slab index. Hence we can index 128 GiB of memory in slabs per tier and
42+ // index anything more than 64 byte allocations inside the slab using a 32 bit
43+ // representation.
4244class CACHELIB_PACKED_ATTR CompressedPtr {
4345 public:
4446 using PtrType = uint32_t ;
@@ -62,9 +64,9 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
6264 return static_cast <uint32_t >(1 ) << (Slab::kMinAllocPower );
6365 }
6466
65- // maximum adressable memory for pointer compression to work.
67+ // maximum addressable memory for pointer compression to work.
6668 static constexpr size_t getMaxAddressableSize () noexcept {
67- return static_cast <size_t >(1 ) << (kNumSlabIdxBits + Slab::kNumSlabBits );
69+ return static_cast <size_t >(1 ) << (kNumSlabIdxBits + Slab::kNumSlabBits + 1 );
6870 }
6971
7072 // default construct to nullptr.
@@ -89,8 +91,11 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
8991 PtrType ptr_{kNull };
9092
9193 // create a compressed pointer for a valid memory allocation.
92- CompressedPtr (uint32_t slabIdx, uint32_t allocIdx)
93- : ptr_(compress(slabIdx, allocIdx)) {}
94+ CompressedPtr (uint32_t slabIdx,
95+ uint32_t allocIdx,
96+ bool isMultiTiered,
97+ TierId tid = 0 )
98+ : ptr_(compress(slabIdx, allocIdx, isMultiTiered, tid)) {}
9499
95100 constexpr explicit CompressedPtr (PtrType ptr) noexcept : ptr_{ptr} {}
96101
@@ -100,31 +105,55 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
100105 static constexpr unsigned int kNumAllocIdxBits =
101106 Slab::kNumSlabBits - Slab::kMinAllocPower ;
102107
108+ // Use 32nd bit position for TierId
109+ static constexpr unsigned int kNumTierIdxOffset = 31 ;
110+
103111 static constexpr PtrType kAllocIdxMask = ((PtrType)1 << kNumAllocIdxBits ) - 1 ;
104112
113+ // kNumTierIdxBits most significant bits
114+ static constexpr PtrType kTierIdxMask = (PtrType)1 << kNumTierIdxOffset ;
115+
105116 // Number of bits for the slab index. This will be the top 16 bits of the
106117 // compressed ptr.
107118 static constexpr unsigned int kNumSlabIdxBits =
108- NumBits<PtrType>::value - kNumAllocIdxBits ;
119+ kNumTierIdxOffset - kNumAllocIdxBits ;
109120
110121 // Compress the given slabIdx and allocIdx into a 32-bit compressed
111122 // pointer.
112- static PtrType compress (uint32_t slabIdx, uint32_t allocIdx) noexcept {
123+ static PtrType compress (uint32_t slabIdx,
124+ uint32_t allocIdx,
125+ bool isMultiTiered,
126+ TierId tid) noexcept {
113127 XDCHECK_LE (allocIdx, kAllocIdxMask );
128+ if (!isMultiTiered) {
129+ XDCHECK_LT (slabIdx, (1u << (kNumSlabIdxBits + 1 )) - 1 );
130+ return (slabIdx << kNumAllocIdxBits ) + allocIdx;
131+ }
114132 XDCHECK_LT (slabIdx, (1u << kNumSlabIdxBits ) - 1 );
115133 return (slabIdx << kNumAllocIdxBits ) + allocIdx;
116134 }
117135
118136 // Get the slab index of the compressed ptr
119- uint32_t getSlabIdx () const noexcept {
137+ uint32_t getSlabIdx (bool isMultiTiered ) const noexcept {
120138 XDCHECK (!isNull ());
121- return static_cast <uint32_t >(ptr_ >> kNumAllocIdxBits );
139+ auto noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask : ptr_;
140+ return static_cast <uint32_t >(noTierIdPtr >> kNumAllocIdxBits );
122141 }
123142
124143 // Get the allocation index of the compressed ptr
125- uint32_t getAllocIdx () const noexcept {
144+ uint32_t getAllocIdx (bool isMultiTiered ) const noexcept {
126145 XDCHECK (!isNull ());
127- return static_cast <uint32_t >(ptr_ & kAllocIdxMask );
146+ auto noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask : ptr_;
147+ return static_cast <uint32_t >(noTierIdPtr & kAllocIdxMask );
148+ }
149+
150+ uint32_t getTierId (bool isMultiTiered) const noexcept {
151+ XDCHECK (!isNull ());
152+ return isMultiTiered ? static_cast <uint32_t >(ptr_ >> kNumTierIdxOffset ) : 0 ;
153+ }
154+
155+ void setTierId (TierId tid) noexcept {
156+ ptr_ += static_cast <uint64_t >(tid) << kNumTierIdxOffset ;
128157 }
129158
130159 friend SlabAllocator;
@@ -137,11 +166,11 @@ class PtrCompressor {
137166 : allocator_(allocator) {}
138167
139168 const CompressedPtr compress (const PtrType* uncompressed) const {
140- return allocator_.compress (uncompressed);
169+ return allocator_.compress (uncompressed, false );
141170 }
142171
143172 PtrType* unCompress (const CompressedPtr compressed) const {
144- return static_cast <PtrType*>(allocator_.unCompress (compressed));
173+ return static_cast <PtrType*>(allocator_.unCompress (compressed, false ));
145174 }
146175
147176 bool operator ==(const PtrCompressor& rhs) const noexcept {
0 commit comments