Skip to content

Commit

Permalink
lets use non-aligned allocator as default
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriyMusatkin committed Oct 23, 2023
1 parent 9dd7a24 commit 9d5e6b6
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 51 deletions.
13 changes: 6 additions & 7 deletions include/aws/common/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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. */
Expand Down
72 changes: 36 additions & 36 deletions source/allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions tests/alloc_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,32 +352,32 @@ 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);

aws_mem_tracer_destroy(alloc);

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

aws_mem_tracer_destroy(alloc);

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)

0 comments on commit 9d5e6b6

Please sign in to comment.