Enforce free list memory bound by tracking bytes directly
This commit is contained in:
@@ -260,7 +260,7 @@ static_assert(sizeof(Node4) < kMinChildrenNode4 * kBytesPerKey);
|
|||||||
|
|
||||||
// Bounds memory usage in free list, but does not account for memory for partial
|
// Bounds memory usage in free list, but does not account for memory for partial
|
||||||
// keys.
|
// keys.
|
||||||
template <class T, size_t kMemoryBound = (1 << 20)>
|
template <class T, int64_t kMemoryBound = (1 << 20)>
|
||||||
struct BoundedFreeListAllocator {
|
struct BoundedFreeListAllocator {
|
||||||
static_assert(sizeof(T) >= sizeof(void *));
|
static_assert(sizeof(T) >= sizeof(void *));
|
||||||
static_assert(std::derived_from<T, Node>);
|
static_assert(std::derived_from<T, Node>);
|
||||||
@@ -275,12 +275,15 @@ struct BoundedFreeListAllocator {
|
|||||||
VALGRIND_MAKE_MEM_UNDEFINED(n, sizeof(T));
|
VALGRIND_MAKE_MEM_UNDEFINED(n, sizeof(T));
|
||||||
VALGRIND_MAKE_MEM_DEFINED(&n->partialKeyCapacity,
|
VALGRIND_MAKE_MEM_DEFINED(&n->partialKeyCapacity,
|
||||||
sizeof(n->partialKeyCapacity));
|
sizeof(n->partialKeyCapacity));
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(freeList, sizeof(freeList));
|
||||||
|
memcpy(&freeList, freeList, sizeof(freeList));
|
||||||
|
freeListBytes -= sizeof(T) + n->partialKeyCapacity;
|
||||||
if (n->partialKeyCapacity >= partialKeyCapacity) {
|
if (n->partialKeyCapacity >= partialKeyCapacity) {
|
||||||
memcpy(&freeList, freeList, sizeof(freeList));
|
|
||||||
--freeListSize;
|
|
||||||
return new (n) T;
|
return new (n) T;
|
||||||
|
} else {
|
||||||
|
// The intent is to filter out too-small nodes in the freelist
|
||||||
|
free(n);
|
||||||
}
|
}
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(n, sizeof(T));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *result = new (safe_malloc(sizeof(T) + partialKeyCapacity)) T;
|
auto *result = new (safe_malloc(sizeof(T) + partialKeyCapacity)) T;
|
||||||
@@ -293,12 +296,12 @@ struct BoundedFreeListAllocator {
|
|||||||
--liveAllocations;
|
--liveAllocations;
|
||||||
#endif
|
#endif
|
||||||
static_assert(std::is_trivially_destructible_v<T>);
|
static_assert(std::is_trivially_destructible_v<T>);
|
||||||
if (freeListSize == kMaxFreeListSize) {
|
if (freeListBytes >= kMemoryBound) {
|
||||||
return free(p);
|
return free(p);
|
||||||
}
|
}
|
||||||
memcpy((void *)p, &freeList, sizeof(freeList));
|
memcpy((void *)p, &freeList, sizeof(freeList));
|
||||||
freeList = p;
|
freeList = p;
|
||||||
++freeListSize;
|
freeListBytes += sizeof(T) + p->partialKeyCapacity;
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(freeList, sizeof(T));
|
VALGRIND_MAKE_MEM_NOACCESS(freeList, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,10 +319,10 @@ struct BoundedFreeListAllocator {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int kMaxFreeListSize = kMemoryBound / sizeof(T);
|
int64_t freeListBytes = 0;
|
||||||
int freeListSize = 0;
|
|
||||||
void *freeList = nullptr;
|
void *freeList = nullptr;
|
||||||
#if SHOW_MEMORY
|
#if SHOW_MEMORY
|
||||||
|
// TODO Track partial key bytes
|
||||||
int64_t maxLiveAllocations = 0;
|
int64_t maxLiveAllocations = 0;
|
||||||
int64_t liveAllocations = 0;
|
int64_t liveAllocations = 0;
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user