@@ -27,18 +27,19 @@ namespace cachelib {
27
27
28
28
class SlabAllocator ;
29
29
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
- //
39
30
// This CompressedPtr makes decompression fast by staying away from division and
40
31
// 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.
42
43
class CACHELIB_PACKED_ATTR CompressedPtr {
43
44
public:
44
45
using PtrType = uint32_t ;
@@ -62,9 +63,10 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
62
63
return static_cast <uint32_t >(1 ) << (Slab::kMinAllocPower );
63
64
}
64
65
65
- // maximum adressable memory for pointer compression to work.
66
+ // maximum addressable memory for pointer compression to work.
66
67
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 );
68
70
}
69
71
70
72
// default construct to nullptr.
@@ -89,8 +91,11 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
89
91
PtrType ptr_{kNull };
90
92
91
93
// 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)) {}
94
99
95
100
constexpr explicit CompressedPtr (PtrType ptr) noexcept : ptr_{ptr} {}
96
101
@@ -100,31 +105,56 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
100
105
static constexpr unsigned int kNumAllocIdxBits =
101
106
Slab::kNumSlabBits - Slab::kMinAllocPower ;
102
107
108
+ // Use 32nd bit position for TierId
109
+ static constexpr unsigned int kNumTierIdxOffset = 31 ;
110
+
103
111
static constexpr PtrType kAllocIdxMask = ((PtrType)1 << kNumAllocIdxBits ) - 1 ;
104
112
113
+ // kNumTierIdxBits most significant bits
114
+ static constexpr PtrType kTierIdxMask = (PtrType)1 << kNumTierIdxOffset ;
115
+
105
116
// Number of bits for the slab index. This will be the top 16 bits of the
106
117
// 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
+ }
109
121
110
122
// Compress the given slabIdx and allocIdx into a 32-bit compressed
111
123
// 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 {
113
128
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;
116
135
}
117
136
118
137
// Get the slab index of the compressed ptr
119
- uint32_t getSlabIdx () const noexcept {
138
+ uint32_t getSlabIdx (bool isMultiTiered ) const noexcept {
120
139
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 );
122
142
}
123
143
124
144
// 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 {
126
152
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 ;
128
158
}
129
159
130
160
friend SlabAllocator;
@@ -137,11 +167,12 @@ class PtrCompressor {
137
167
: allocator_(allocator) {}
138
168
139
169
const CompressedPtr compress (const PtrType* uncompressed) const {
140
- return allocator_.compress (uncompressed);
170
+ return allocator_.compress (uncompressed, false /* isMultiTiered */ );
141
171
}
142
172
143
173
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 */ ));
145
176
}
146
177
147
178
bool operator ==(const PtrCompressor& rhs) const noexcept {
0 commit comments