Skip to content

Commit

Permalink
no align allocator
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriyMusatkin committed Oct 23, 2023
1 parent f705c61 commit bfbabc1
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 4 deletions.
25 changes: 25 additions & 0 deletions include/aws/common/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@
AWS_PUSH_SANE_WARNING_LEVEL
AWS_EXTERN_C_BEGIN

/*
* Quick guide to allocators:
* CRT offers several flavours of allocators:
* - default: basic allocator, targeted toward most common use case. behavior
* can change over time. Current default aligns small allocations on 8 byte
* boundary and big buffers on 32/64 byte (system dependent) boundary.
* Aligned mem can improve perf on some operations, like memcpy or hashes.
* Depending on a system, can result in higher peak memory count in heavy
* acquire/free scenarios (ex. s3), due to memory fragmentation related to how
* aligned allocators work (overallocate, find aligned offset, release extra memory)
* - no_align: similar to default, but does not do any alignment. In practice,
* has smaller peak memory footprint than default allocator, at the cost of
* potentially being slower.
* - wrapped_cf: wraps MacOS's Security Framework allocator.
* - mem_tracer: wraps any allocator and provides tracing functionality to allocations
* - small_block_allocator: pools smaller allocations into preallocated buckets.
* Not actively maintained. Avoid if possible.
*/

/* Allocator structure. An instance of this will be passed around for anything needing memory allocation */
struct aws_allocator {
void *(*mem_acquire)(struct aws_allocator *allocator, size_t size);
Expand All @@ -32,6 +51,12 @@ bool aws_allocator_is_valid(const struct aws_allocator *alloc);
AWS_COMMON_API
struct aws_allocator *aws_default_allocator(void);

/*
* Vanilla allocator. No extra logic on top of system allocator.
*/
AWS_COMMON_API
struct aws_allocator *aws_no_align_allocator(void);

#ifdef __MACH__
/* Avoid pulling in CoreFoundation headers in a header file. */
struct __CFAllocator; /* NOLINT(bugprone-reserved-identifier) */
Expand Down
51 changes: 51 additions & 0 deletions source/allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,57 @@ struct aws_allocator *aws_default_allocator(void) {
return &default_allocator;
}

static void *s_no_align_malloc(struct aws_allocator *allocator, size_t size) {
(void)allocator;
void *result = malloc(size);
AWS_PANIC_OOM(result, "posix_memalign failed to allocate memory");
return result;
}

static void s_no_align_free(struct aws_allocator *allocator, void *ptr) {
(void)allocator;
free(ptr);
}

static void *s_no_align_realloc(struct aws_allocator *allocator, void *ptr, size_t oldsize, size_t newsize) {
(void)allocator;
(void)oldsize;
AWS_FATAL_PRECONDITION(newsize);

if (newsize <= oldsize) {
return ptr;
}

/* newsize is > oldsize, need more memory */
void *new_mem = s_no_align_malloc(allocator, newsize);
AWS_PANIC_OOM(new_mem, "Unhandled OOM encountered in s_default_malloc");

if (ptr) {
memcpy(new_mem, ptr, oldsize);
s_no_align_free(allocator, ptr);
}

return new_mem;
}

static void *s_no_align_calloc(struct aws_allocator *allocator, size_t num, size_t size) {
(void)allocator;
void *mem = calloc(num, size);
AWS_PANIC_OOM(mem, "Unhandled OOM encountered in s_default_malloc");
return mem;
}

static struct aws_allocator no_align_allocator = {
.mem_acquire = s_no_align_malloc,
.mem_release = s_no_align_free,
.mem_realloc = s_no_align_realloc,
.mem_calloc = s_no_align_calloc,
};

struct aws_allocator *aws_no_align_allocator(void) {
return &no_align_allocator;
}

void *aws_mem_acquire(struct aws_allocator *allocator, size_t size) {
AWS_FATAL_PRECONDITION(allocator != NULL);
AWS_FATAL_PRECONDITION(allocator->mem_acquire != NULL);
Expand Down
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ add_test_case(sba_churn)
add_test_case(sba_metrics)
add_test_case(default_threaded_reallocs)
add_test_case(default_threaded_allocs_and_frees)
add_test_case(no_align_threaded_reallocs)
add_test_case(no_align_threaded_allocs_and_frees)

add_test_case(test_memtrace_none)
add_test_case(test_memtrace_count)
Expand Down
42 changes: 38 additions & 4 deletions tests/alloc_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ static int s_test_alloc_nothing_fn(struct aws_allocator *allocator, void *ctx) {
(void)allocator;
(void)ctx;

struct aws_allocator test_allocator = {.mem_acquire = s_test_alloc_acquire,
.mem_release = s_test_alloc_release,
.mem_realloc = s_test_realloc,
.mem_calloc = s_test_calloc};
struct aws_allocator test_allocator = {
.mem_acquire = s_test_alloc_acquire,
.mem_release = s_test_alloc_release,
.mem_realloc = s_test_realloc,
.mem_calloc = s_test_calloc};

/* realloc should handle the case correctly, return null, and free the memory */
void *p = aws_mem_acquire(&test_allocator, 12);
Expand Down Expand Up @@ -346,3 +347,36 @@ static int s_default_threaded_allocs_and_frees(struct aws_allocator *allocator,
return 0;
}
AWS_TEST_CASE(default_threaded_allocs_and_frees, s_default_threaded_allocs_and_frees)

/*
* No align allocator tests.
*/
static int s_no_align_threaded_reallocs(struct aws_allocator *allocator, void *ctx) {
(void)allocator;
(void)ctx;
srand(15);

struct aws_allocator *alloc = aws_mem_tracer_new(aws_no_align_allocator(), NULL, AWS_MEMTRACE_STACKS, 8);

s_thread_test(alloc, s_threaded_realloc_worker, alloc);

aws_mem_tracer_destroy(alloc);

return 0;
}
AWS_TEST_CASE(no_align_threaded_reallocs, s_no_align_threaded_reallocs)

static int s_no_align_threaded_allocs_and_frees(struct aws_allocator *allocator, void *ctx) {
(void)allocator;
(void)ctx;
srand(99);

struct aws_allocator *alloc = aws_mem_tracer_new(aws_no_align_allocator(), NULL, AWS_MEMTRACE_STACKS, 8);

s_thread_test(alloc, s_threaded_alloc_worker, alloc);

aws_mem_tracer_destroy(alloc);

return 0;
}
AWS_TEST_CASE(no_align_threaded_allocs_and_frees, s_no_align_threaded_allocs_and_frees)

0 comments on commit bfbabc1

Please sign in to comment.