Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/small obj allocator #3301

Draft
wants to merge 2 commits into
base: community
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/deluge/memory/general_memory_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ GeneralMemoryAllocator::GeneralMemoryAllocator() {
lock = false;

regions[MEMORY_REGION_STEALABLE].setup(emptySpacesMemory, sizeof(emptySpacesMemory), (uint32_t)&__sdram_bss_end,
EXTERNAL_MEMORY_END - RESERVED_EXTERNAL_ALLOCATOR);
EXTERNAL_MEMORY_END - RESERVED_EXTERNAL_ALLOCATOR, &cacheManager);
regions[MEMORY_REGION_EXTERNAL].setup(emptySpacesMemoryGeneral, sizeof(emptySpacesMemoryGeneral),
EXTERNAL_MEMORY_END - RESERVED_EXTERNAL_ALLOCATOR, EXTERNAL_MEMORY_END);
EXTERNAL_MEMORY_END - RESERVED_EXTERNAL_ALLOCATOR, EXTERNAL_MEMORY_END,
nullptr);
regions[MEMORY_REGION_INTERNAL].setup(emptySpacesMemoryInternal, sizeof(emptySpacesMemoryInternal),
(uint32_t)&__heap_start, (uint32_t)&program_stack_start);
(uint32_t)&__heap_start, (uint32_t)&program_stack_start, nullptr);

