diff --git a/include/aws/common/allocator.h b/include/aws/common/allocator.h index d4880f846..eff552b43 100644 --- a/include/aws/common/allocator.h +++ b/include/aws/common/allocator.h @@ -15,16 +15,14 @@ AWS_EXTERN_C_BEGIN /* * Quick guide to allocators: * CRT offers several flavours of allocators: - * - default: basic allocator, targeted toward most common use case. behavior + * - default: basic allocator that invokes system one directly. + * - aligned: 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. + * aligned allocators work (over allocate, find aligned offset, release extra memory) * - 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. @@ -52,10 +50,11 @@ AWS_COMMON_API struct aws_allocator *aws_default_allocator(void); /* - * Vanilla allocator. No extra logic on top of system allocator. + * Allocator that align small allocations on 8 byte boundary and big allocations + * on 32/64 byte boundary. */ AWS_COMMON_API -struct aws_allocator *aws_no_align_allocator(void); +struct aws_allocator *aws_aligned_allocator(void); #ifdef __MACH__ /* Avoid pulling in CoreFoundation headers in a header file. */ diff --git a/source/allocator.c b/source/allocator.c index c07c58336..02847b1ae 100644 --- a/source/allocator.c +++ b/source/allocator.c @@ -34,7 +34,7 @@ bool aws_allocator_is_valid(const struct aws_allocator *alloc) { return alloc && AWS_OBJECT_PTR_IS_READABLE(alloc) && alloc->mem_acquire && alloc->mem_release; } -static void *s_default_malloc(struct aws_allocator *allocator, size_t size) { +static void *s_aligned_malloc(struct aws_allocator *allocator, size_t size) { (void)allocator; /* larger allocations should be aligned so that AVX and friends can avoid * the extra preamble during unaligned versions of memcpy/memset on big buffers @@ -62,7 +62,7 @@ static void *s_default_malloc(struct aws_allocator *allocator, size_t size) { #endif } -static void s_default_free(struct aws_allocator *allocator, void *ptr) { +static void s_aligned_free(struct aws_allocator *allocator, void *ptr) { (void)allocator; #if !defined(_WIN32) free(ptr); @@ -71,7 +71,7 @@ static void s_default_free(struct aws_allocator *allocator, void *ptr) { #endif } -static void *s_default_realloc(struct aws_allocator *allocator, void *ptr, size_t oldsize, size_t newsize) { +static void *s_aligned_realloc(struct aws_allocator *allocator, void *ptr, size_t oldsize, size_t newsize) { (void)allocator; (void)oldsize; AWS_FATAL_PRECONDITION(newsize); @@ -82,12 +82,12 @@ static void *s_default_realloc(struct aws_allocator *allocator, void *ptr, size_ } /* newsize is > oldsize, need more memory */ - void *new_mem = s_default_malloc(allocator, newsize); - AWS_PANIC_OOM(new_mem, "Unhandled OOM encountered in s_default_malloc"); + void *new_mem = s_aligned_malloc(allocator, newsize); + AWS_PANIC_OOM(new_mem, "Unhandled OOM encountered in s_aligned_malloc"); if (ptr) { memcpy(new_mem, ptr, oldsize); - s_default_free(allocator, ptr); + s_aligned_free(allocator, ptr); } return new_mem; @@ -99,37 +99,26 @@ static void *s_default_realloc(struct aws_allocator *allocator, void *ptr, size_ #endif } -static void *s_default_calloc(struct aws_allocator *allocator, size_t num, size_t size) { - void *mem = s_default_malloc(allocator, num * size); - AWS_PANIC_OOM(mem, "Unhandled OOM encountered in s_default_malloc"); +static void *s_aligned_calloc(struct aws_allocator *allocator, size_t num, size_t size) { + void *mem = s_aligned_malloc(allocator, num * size); + AWS_PANIC_OOM(mem, "Unhandled OOM encountered in s_aligned_calloc"); memset(mem, 0, num * size); return mem; } -static struct aws_allocator default_allocator = { - .mem_acquire = s_default_malloc, - .mem_release = s_default_free, - .mem_realloc = s_default_realloc, - .mem_calloc = s_default_calloc, -}; - -struct aws_allocator *aws_default_allocator(void) { - return &default_allocator; -} - -static void *s_no_align_malloc(struct aws_allocator *allocator, size_t size) { +static void *s_non_aligned_malloc(struct aws_allocator *allocator, size_t size) { (void)allocator; void *result = malloc(size); - AWS_PANIC_OOM(result, "posix_memalign failed to allocate memory"); + AWS_PANIC_OOM(result, "malloc failed to allocate memory"); return result; } -static void s_no_align_free(struct aws_allocator *allocator, void *ptr) { +static void s_non_aligned_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) { +static void *s_non_aligned_realloc(struct aws_allocator *allocator, void *ptr, size_t oldsize, size_t newsize) { (void)allocator; (void)oldsize; AWS_FATAL_PRECONDITION(newsize); @@ -139,33 +128,44 @@ static void *s_no_align_realloc(struct aws_allocator *allocator, void *ptr, size } /* 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"); + void *new_mem = s_non_aligned_malloc(allocator, newsize); + AWS_PANIC_OOM(new_mem, "Unhandled OOM encountered in s_non_aligned_realloc"); if (ptr) { memcpy(new_mem, ptr, oldsize); - s_no_align_free(allocator, ptr); + s_non_aligned_free(allocator, ptr); } return new_mem; } -static void *s_no_align_calloc(struct aws_allocator *allocator, size_t num, size_t size) { +static void *s_non_aligned_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"); + AWS_PANIC_OOM(mem, "Unhandled OOM encountered in s_non_aligned_calloc"); 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, +static struct aws_allocator default_allocator = { + .mem_acquire = s_non_aligned_malloc, + .mem_release = s_non_aligned_free, + .mem_realloc = s_non_aligned_realloc, + .mem_calloc = s_non_aligned_calloc, +}; + +struct aws_allocator *aws_default_allocator(void) { + return &default_allocator; +} + +static struct aws_allocator aligned_allocator = { + .mem_acquire = s_aligned_malloc, + .mem_release = s_aligned_free, + .mem_realloc = s_aligned_realloc, + .mem_calloc = s_aligned_calloc, }; -struct aws_allocator *aws_no_align_allocator(void) { - return &no_align_allocator; +struct aws_allocator *aws_aligned_allocator(void) { + return &aligned_allocator; } void *aws_mem_acquire(struct aws_allocator *allocator, size_t size) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a35328083..a68605398 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -320,8 +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(aligned_threaded_reallocs) +add_test_case(aligned_threaded_allocs_and_frees) add_test_case(test_memtrace_none) add_test_case(test_memtrace_count) diff --git a/tests/alloc_test.c b/tests/alloc_test.c index 060dce120..364b3f319 100644 --- a/tests/alloc_test.c +++ b/tests/alloc_test.c @@ -352,12 +352,12 @@ AWS_TEST_CASE(default_threaded_allocs_and_frees, s_default_threaded_allocs_and_f /* * No align allocator tests. */ -static int s_no_align_threaded_reallocs(struct aws_allocator *allocator, void *ctx) { +static int s_aligned_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); + struct aws_allocator *alloc = aws_mem_tracer_new(aws_aligned_allocator(), NULL, AWS_MEMTRACE_STACKS, 8); s_thread_test(alloc, s_threaded_realloc_worker, alloc); @@ -365,14 +365,14 @@ static int s_no_align_threaded_reallocs(struct aws_allocator *allocator, void *c return 0; } -AWS_TEST_CASE(no_align_threaded_reallocs, s_no_align_threaded_reallocs) +AWS_TEST_CASE(aligned_threaded_reallocs, s_aligned_threaded_reallocs) -static int s_no_align_threaded_allocs_and_frees(struct aws_allocator *allocator, void *ctx) { +static int s_aligned_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); + struct aws_allocator *alloc = aws_mem_tracer_new(aws_aligned_allocator(), NULL, AWS_MEMTRACE_STACKS, 8); s_thread_test(alloc, s_threaded_alloc_worker, alloc); @@ -380,4 +380,4 @@ static int s_no_align_threaded_allocs_and_frees(struct aws_allocator *allocator, return 0; } -AWS_TEST_CASE(no_align_threaded_allocs_and_frees, s_no_align_threaded_allocs_and_frees) +AWS_TEST_CASE(aligned_threaded_allocs_and_frees, s_aligned_threaded_allocs_and_frees)