LinearAllocator improved

This commit is contained in:
timerix 2023-06-08 21:29:47 +06:00
parent 8d36fd8042
commit 28169450cf
10 changed files with 73 additions and 51 deletions

View File

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

View File

@ -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); }

View File

@ -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);
}

View File

@ -1,17 +1,27 @@
#include "allocators_internal.h"
#include <stdio.h>
#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);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
#include <assert.h>
#include "memory.h"
void* LinearAllocator_alloc(allocator_ptr _self, size_t size);
void* LinearAllocator_alloc(allocator_ptr _self, alloc_size_t size);

View File

@ -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");
);