#if ALPHA_OR_BETA_VERSION
regions[MEMORY_REGION_STEALABLE].name = "stealable";
Expand Down
3 changes: 2 additions & 1 deletion src/deluge/memory/general_memory_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ class GeneralMemoryAllocator {
void putStealableInAppropriateQueue(Stealable* stealable);

MemoryRegion regions[NUM_MEMORY_REGIONS];

// only used for managing stealables (audio files that we could deallocate and re load from sd later if needed)
CacheManager cacheManager;
bool lock;

static GeneralMemoryAllocator& get() {
Expand Down
23 changes: 11 additions & 12 deletions src/deluge/memory/memory_region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@
#endif

MemoryRegion::MemoryRegion() : emptySpaces(sizeof(EmptySpaceRecord)) {
numAllocations = 0;
}

void MemoryRegion::setup(void* emptySpacesMemory, int32_t emptySpacesMemorySize, uint32_t regionBegin,
uint32_t regionEnd) {
uint32_t regionEnd, CacheManager* cacheManager) {
emptySpaces.setStaticMemory(emptySpacesMemory, emptySpacesMemorySize);
// bit of a hack - the allocations start with a 4 byte type+size header, this ensures the
// resulting allocations are still aligned to 16 bytes (which should generally be fine for anything?)
Expand All @@ -53,20 +52,20 @@ void MemoryRegion::setup(void* emptySpacesMemory, int32_t emptySpacesMemorySize,
EmptySpaceRecord* firstRecord = (EmptySpaceRecord*)emptySpaces.getElementAddress(0);
firstRecord->length = memorySizeWithoutHeaders;
firstRecord->address = regionBegin + 8;
pivot = 512;
cache_manager_ = cacheManager;
}

uint32_t MemoryRegion::padSize(uint32_t requiredSize) {
requiredSize += 8; // dirty hack - we need the size with its headers to be aligned so we'll add it here then
// subtract 8 afterwards
if (requiredSize < minAlign) {
requiredSize = minAlign;
if (requiredSize < minAlign_) {
requiredSize = minAlign_;
}
else {
int extraSize = 0;
while (requiredSize > maxAlign) {
extraSize += maxAlign;
requiredSize -= maxAlign;
while (requiredSize > maxAlign_) {
extraSize += maxAlign_;
requiredSize -= maxAlign_;
}
// if it's not a power of 2 go up to the next power of 2
if (!((requiredSize & (requiredSize - 1)) == 0)) {
Expand Down Expand Up @@ -280,7 +279,7 @@ inline void MemoryRegion::markSpaceAsEmpty(uint32_t address, uint32_t spaceSize,

void* MemoryRegion::alloc(uint32_t requiredSize, bool makeStealable, void* thingNotToStealFrom) {
requiredSize = padSize(requiredSize);
bool large = requiredSize > pivot;
bool large = requiredSize > pivot_;
// set a minimum size requiredSize = padSize(requiredSize);
int32_t allocatedSize;
uint32_t allocatedAddress;
Expand Down Expand Up @@ -310,7 +309,7 @@ void* MemoryRegion::alloc(uint32_t requiredSize, bool makeStealable, void* thing
FREEZE_WITH_ERROR("M003");
}
else {
if (extraSpaceSizeWithoutItsHeaders <= minAlign) {
if (extraSpaceSizeWithoutItsHeaders <= minAlign_) {
emptySpaces.deleteAtIndex(i);
}
else {
Expand Down Expand Up @@ -375,7 +374,7 @@ void* MemoryRegion::alloc(uint32_t requiredSize, bool makeStealable, void* thing
// Or if no empty space big enough, try stealing some memory
else {
noEmptySpace:
allocatedAddress = cache_manager_.ReclaimMemory(*this, requiredSize, thingNotToStealFrom, &allocatedSize);
allocatedAddress = cache_manager_->ReclaimMemory(*this, requiredSize, thingNotToStealFrom, &allocatedSize);
if (!allocatedAddress) {
#if ALPHA_OR_BETA_VERSION
if (name) {
Expand All @@ -400,7 +399,7 @@ void* MemoryRegion::alloc(uint32_t requiredSize, bool makeStealable, void* thing

// See if there was some extra space left over
int32_t extraSpaceSizeWithoutItsHeaders = allocatedSize - requiredSize - 8;
if (requiredSize && extraSpaceSizeWithoutItsHeaders > minAlign) {
if (requiredSize && extraSpaceSizeWithoutItsHeaders > minAlign_) {
allocatedSize = requiredSize;
markSpaceAsEmpty(allocatedAddress + allocatedSize + 8, extraSpaceSizeWithoutItsHeaders, false, false);
}
Expand Down
32 changes: 22 additions & 10 deletions src/deluge/memory/memory_region.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "memory/cache_manager.h"
#include "util/container/array/ordered_resizeable_array_with_multi_word_key.h"

#include <util/exceptions.h>

struct EmptySpaceRecord {
uint32_t length;
uint32_t address;
Expand All @@ -36,15 +38,16 @@ struct NeighbouringMemoryGrabAttemptResult {

#define SPACE_TYPE_MASK 0xC0000000u
#define SPACE_SIZE_MASK 0x3FFFFFFFu

constexpr int32_t maxAlign = 1 << 12;
constexpr int32_t minAlign = 64;

constexpr size_t max_align_big = 1 << 12;
constexpr size_t min_align_big = 64;
constexpr size_t pivot_big = 512;
class MemoryRegion {
public:
MemoryRegion();
void setup(void* emptySpacesMemory, int32_t emptySpacesMemorySize, uint32_t regionBegin, uint32_t regionEnd);
void setup(void* emptySpacesMemory, int32_t emptySpacesMemorySize, uint32_t regionBegin, uint32_t regionEnd,
CacheManager* cacheManager);
void* alloc(uint32_t requiredSize, bool makeStealable, void* thingNotToStealFrom);
size_t nallocx(size_t size) { return padSize(size); }
uint32_t shortenRight(void* address, uint32_t newSize);
uint32_t shortenLeft(void* address, uint32_t amountToShorten, uint32_t numBytesToMoveRightIfSuccessful = 0);
void extend(void* address, uint32_t minAmountToExtend, uint32_t idealAmountToExtend,
Expand All @@ -55,9 +58,13 @@ class MemoryRegion {

uint32_t start;
uint32_t end;
uint32_t numAllocations;
uint32_t pivot;
CacheManager& cache_manager() { return cache_manager_; }

CacheManager& cache_manager() {
if (cache_manager_) {
return *cache_manager_;
}
throw deluge::exception::NO_CACHE_FOR_REGION;
}

#if ALPHA_OR_BETA_VERSION
char const* name; // For debugging messages only.
Expand All @@ -66,8 +73,13 @@ class MemoryRegion {

private:
friend class CacheManager;
CacheManager cache_manager_;

// manages "stealables" for a memory region, only used in external stealable region
CacheManager* cache_manager_;
uint32_t numAllocations_{0};
uint32_t pivot_{pivot_big}; // items smaller than pivot allocate to left, larger to right
size_t maxAlign_ = max_align_big;
// not size_t, it needs to be compared to results of pointer subtractions that can be negative
ptrdiff_t minAlign_ = min_align_big;
void markSpaceAsEmpty(uint32_t spaceStart, uint32_t spaceSize, bool mayLookLeft = true, bool mayLookRight = true);
NeighbouringMemoryGrabAttemptResult
attemptToGrabNeighbouringMemory(void* originalSpaceAddress, int32_t originalSpaceSize, int32_t minAmountToExtend,
Expand Down
1 change: 1 addition & 0 deletions src/deluge/util/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ namespace deluge {
enum class exception {
BAD_ALLOC,
BAD_RELEASE,
NO_CACHE_FOR_REGION,
};
}
5 changes: 4 additions & 1 deletion tests/32bit_unit_tests/memory_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ bool testAllocationStructure(void* address, uint32_t size, uint32_t spaceType) {

TEST_GROUP(MemoryAllocation) {
MemoryRegion memreg;
CacheManager cm;
// this will hold the address of the stealable test vtable
uint32_t empty_spaze_size = sizeof(EmptySpaceRecord) * 512;
void* emptySpacesMemory = malloc(empty_spaze_size);
Expand All @@ -92,9 +93,10 @@ TEST_GROUP(MemoryAllocation) {
// this runs before each test to re intitialize the memory
void setup() {
nSteals = 0;
auto newCM = new (&cm) CacheManager();
memset(raw_mem, 0, mem_size);
memset(emptySpacesMemory, 0, empty_spaze_size);
memreg.setup(emptySpacesMemory, empty_spaze_size, (uint32_t)raw_mem, (uint32_t)raw_mem + mem_size);
memreg.setup(emptySpacesMemory, empty_spaze_size, (uint32_t)raw_mem, (uint32_t)raw_mem + mem_size, newCM);
}
};

Expand Down Expand Up @@ -319,6 +321,7 @@ TEST(MemoryAllocation, stealableAllocations) {
void* testalloc = memreg.alloc(size, true, NULL);
totalAllocated += size;
StealableTest* stealable = new (testalloc) StealableTest();

memreg.cache_manager().QueueForReclamation(StealableQueue{0}, stealable);
vtableAddress = *(uint32_t*)testalloc;
actualSize = getAllocatedSize(testalloc);
Expand Down
Loading