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 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
|
- 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()
|
- store in resizable structs their buffer allocators and free them with Struct_destruct()
|
||||||
- check allocator_free call order
|
- check allocator_free call order
|
||||||
|
- deal with StackingAllocator_free not freing memory sometimes
|
||||||
- replace LinearAllocator with StackingAllocator when possible (in DtsodV24_deserialize)
|
- replace LinearAllocator with StackingAllocator when possible (in DtsodV24_deserialize)
|
||||||
|
|
||||||
## Autoarr
|
## Autoarr
|
||||||
- store lenght and max_lenght inside the struct instead of calculating them by macro
|
- store lenght and max_lenght inside the struct instead of calculating them by macro
|
||||||
- keep Autoarr_length() and Autoarr_maxLength() to old code compatibility
|
- keep Autoarr_length() and Autoarr_maxLength() to old code compatibility
|
||||||
|
- toString()
|
||||||
|
|
||||||
## Hashtable
|
## Hashtable
|
||||||
- store hash in KVPair
|
- store hash in KVPair
|
||||||
|
|||||||
@ -6,7 +6,7 @@ Autoarr_define(KVPair, false)
|
|||||||
|
|
||||||
// proper way to clean a KVP
|
// proper way to clean a KVP
|
||||||
void KVPair_destruct(KVPair p){
|
void KVPair_destruct(KVPair p){
|
||||||
free(p.key);
|
// free(p.key);
|
||||||
Unitype_destruct(&p.value);
|
Unitype_destruct(&p.value);
|
||||||
}
|
}
|
||||||
void __KVPair_destruct(void* p){ KVPair_destruct(*(KVPair*)p); }
|
void __KVPair_destruct(void* p){ KVPair_destruct(*(KVPair*)p); }
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include "allocators_internal.h"
|
#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);
|
// assert(size>0);
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,27 @@
|
|||||||
#include "allocators_internal.h"
|
#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 chunk_alloc(SZ, OCCUPIED) (MemoryChunk){ .data=malloc(SZ), .size=SZ, .occupied_size=OCCUPIED }
|
||||||
#define curr_chunk (self->chunks+self->curr_chunk_i)
|
#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);
|
free(curr_chunk->data);
|
||||||
*curr_chunk=chunk_alloc(size, size);
|
*curr_chunk=chunk_alloc(alloc_size, alloc_size);
|
||||||
return curr_chunk->data;
|
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++;
|
self->curr_chunk_i++;
|
||||||
// next chunk has been already allocated
|
// next chunk has been already allocated
|
||||||
if(self->curr_chunk_i < self->chunks_count)
|
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
|
// self->chunks array is full
|
||||||
if(self->chunks_count == self->max_chunks_count){
|
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);
|
self->chunks = realloc(self->chunks, sizeof(MemoryChunk) * self->max_chunks_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// new chunk allocation
|
// new chunk allocation
|
||||||
self->chunks_count++;
|
self->chunks_count++;
|
||||||
size_t new_chunk_size=default_chunk_size > size ? size : default_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, new_chunk_size);
|
*curr_chunk=chunk_alloc(_new_chunk_size, alloc_size);
|
||||||
return curr_chunk->data;
|
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(_self!=NULL);
|
||||||
// assert(size>0);
|
// assert(alloc_size>0);
|
||||||
LinearAllocator* self = (LinearAllocator*)_self;
|
LinearAllocator* self = (LinearAllocator*)_self;
|
||||||
size=add_padding(size);
|
alloc_size=add_padding(alloc_size);
|
||||||
|
|
||||||
// aligned size can fit into the current chunk
|
// aligned alloc_size can fit into the current chunk
|
||||||
if(curr_chunk->occupied_size + size <= curr_chunk->size){
|
if(curr_chunk->occupied_size + alloc_size <= curr_chunk->size){
|
||||||
void* data_ptr=curr_chunk->data + curr_chunk->occupied_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;
|
return data_ptr;
|
||||||
}
|
}
|
||||||
// reallocation of current chunk because it is clean
|
// 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.
|
// It is very unefficient operation.
|
||||||
// If it happens not only in the first chunk, code have to be refactored
|
// If it happens not only in the first chunk, code have to be refactored
|
||||||
assert(self->curr_chunk_i==0);
|
assert(self->curr_chunk_i==0);
|
||||||
return ___alloc_realloc_chunk(self, size);
|
return ___alloc_realloc_chunk(self, alloc_size);
|
||||||
}
|
}
|
||||||
// creation of a new chunk
|
// creation of a new chunk
|
||||||
else {
|
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){
|
void LinearAllocator_destruct(LinearAllocator* self){
|
||||||
// assert(_self!=NULL);
|
// 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);
|
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);
|
free(self->chunks);
|
||||||
self->chunks=NULL;
|
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(self!=NULL);
|
||||||
assert(starting_size>0);
|
assert(starting_size>0);
|
||||||
self->base.alloc_f=LinearAllocator_alloc;
|
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->curr_chunk_i=0;
|
||||||
self->chunks_count=1;
|
self->chunks_count=1;
|
||||||
self->max_chunks_count=chunks_per_allocation;
|
self->max_chunks_count=new_max_chunks_count;
|
||||||
self->chunks=malloc(sizeof(*self->chunks) * chunks_per_allocation);
|
self->chunks=malloc(sizeof(MemoryChunk) * new_max_chunks_count);
|
||||||
self->chunks[0]=chunk_alloc(starting_size, 0);
|
self->chunks[0]=chunk_alloc(starting_size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
#define curr_chunk (linear.chunks+linear.curr_chunk_i)
|
#define curr_chunk (linear.chunks+linear.curr_chunk_i)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t data_size;
|
alloc_size_t data_size;
|
||||||
} AllocationHeader;
|
} AllocationHeader;
|
||||||
|
|
||||||
void* StackingAllocator_alloc(allocator_ptr _self, size_t size){
|
void* StackingAllocator_alloc(allocator_ptr _self, alloc_size_t size){
|
||||||
assert(_self!=NULL);
|
assert(_self!=NULL);
|
||||||
assert(size>0);
|
assert(size>0);
|
||||||
StackingAllocator* self = (StackingAllocator*)_self;
|
StackingAllocator* self = (StackingAllocator*)_self;
|
||||||
@ -36,7 +36,7 @@ void StackingAllocator_free(allocator_ptr _self, void* data_ptr){
|
|||||||
linear.curr_chunk_i--;
|
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
|
// data must fit in chunk
|
||||||
assert(allocation_size <= curr_chunk->occupied_size);
|
assert(allocation_size <= curr_chunk->occupied_size);
|
||||||
curr_chunk->occupied_size -= allocation_size;
|
curr_chunk->occupied_size -= allocation_size;
|
||||||
@ -46,7 +46,7 @@ void StackingAllocator_destruct(StackingAllocator* self){
|
|||||||
LinearAllocator_destruct(&self->base);
|
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(self!=NULL);
|
||||||
assert(starting_size>0);
|
assert(starting_size>0);
|
||||||
LinearAllocator_construct(&linear, starting_size);
|
LinearAllocator_construct(&linear, starting_size);
|
||||||
|
|||||||
@ -10,9 +10,11 @@ extern "C" {
|
|||||||
// MemoryAllocator interface //
|
// 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 void (*free_t)(allocator_ptr, void* ptr);
|
||||||
|
|
||||||
typedef struct MemoryAllocator {
|
typedef struct MemoryAllocator {
|
||||||
@ -27,7 +29,7 @@ typedef struct MemoryAllocator {
|
|||||||
#define allocator_destruct(ALLOCATOR) \
|
#define allocator_destruct(ALLOCATOR) \
|
||||||
((allocator_ptr)ALLOCATOR)->destruct_f(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include "memory.h"
|
#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);
|
void* transfered=allocator_alloc(dest, data_size);
|
||||||
memcpy(transfered, data, data_size);
|
memcpy(transfered, data, data_size);
|
||||||
|
|||||||
@ -31,19 +31,19 @@ void CstdAllocator_construct(CstdAllocator* self);
|
|||||||
|
|
||||||
typedef struct MemoryChunk {
|
typedef struct MemoryChunk {
|
||||||
void* data;
|
void* data;
|
||||||
size_t size;
|
alloc_size_t size;
|
||||||
size_t occupied_size; /* free memory position in the current chunk. */
|
alloc_size_t occupied_size; /* free memory position in the current chunk. */
|
||||||
} MemoryChunk;
|
} MemoryChunk;
|
||||||
|
|
||||||
STRUCT(LinearAllocator,
|
STRUCT(LinearAllocator,
|
||||||
MemoryAllocator base;
|
MemoryAllocator base;
|
||||||
MemoryChunk* chunks; /* MemoryChunk[max_chunks_count] */
|
MemoryChunk* chunks; /* MemoryChunk[max_chunks_count] */
|
||||||
u16 chunks_count; /* allocated chunks */
|
u32 chunks_count; /* allocated chunks */
|
||||||
u16 max_chunks_count; /* chunks that can be allocated without reallocating .chunks */
|
u32 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 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);
|
void LinearAllocator_destruct(LinearAllocator* self);
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ STRUCT(StackingAllocator,
|
|||||||
u32 allocations_count;
|
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);
|
void StackingAllocator_destruct(StackingAllocator* self);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "memory.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(){
|
static inline void test_all(){
|
||||||
kprintf("\e[97mkerep tests are starting!\n");
|
kprintf("\e[97mkerep tests are starting!\n");
|
||||||
optime(__func__, 1,
|
optime(__func__, 1,
|
||||||
test_type_system();
|
// test_type_system();
|
||||||
test_allocators();
|
// test_allocators();
|
||||||
test_kprint_colors();
|
// test_kprint_colors();
|
||||||
test_kprint();
|
// test_kprint();
|
||||||
test_safethrow();
|
// test_safethrow();
|
||||||
test_rng_algorithms();
|
// test_rng_algorithms();
|
||||||
test_cptr();
|
// test_cptr();
|
||||||
test_string();
|
// test_string();
|
||||||
// test_searchtree();
|
// test_searchtree();
|
||||||
test_autoarr();
|
// test_autoarr();
|
||||||
test_autoarrVsVector();
|
// test_autoarrVsVector();
|
||||||
// test_hash_functions(); /* long test */
|
// test_hash_functions(); /* long test */
|
||||||
// test_hashtable();
|
test_hashtable();
|
||||||
// test_dtsod();
|
// test_dtsod();
|
||||||
kprintf("\e[96m--------------------------------------\e[0m\n");
|
kprintf("\e[96m--------------------------------------\e[0m\n");
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user