@@ -27,18 +27,19 @@ 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
4031//  modulo arithmetic and doing those during the compression time. We most often
41- //  decompress a CompressedPtr than compress a pointer while creating one.
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 per tier in multi-tier
42+ //  configuration or index 256 GiB in single-tier configuration.
4243class  CACHELIB_PACKED_ATTR  CompressedPtr {
4344 public: 
4445  using  PtrType = uint32_t ;
@@ -62,9 +63,10 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
6263    return  static_cast <uint32_t >(1 ) << (Slab::kMinAllocPower );
6364  }
6465
65-   //  maximum adressable  memory for pointer compression to work.
66+   //  maximum addressable  memory for pointer compression to work.
6667  static  constexpr  size_t  getMaxAddressableSize () noexcept  {
67-     return  static_cast <size_t >(1 ) << (kNumSlabIdxBits  + Slab::kNumSlabBits );
68+     return  static_cast <size_t >(1 )
69+            << (numSlabIdxBits (false ) + Slab::kNumSlabBits );
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,56 @@ 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.
107-   static  constexpr  unsigned  int  kNumSlabIdxBits  =
108-       NumBits<PtrType>::value - kNumAllocIdxBits ;
118+   static  constexpr  unsigned  int  numSlabIdxBits (bool  isMultiTiered) {
119+     return  kNumTierIdxOffset  - kNumAllocIdxBits  + (!isMultiTiered);
120+   }
109121
110122  //  Compress the given slabIdx and allocIdx into a 32-bit compressed
111123  //  pointer.
112-   static  PtrType compress (uint32_t  slabIdx, uint32_t  allocIdx) noexcept  {
124+   static  PtrType compress (uint32_t  slabIdx,
125+                           uint32_t  allocIdx,
126+                           bool  isMultiTiered,
127+                           TierId tid) noexcept  {
113128    XDCHECK_LE (allocIdx, kAllocIdxMask );
114-     XDCHECK_LT (slabIdx, (1u  << kNumSlabIdxBits ) - 1 );
115-     return  (slabIdx << kNumAllocIdxBits ) + allocIdx;
129+     XDCHECK_LT (slabIdx, (1u  << numSlabIdxBits (isMultiTiered)) - 1 );
130+     if  (!isMultiTiered) {
131+       return  (slabIdx << kNumAllocIdxBits ) + allocIdx;
132+     }
133+     return  (static_cast <uint32_t >(tid) << kNumTierIdxOffset ) +
134+            (slabIdx << kNumAllocIdxBits ) + allocIdx;
116135  }
117136
118137  //  Get the slab index of the compressed ptr
119-   uint32_t  getSlabIdx () const  noexcept  {
138+   uint32_t  getSlabIdx (bool  isMultiTiered ) const  noexcept  {
120139    XDCHECK (!isNull ());
121-     return  static_cast <uint32_t >(ptr_ >> kNumAllocIdxBits );
140+     auto  noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask  : ptr_;
141+     return  static_cast <uint32_t >(noTierIdPtr >> kNumAllocIdxBits );
122142  }
123143
124144  //  Get the allocation index of the compressed ptr
125-   uint32_t  getAllocIdx () const  noexcept  {
145+   uint32_t  getAllocIdx (bool  isMultiTiered) const  noexcept  {
146+     XDCHECK (!isNull ());
147+     auto  noTierIdPtr = isMultiTiered ? ptr_ & ~kTierIdxMask  : ptr_;
148+     return  static_cast <uint32_t >(noTierIdPtr & kAllocIdxMask );
149+   }
150+ 
151+   uint32_t  getTierId (bool  isMultiTiered) const  noexcept  {
126152    XDCHECK (!isNull ());
127-     return  static_cast <uint32_t >(ptr_ & kAllocIdxMask );
153+     return  isMultiTiered ? static_cast <uint32_t >(ptr_ >> kNumTierIdxOffset ) : 0 ;
154+   }
155+ 
156+   void  setTierId (TierId tid) noexcept  {
157+     ptr_ += static_cast <uint32_t >(tid) << kNumTierIdxOffset ;
128158  }
129159
130160  friend  SlabAllocator;
@@ -137,11 +167,12 @@ class PtrCompressor {
137167      : allocator_(allocator) {}
138168
139169  const  CompressedPtr compress (const  PtrType* uncompressed) const  {
140-     return  allocator_.compress (uncompressed);
170+     return  allocator_.compress (uncompressed,  false   /*  isMultiTiered  */ 
141171  }
142172
143173  PtrType* unCompress (const  CompressedPtr compressed) const  {
144-     return  static_cast <PtrType*>(allocator_.unCompress (compressed));
174+     return  static_cast <PtrType*>(
175+         allocator_.unCompress (compressed, false  /*  isMultiTiered */ 
145176  }
146177
147178  bool  operator ==(const  PtrCompressor& rhs) const  noexcept  {
0 commit comments