From 28169450cf65c4ee9d0167d935192a3f8226b29d Mon Sep 17 00:00:00 2001 From: timerix Date: Thu, 8 Jun 2023 21:29:47 +0600 Subject: [PATCH] LinearAllocator improved --- TODO.md | 6 ++- src/Hashtable/KeyValuePair.c | 2 +- src/base/memory/CstdAllocator.c | 2 +- src/base/memory/LinearAllocator.c | 58 ++++++++++++++++++--------- src/base/memory/StackingAllocator.c | 8 ++-- src/base/memory/allocator_base.h | 8 ++-- src/base/memory/allocators.c | 2 +- src/base/memory/allocators.h | 14 +++---- src/base/memory/allocators_internal.h | 2 +- tests/tests.h | 22 +++++----- 10 files changed, 73 insertions(+), 51 deletions(-) diff --git a/TODO.md b/TODO.md index 7d23ecd..a37154d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,14 +1,16 @@ -## General refactoring +## Allocators - replace all malloc() and free() with allocator_alloc() and allocator_free() -- replace allocating constructors with Type_init(var_ptr, ...) +- replace allocating constructors with Type_construct(var_ptr, ...) - replace Struct_free functions with Struct_destruct which will not call free() on the struct ptr - store in resizable structs their buffer allocators and free them with Struct_destruct() - check allocator_free call order +- deal with StackingAllocator_free not freing memory sometimes - replace LinearAllocator with StackingAllocator when possible (in DtsodV24_deserialize) ## Autoarr - store lenght and max_lenght inside the struct instead of calculating them by macro - keep Autoarr_length() and Autoarr_maxLength() to old code compatibility +- toString() ## Hashtable - store hash in KVPair diff --git a/src/Hashtable/KeyValuePair.c b/src/Hashtable/KeyValuePair.c index 3071f39..a6ca36e 100644 --- a/src/Hashtable/KeyValuePair.c +++ b/src/Hashtable/KeyValuePair.c @@ -6,7 +6,7 @@ Autoarr_define(KVPair, false) // proper way to clean a KVP void KVPair_destruct(KVPair p){ - free(p.key); + // free(p.key); Unitype_destruct(&p.value); } void __KVPair_destruct(void* p){ KVPair_destruct(*(KVPair*)p); } diff --git a/src/base/memory/CstdAllocator.c b/src/base/memory/CstdAllocator.c index ef1557d..c729842 100644 --- a/src/base/memory/CstdAllocator.c +++ b/src/base/memory/CstdAllocator.c @@ -1,6 +1,6 @@ #include "allocators_internal.h" -void* CstdAllocator_alloc(allocator_ptr self, size_t size){ +void* CstdAllocator_alloc(allocator_ptr self, alloc_size_t size){ // assert(size>0); return malloc(size); } diff --git a/src/base/memory/LinearAllocator.c b/src/base/memory/LinearAllocator.c index 5129262..cbdf5e2 100644 --- a/src/base/memory/LinearAllocator.c +++ b/src/base/memory/LinearAllocator.c @@ -1,17 +1,27 @@ #include "allocators_internal.h" +#include + + +#define default_chunks_per_allocation 16 +// growing chunk array size +#define new_max_chunks_count ( default_chunks_per_allocation*(self->chunks_count/16 == 0) + \ + default_chunks_per_allocation*add_padding(self->chunks_count/2)/4 ) + +#define default_chunk_size 1024 +// growing chunk size +#define new_chunk_size ( default_chunk_size*(self->chunks_count/16 == 0) + \ + default_chunk_size*add_padding(self->chunks_count/8) ) -#define chunks_per_allocation 16 -#define default_chunk_size add_padding(1024) #define chunk_alloc(SZ, OCCUPIED) (MemoryChunk){ .data=malloc(SZ), .size=SZ, .occupied_size=OCCUPIED } #define curr_chunk (self->chunks+self->curr_chunk_i) -__attribute__ ((noinline)) void* ___alloc_realloc_chunk(LinearAllocator* self, size_t size){ +__attribute__ ((noinline)) void* ___alloc_realloc_chunk(LinearAllocator* self, alloc_size_t alloc_size){ free(curr_chunk->data); - *curr_chunk=chunk_alloc(size, size); + *curr_chunk=chunk_alloc(alloc_size, alloc_size); return curr_chunk->data; } -__attribute__ ((noinline)) void* __alloc_new_chunk(LinearAllocator* self, size_t size){ +__attribute__ ((noinline)) void* __alloc_new_chunk(LinearAllocator* self, alloc_size_t alloc_size){ self->curr_chunk_i++; // next chunk has been already allocated if(self->curr_chunk_i < self->chunks_count) @@ -19,27 +29,27 @@ __attribute__ ((noinline)) void* __alloc_new_chunk(LinearAllocator* self, size_t // self->chunks array is full if(self->chunks_count == self->max_chunks_count){ - self->max_chunks_count += chunks_per_allocation; + self->max_chunks_count = new_max_chunks_count; self->chunks = realloc(self->chunks, sizeof(MemoryChunk) * self->max_chunks_count); } // new chunk allocation self->chunks_count++; - size_t new_chunk_size=default_chunk_size > size ? size : default_chunk_size; - *curr_chunk=chunk_alloc(new_chunk_size, new_chunk_size); + alloc_size_t _new_chunk_size= alloc_size > new_chunk_size ? alloc_size : new_chunk_size; + *curr_chunk=chunk_alloc(_new_chunk_size, alloc_size); return curr_chunk->data; } -void* LinearAllocator_alloc(allocator_ptr _self, size_t size){ +void* LinearAllocator_alloc(allocator_ptr _self, alloc_size_t alloc_size){ // assert(_self!=NULL); - // assert(size>0); + // assert(alloc_size>0); LinearAllocator* self = (LinearAllocator*)_self; - size=add_padding(size); + alloc_size=add_padding(alloc_size); - // aligned size can fit into the current chunk - if(curr_chunk->occupied_size + size <= curr_chunk->size){ + // aligned alloc_size can fit into the current chunk + if(curr_chunk->occupied_size + alloc_size <= curr_chunk->size){ void* data_ptr=curr_chunk->data + curr_chunk->occupied_size; - curr_chunk->occupied_size += size; + curr_chunk->occupied_size += alloc_size; return data_ptr; } // reallocation of current chunk because it is clean @@ -47,11 +57,11 @@ void* LinearAllocator_alloc(allocator_ptr _self, size_t size){ // It is very unefficient operation. // If it happens not only in the first chunk, code have to be refactored assert(self->curr_chunk_i==0); - return ___alloc_realloc_chunk(self, size); + return ___alloc_realloc_chunk(self, alloc_size); } // creation of a new chunk else { - return __alloc_new_chunk(self, size); + return __alloc_new_chunk(self, alloc_size); } } @@ -61,14 +71,22 @@ void LinearAllocator_free(allocator_ptr _self, void* ptr){ void LinearAllocator_destruct(LinearAllocator* self){ // assert(_self!=NULL); - for(u16 chunk_i=0; chunk_i < self->chunks_count; chunk_i++){ + u32 size=0; + u32 oc_size=0; + for(u32 chunk_i=0; chunk_i < self->chunks_count; chunk_i++){ free(self->chunks[chunk_i].data); + size+=self->chunks[chunk_i].size; + oc_size+=self->chunks[chunk_i].occupied_size; } + printf("\e[35m%u/%u\n",oc_size,size); free(self->chunks); self->chunks=NULL; + self->chunks_count=0; + self->curr_chunk_i=0; + self->max_chunks_count=0; } -void LinearAllocator_construct(LinearAllocator* self, size_t starting_size){ +void LinearAllocator_construct(LinearAllocator* self, alloc_size_t starting_size){ assert(self!=NULL); assert(starting_size>0); self->base.alloc_f=LinearAllocator_alloc; @@ -76,8 +94,8 @@ void LinearAllocator_construct(LinearAllocator* self, size_t starting_size){ self->curr_chunk_i=0; self->chunks_count=1; - self->max_chunks_count=chunks_per_allocation; - self->chunks=malloc(sizeof(*self->chunks) * chunks_per_allocation); + self->max_chunks_count=new_max_chunks_count; + self->chunks=malloc(sizeof(MemoryChunk) * new_max_chunks_count); self->chunks[0]=chunk_alloc(starting_size, 0); } diff --git a/src/base/memory/StackingAllocator.c b/src/base/memory/StackingAllocator.c index b8ce0c9..cce1fd5 100644 --- a/src/base/memory/StackingAllocator.c +++ b/src/base/memory/StackingAllocator.c @@ -5,10 +5,10 @@ #define curr_chunk (linear.chunks+linear.curr_chunk_i) typedef struct { - size_t data_size; + alloc_size_t data_size; } AllocationHeader; -void* StackingAllocator_alloc(allocator_ptr _self, size_t size){ +void* StackingAllocator_alloc(allocator_ptr _self, alloc_size_t size){ assert(_self!=NULL); assert(size>0); StackingAllocator* self = (StackingAllocator*)_self; @@ -36,7 +36,7 @@ void StackingAllocator_free(allocator_ptr _self, void* data_ptr){ linear.curr_chunk_i--; } - size_t allocation_size=header_ptr->data_size+sizeof(*header_ptr); + alloc_size_t allocation_size=header_ptr->data_size+sizeof(*header_ptr); // data must fit in chunk assert(allocation_size <= curr_chunk->occupied_size); curr_chunk->occupied_size -= allocation_size; @@ -46,7 +46,7 @@ void StackingAllocator_destruct(StackingAllocator* self){ LinearAllocator_destruct(&self->base); } -void StackingAllocator_construct(StackingAllocator* self, size_t starting_size){ +void StackingAllocator_construct(StackingAllocator* self, alloc_size_t starting_size){ assert(self!=NULL); assert(starting_size>0); LinearAllocator_construct(&linear, starting_size); diff --git a/src/base/memory/allocator_base.h b/src/base/memory/allocator_base.h index 8f1a62a..777882b 100644 --- a/src/base/memory/allocator_base.h +++ b/src/base/memory/allocator_base.h @@ -10,9 +10,11 @@ extern "C" { // MemoryAllocator interface // /////////////////////////////////////////// -typedef struct MemoryAllocator* allocator_ptr; +typedef u32 alloc_size_t; +typedef struct MemoryAllocator MemoryAllocator; +typedef MemoryAllocator* allocator_ptr; -typedef void* (*alloc_t)(allocator_ptr, size_t size); +typedef void* (*alloc_t)(allocator_ptr, alloc_size_t size); typedef void (*free_t)(allocator_ptr, void* ptr); typedef struct MemoryAllocator { @@ -27,7 +29,7 @@ typedef struct MemoryAllocator { #define allocator_destruct(ALLOCATOR) \ ((allocator_ptr)ALLOCATOR)->destruct_f(ALLOCATOR) -void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, size_t data_size); +void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, alloc_size_t data_size); #ifdef __cplusplus } diff --git a/src/base/memory/allocators.c b/src/base/memory/allocators.c index ae92737..02483d3 100644 --- a/src/base/memory/allocators.c +++ b/src/base/memory/allocators.c @@ -1,6 +1,6 @@ #include "memory.h" -void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, size_t data_size) +void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, alloc_size_t data_size) { void* transfered=allocator_alloc(dest, data_size); memcpy(transfered, data, data_size); diff --git a/src/base/memory/allocators.h b/src/base/memory/allocators.h index 27ee401..5f92d5e 100644 --- a/src/base/memory/allocators.h +++ b/src/base/memory/allocators.h @@ -31,19 +31,19 @@ void CstdAllocator_construct(CstdAllocator* self); typedef struct MemoryChunk { void* data; - size_t size; - size_t occupied_size; /* free memory position in the current chunk. */ + alloc_size_t size; + alloc_size_t occupied_size; /* free memory position in the current chunk. */ } MemoryChunk; STRUCT(LinearAllocator, MemoryAllocator base; MemoryChunk* chunks; /* MemoryChunk[max_chunks_count] */ - u16 chunks_count; /* allocated chunks */ - u16 max_chunks_count; /* chunks that can be allocated without reallocating .chunks */ - u16 curr_chunk_i; /* index of current chunk in .chunks, can be < .chunks_count */ + u32 chunks_count; /* allocated chunks */ + u32 max_chunks_count; /* chunks that can be allocated without reallocating .chunks */ + u32 curr_chunk_i; /* index of current chunk in .chunks, can be < .chunks_count */ ); -void LinearAllocator_construct(LinearAllocator* self, size_t starting_size); +void LinearAllocator_construct(LinearAllocator* self, alloc_size_t starting_size); void LinearAllocator_destruct(LinearAllocator* self); @@ -59,7 +59,7 @@ STRUCT(StackingAllocator, u32 allocations_count; ); -void StackingAllocator_construct(StackingAllocator* self, size_t starting_size); +void StackingAllocator_construct(StackingAllocator* self, alloc_size_t starting_size); void StackingAllocator_destruct(StackingAllocator* self); diff --git a/src/base/memory/allocators_internal.h b/src/base/memory/allocators_internal.h index 2205d63..cecd9b6 100644 --- a/src/base/memory/allocators_internal.h +++ b/src/base/memory/allocators_internal.h @@ -1,4 +1,4 @@ #include #include "memory.h" -void* LinearAllocator_alloc(allocator_ptr _self, size_t size); +void* LinearAllocator_alloc(allocator_ptr _self, alloc_size_t size); diff --git a/tests/tests.h b/tests/tests.h index 4e5b069..2b57815 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -24,19 +24,19 @@ void test_type_system(); static inline void test_all(){ kprintf("\e[97mkerep tests are starting!\n"); optime(__func__, 1, - test_type_system(); - test_allocators(); - test_kprint_colors(); - test_kprint(); - test_safethrow(); - test_rng_algorithms(); - test_cptr(); - test_string(); + // test_type_system(); + // test_allocators(); + // test_kprint_colors(); + // test_kprint(); + // test_safethrow(); + // test_rng_algorithms(); + // test_cptr(); + // test_string(); // test_searchtree(); - test_autoarr(); - test_autoarrVsVector(); + // test_autoarr(); + // test_autoarrVsVector(); // test_hash_functions(); /* long test */ - // test_hashtable(); + test_hashtable(); // test_dtsod(); kprintf("\e[96m--------------------------------------\e[0m\n"); );