LinearAllocator improved
This commit is contained in:
parent
8d36fd8042
commit
28169450cf
6
TODO.md
6
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
|
||||
|
||||
@ -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); }
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user