Enforce free list memory bound by tracking bytes directly

This commit is contained in:
2024-03-08 21:46:35 -08:00
parent 504a93bb10
commit e32bea7b29

View File

@@ -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