@@ -27,9 +27,12 @@ namespace cachelib {
2727
2828class SlabAllocator ;
2929
30+ template <typename PtrType, typename AllocatorContainer>
31+ class PtrCompressor ;
32+
3033// This CompressedPtr makes decompression fast by staying away from division and
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
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
3336// is used for pointer compression by the memory allocator.
3437
3538// We compress pointers by storing the tier index, slab index and alloc index of
@@ -38,8 +41,9 @@ class SlabAllocator;
3841// kNumSlabBits - 6 = 16 bits for storing the alloc index. The tier id occupies
3942// the 32nd bit only since its value cannot exceed kMaxTiers (2). This leaves
4043// 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.
44+ // the slab index. Hence we can index 128 GiB of memory in slabs per tier and
45+ // index anything more than 64 byte allocations inside the slab using a 32 bit
46+ // representation.
4347class CACHELIB_PACKED_ATTR CompressedPtr {
4448 public:
4549 using PtrType = uint32_t ;
@@ -158,33 +162,83 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
158162 }
159163
160164 friend SlabAllocator;
165+ template <typename CPtrType, typename AllocatorContainer>
166+ friend class PtrCompressor ;
161167};
162168
163169template <typename PtrType, typename AllocatorT>
164- class PtrCompressor {
170+ class SingleTierPtrCompressor {
165171 public:
166- explicit PtrCompressor (const AllocatorT& allocator) noexcept
172+ explicit SingleTierPtrCompressor (const AllocatorT& allocator) noexcept
167173 : allocator_(allocator) {}
168174
169175 const CompressedPtr compress (const PtrType* uncompressed) const {
170- return allocator_.compress (uncompressed, true );
176+ return allocator_.compress (uncompressed, false );
171177 }
172178
173179 PtrType* unCompress (const CompressedPtr compressed) const {
174- return static_cast <PtrType*>(allocator_.unCompress (compressed, true ));
180+ return static_cast <PtrType*>(allocator_.unCompress (compressed, false ));
175181 }
176182
177- bool operator ==(const PtrCompressor & rhs) const noexcept {
183+ bool operator ==(const SingleTierPtrCompressor & rhs) const noexcept {
178184 return &allocator_ == &rhs.allocator_ ;
179185 }
180186
181- bool operator !=(const PtrCompressor & rhs) const noexcept {
187+ bool operator !=(const SingleTierPtrCompressor & rhs) const noexcept {
182188 return !(*this == rhs);
183189 }
184190
185191 private:
186192 // memory allocator that does the pointer compression.
187193 const AllocatorT& allocator_;
188194};
195+
196+ template <typename PtrType, typename AllocatorContainer>
197+ class PtrCompressor {
198+ public:
199+ explicit PtrCompressor (const AllocatorContainer& allocators) noexcept
200+ : allocators_(allocators) {}
201+
202+ const CompressedPtr compress (const PtrType* uncompressed) const {
203+ if (uncompressed == nullptr )
204+ return CompressedPtr{};
205+
206+ TierId tid;
207+ for (tid = 0 ; tid < allocators_.size (); tid++) {
208+ if (allocators_[tid]->isMemoryInAllocator (
209+ static_cast <const void *>(uncompressed)))
210+ break ;
211+ }
212+
213+ bool isMultiTiered = allocators_.size () > 1 ;
214+ auto cptr = allocators_[tid]->compress (uncompressed, isMultiTiered);
215+ if (isMultiTiered) { // config has multiple tiers
216+ cptr.setTierId (tid);
217+ }
218+ return cptr;
219+ }
220+
221+ PtrType* unCompress (const CompressedPtr compressed) const {
222+ if (compressed.isNull ()) {
223+ return nullptr ;
224+ }
225+ bool isMultiTiered = allocators_.size () > 1 ;
226+ auto & allocator = *allocators_[compressed.getTierId (isMultiTiered)];
227+ return static_cast <PtrType*>(
228+ allocator.unCompress (compressed, isMultiTiered));
229+ }
230+
231+ bool operator ==(const PtrCompressor& rhs) const noexcept {
232+ return &allocators_ == &rhs.allocators_ ;
233+ }
234+
235+ bool operator !=(const PtrCompressor& rhs) const noexcept {
236+ return !(*this == rhs);
237+ }
238+
239+ private:
240+ // memory allocator that does the pointer compression.
241+ const AllocatorContainer& allocators_;
242+ };
189243} // namespace cachelib
190244} // namespace facebook
0 commit comments