Skip to content

Commit 6fb2e74

Browse files
committed
changed compressed ptr to 32 bits and slab indx size to 15 bits
1 parent 1d16e1a commit 6fb2e74

File tree

5 files changed

+116
-67
lines changed

5 files changed

+116
-67
lines changed

cachelib/allocator/Cache.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ class CacheBase {
8383
CacheBase(CacheBase&&) = default;
8484
CacheBase& operator=(CacheBase&&) = default;
8585

86-
// TODO: come up with some reasonable number
87-
static constexpr unsigned kMaxTiers = 8;
86+
// Setting max tier count to 2
87+
// This is needed to keep CompressedPtr at 32 bits
88+
static constexpr unsigned kMaxTiers = 2;
8889

8990
// Get a string referring to the cache name for this cache
9091
virtual const std::string getCacheName() const = 0;

cachelib/allocator/memory/AllocationClass.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ AllocationClass::AllocationClass(ClassId classId,
5050
poolId_(poolId),
5151
allocationSize_(allocSize),
5252
slabAlloc_(s),
53-
freedAllocations_{slabAlloc_.createSingleTierPtrCompressor<FreeAlloc>()} {
53+
freedAllocations_{slabAlloc_.createPtrCompressor<FreeAlloc>()} {
5454
checkState();
5555
}
5656

@@ -102,7 +102,7 @@ AllocationClass::AllocationClass(
102102
currSlab_(s.getSlabForIdx(*object.currSlabIdx_ref())),
103103
slabAlloc_(s),
104104
freedAllocations_(*object.freedAllocationsObject_ref(),
105-
slabAlloc_.createSingleTierPtrCompressor<FreeAlloc>()),
105+
slabAlloc_.createPtrCompressor<FreeAlloc>()),
106106
canAllocate_(*object.canAllocate_ref()) {
107107
if (!slabAlloc_.isRestorable()) {
108108
throw std::logic_error("The allocation class cannot be restored.");
@@ -356,9 +356,9 @@ std::pair<bool, std::vector<void*>> AllocationClass::pruneFreeAllocs(
356356
// allocated slab, release any freed allocations belonging to this slab.
357357
// Set the bit to true if the corresponding allocation is freed, false
358358
// otherwise.
359-
FreeList freeAllocs{slabAlloc_.createSingleTierPtrCompressor<FreeAlloc>()};
360-
FreeList notInSlab{slabAlloc_.createSingleTierPtrCompressor<FreeAlloc>()};
361-
FreeList inSlab{slabAlloc_.createSingleTierPtrCompressor<FreeAlloc>()};
359+
FreeList freeAllocs{slabAlloc_.createPtrCompressor<FreeAlloc>()};
360+
FreeList notInSlab{slabAlloc_.createPtrCompressor<FreeAlloc>()};
361+
FreeList inSlab{slabAlloc_.createPtrCompressor<FreeAlloc>()};
362362

363363
lock_->lock_combine([&]() {
364364
// Take the allocation class free list offline

cachelib/allocator/memory/AllocationClass.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ class AllocationClass {
446446
struct CACHELIB_PACKED_ATTR FreeAlloc {
447447
using CompressedPtr = facebook::cachelib::CompressedPtr;
448448
using PtrCompressor =
449-
facebook::cachelib::SingleTierPtrCompressor<FreeAlloc, SlabAllocator>;
449+
facebook::cachelib::PtrCompressor<FreeAlloc, SlabAllocator>;
450450
SListHook<FreeAlloc> hook_{};
451451
};
452452

cachelib/allocator/memory/CompressedPtr.h

Lines changed: 105 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,70 @@
1818

1919
#include <folly/logging/xlog.h>
2020

21+
#include <deque>
22+
#include <forward_list>
23+
#include <list>
24+
#include <map>
2125
#include <memory>
26+
#include <queue>
27+
#include <set>
28+
#include <stack>
29+
#include <string>
30+
#include <tuple>
31+
#include <type_traits>
32+
#include <unordered_map>
33+
#include <unordered_set>
34+
#include <utility>
35+
#include <vector>
2236

2337
#include "cachelib/allocator/memory/Slab.h"
2438

39+
// specialize a type for all of the STL containers.
40+
namespace IsContainerImpl {
41+
template <typename T>
42+
struct IsContainer : std::false_type {};
43+
template <typename T, std::size_t N>
44+
struct IsContainer<std::array<T, N>> : std::true_type {};
45+
template <typename... Args>
46+
struct IsContainer<std::vector<Args...>> : std::true_type {};
47+
template <typename... Args>
48+
struct IsContainer<std::deque<Args...>> : std::true_type {};
49+
template <typename... Args>
50+
struct IsContainer<std::list<Args...>> : std::true_type {};
51+
template <typename... Args>
52+
struct IsContainer<std::forward_list<Args...>> : std::true_type {};
53+
template <typename... Args>
54+
struct IsContainer<std::set<Args...>> : std::true_type {};
55+
template <typename... Args>
56+
struct IsContainer<std::multiset<Args...>> : std::true_type {};
57+
template <typename... Args>
58+
struct IsContainer<std::map<Args...>> : std::true_type {};
59+
template <typename... Args>
60+
struct IsContainer<std::multimap<Args...>> : std::true_type {};
61+
template <typename... Args>
62+
struct IsContainer<std::unordered_set<Args...>> : std::true_type {};
63+
template <typename... Args>
64+
struct IsContainer<std::unordered_multiset<Args...>> : std::true_type {};
65+
template <typename... Args>
66+
struct IsContainer<std::unordered_map<Args...>> : std::true_type {};
67+
template <typename... Args>
68+
struct IsContainer<std::unordered_multimap<Args...>> : std::true_type {};
69+
template <typename... Args>
70+
struct IsContainer<std::stack<Args...>> : std::true_type {};
71+
template <typename... Args>
72+
struct IsContainer<std::queue<Args...>> : std::true_type {};
73+
template <typename... Args>
74+
struct IsContainer<std::priority_queue<Args...>> : std::true_type {};
75+
} // namespace IsContainerImpl
76+
77+
// type trait to utilize the implementation type traits as well as decay the
78+
// type
79+
template <typename T>
80+
struct IsContainer {
81+
static constexpr bool const value =
82+
IsContainerImpl::IsContainer<std::decay_t<T>>::value;
83+
};
84+
2585
namespace facebook {
2686
namespace cachelib {
2787

@@ -31,20 +91,22 @@ template <typename PtrType, typename AllocatorContainer>
3191
class PtrCompressor;
3292

3393
// 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.
94+
// compress pointers by storing the tier index, slab index and alloc index
95+
// of the allocation inside the slab. With slab worth kNumSlabBits (22 bits)
96+
// of data, if we have the min allocation size as 64 bytes, that requires
97+
// kNumSlabBits - 6 = 16 bits for storing the alloc index. The tier id
98+
// occupies the 32nd bit only since its value cannot exceed kMaxTiers (2).
99+
// This leaves the remaining (32 -(kNumSlabBits - 6) - 1 bit for tier id) =
100+
// 15 bits for the slab index. Hence we can index 128 GiB of memory in slabs
101+
// per tier and index anything more than 64 byte allocations inside the slab
102+
// using a 32 bit representation.
41103
//
42104
// This CompressedPtr makes decompression fast by staying away from division and
43105
// modulo arithmetic and doing those during the compression time. We most often
44106
// decompress a CompressedPtr than compress a pointer while creating one.
45107
class CACHELIB_PACKED_ATTR CompressedPtr {
46108
public:
47-
using PtrType = uint64_t;
109+
using PtrType = uint32_t;
48110
// Thrift doesn't support unsigned type
49111
using SerializedPtrType = int64_t;
50112

@@ -103,26 +165,28 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
103165
static constexpr unsigned int kNumAllocIdxBits =
104166
Slab::kNumSlabBits - Slab::kMinAllocPower;
105167

106-
// Use topmost 32 bits for TierId
107-
// XXX: optimize
108-
static constexpr unsigned int kNumTierIdxOffset = 32;
168+
// Use the top bit for tier id
169+
static constexpr unsigned int kNumTierIdxOffset = 31;
109170

110171
static constexpr PtrType kAllocIdxMask = ((PtrType)1 << kNumAllocIdxBits) - 1;
111172

112173
// kNumTierIdxBits most significant bits
113-
static constexpr PtrType kTierIdxMask = (((PtrType)1 << kNumTierIdxOffset) - 1) << (NumBits<PtrType>::value - kNumTierIdxOffset);
174+
static constexpr PtrType kTierIdxMask = (PtrType)1 << kNumTierIdxOffset;
114175

115-
// Number of bits for the slab index. This will be the top 16 bits of the
176+
// Number of bits for the slab index. This will be the 16th - 31st bits of the
116177
// compressed ptr.
117178
static constexpr unsigned int kNumSlabIdxBits =
118-
NumBits<PtrType>::value - kNumTierIdxOffset - kNumAllocIdxBits;
179+
kNumTierIdxOffset - kNumAllocIdxBits;
119180

120181
// Compress the given slabIdx and allocIdx into a 64-bit compressed
121182
// pointer.
122-
static PtrType compress(uint32_t slabIdx, uint32_t allocIdx, TierId tid) noexcept {
183+
static PtrType compress(uint32_t slabIdx,
184+
uint32_t allocIdx,
185+
TierId tid) noexcept {
123186
XDCHECK_LE(allocIdx, kAllocIdxMask);
124187
XDCHECK_LT(slabIdx, (1u << kNumSlabIdxBits) - 1);
125-
return (static_cast<uint64_t>(tid) << kNumTierIdxOffset) + (slabIdx << kNumAllocIdxBits) + allocIdx;
188+
return (static_cast<uint64_t>(tid) << kNumTierIdxOffset) +
189+
(slabIdx << kNumAllocIdxBits) + allocIdx;
126190
}
127191

128192
// Get the slab index of the compressed ptr
@@ -153,62 +217,44 @@ class CACHELIB_PACKED_ATTR CompressedPtr {
153217
friend class PtrCompressor;
154218
};
155219

156-
template <typename PtrType, typename AllocatorT>
157-
class SingleTierPtrCompressor {
158-
public:
159-
explicit SingleTierPtrCompressor(const AllocatorT& allocator) noexcept
160-
: allocator_(allocator) {}
161-
162-
const CompressedPtr compress(const PtrType* uncompressed) const {
163-
return allocator_.compress(uncompressed);
164-
}
165-
166-
PtrType* unCompress(const CompressedPtr compressed) const {
167-
return static_cast<PtrType*>(allocator_.unCompress(compressed));
168-
}
169-
170-
bool operator==(const SingleTierPtrCompressor& rhs) const noexcept {
171-
return &allocator_ == &rhs.allocator_;
172-
}
173-
174-
bool operator!=(const SingleTierPtrCompressor& rhs) const noexcept {
175-
return !(*this == rhs);
176-
}
177-
178-
private:
179-
// memory allocator that does the pointer compression.
180-
const AllocatorT& allocator_;
181-
};
182-
183220
template <typename PtrType, typename AllocatorContainer>
184221
class PtrCompressor {
185222
public:
186223
explicit PtrCompressor(const AllocatorContainer& allocators) noexcept
187-
: allocators_(allocators) {}
224+
: allocators_(allocators),
225+
isContainer_(IsContainer<decltype(allocators)>::value) {}
188226

189227
const CompressedPtr compress(const PtrType* uncompressed) const {
190-
if (uncompressed == nullptr)
228+
if (uncompressed == nullptr) {
191229
return CompressedPtr{};
192-
193-
TierId tid;
194-
for (tid = 0; tid < allocators_.size(); tid++) {
195-
if (allocators_[tid]->isMemoryInAllocator(static_cast<const void*>(uncompressed)))
196-
break;
197230
}
198-
199-
auto cptr = allocators_[tid]->compress(uncompressed);
200-
cptr.setTierId(tid);
201-
202-
return cptr;
231+
if (isContainer_) {
232+
TierId tid;
233+
for (tid = 0; tid < allocators_.size(); tid++) {
234+
if (allocators_[tid]->isMemoryInAllocator(
235+
static_cast<const void*>(uncompressed)))
236+
break;
237+
}
238+
auto cptr = allocators_[tid]->compress(uncompressed);
239+
cptr.setTierId(tid);
240+
return cptr;
241+
242+
} else {
243+
return allocators_.compress(uncompressed);
244+
}
203245
}
204246

205247
PtrType* unCompress(const CompressedPtr compressed) const {
206248
if (compressed.isNull()) {
207249
return nullptr;
208250
}
251+
if (isContainer_) {
252+
auto& allocator = *allocators_[compressed.getTierId()];
253+
return static_cast<PtrType*>(allocator.unCompress(compressed));
209254

210-
auto &allocator = *allocators_[compressed.getTierId()];
211-
return static_cast<PtrType*>(allocator.unCompress(compressed));
255+
} else {
256+
return static_cast<PtrType*>(allocators_.unCompress(compressed));
257+
}
212258
}
213259

214260
bool operator==(const PtrCompressor& rhs) const noexcept {
@@ -222,6 +268,8 @@ class PtrCompressor {
222268
private:
223269
// memory allocator that does the pointer compression.
224270
const AllocatorContainer& allocators_;
271+
272+
bool isContainer_{false};
225273
};
226274
} // namespace cachelib
227275
} // namespace facebook

cachelib/allocator/memory/SlabAllocator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ class SlabAllocator {
308308
}
309309

310310
template <typename PtrType>
311-
SingleTierPtrCompressor<PtrType, SlabAllocator> createSingleTierPtrCompressor() const {
312-
return SingleTierPtrCompressor<PtrType, SlabAllocator>(*this);
311+
PtrCompressor<PtrType, SlabAllocator> createPtrCompressor() const {
312+
return PtrCompressor<PtrType, SlabAllocator>(*this);
313313
}
314314

315315
// returns starting address of memory we own.

0 commit comments

Comments
 (0)