diff options
author | Oxore <oxore@protonmail.com> | 2024-08-03 14:37:44 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2024-08-03 14:37:44 +0300 |
commit | 466ffe67cec1f2c460eea28a779a86cc659ddc24 (patch) | |
tree | f39bf3873cd8acbc13e97f99bad1522390d768ef |
Initial commit
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | Readme.md | 40 | ||||
-rw-r--r-- | arena-malloc.c | 61 | ||||
-rw-r--r-- | arena-memstream.c | 55 |
5 files changed, 162 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..407b5f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +arena-malloc +arena-memstream diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..55248ea --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +#CFLAGS=-fsanitize=address,undefined -g3 +CFLAGS=-Ofast + +all: arena-malloc arena-memstream diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..67d3dc5 --- /dev/null +++ b/Readme.md @@ -0,0 +1,40 @@ +# Arena allocator benchmark + +`50_000_000` of 16 byte allocations, `-Ofast`, without sanitizers. + +arena-malloc (`realloc` 1.5x of size): + +``` +$ perf stat -r10 -B ./arena-malloc + + Performance counter stats for './arena-malloc' (10 runs): + + 340.31 msec task-clock:u # 0.965 CPUs utilized ( +- 0.77% ) + 0 context-switches:u # 0.000 /sec + 0 cpu-migrations:u # 0.000 /sec + 6,055 page-faults:u # 17.792 K/sec ( +- 0.01% ) + 255,422,997 cycles:u # 0.751 GHz ( +- 0.07% ) + 700,131,646 instructions:u # 2.74 insn per cycle ( +- 0.00% ) + 100,031,363 branches:u # 293.938 M/sec ( +- 0.00% ) + 2,612 branch-misses:u # 0.00% of all branches ( +- 0.97% ) + + 0.35257 +- 0.00692 seconds time elapsed ( +- 1.96% ) +``` + +arena-memstream (`open_memstream`, `fwrite`, `fflush`): +``` +$ perf stat -r10 -B ./arena-memstream + + Performance counter stats for './arena-memstream' (10 runs): + + 3,914.75 msec task-clock:u # 0.978 CPUs utilized ( +- 0.07% ) + 0 context-switches:u # 0.000 /sec + 0 cpu-migrations:u # 0.000 /sec + 46,927 page-faults:u # 11.987 K/sec ( +- 0.39% ) + 8,395,773,261 cycles:u # 2.145 GHz ( +- 0.07% ) + 14,089,659,266 instructions:u # 1.68 insn per cycle ( +- 0.00% ) + 2,871,455,062 branches:u # 733.496 M/sec ( +- 0.00% ) + 447,933 branch-misses:u # 0.02% of all branches ( +- 47.49% ) + + 4.00461 +- 0.00335 seconds time elapsed ( +- 0.08% ) +``` diff --git a/arena-malloc.c b/arena-malloc.c new file mode 100644 index 0000000..4246047 --- /dev/null +++ b/arena-malloc.c @@ -0,0 +1,61 @@ +#include <assert.h> +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + +struct arena { + void *buffer; + size_t offset; + size_t size; +}; + +void arena_create(struct arena *arena) +{ + unsigned long const init_size = 10ul * 1024ul * 1024ul; + *arena = (struct arena){ + .buffer = malloc(init_size), + .size = init_size, + }; +} + +void arena_destroy(struct arena *arena) +{ + free(arena->buffer); + *arena = (struct arena){0}; +} + +size_t arena_add(struct arena *arena, void const *data, size_t const size) +{ + size_t const offset = arena->offset; + if (size + offset > arena->size) { + arena->size = (size + offset) * 1.5; + arena->buffer = realloc(arena->buffer, arena->size); + assert(arena->buffer); + } + if (data) { + memcpy(arena->buffer + offset, data, size); + } + arena->offset += size; + return offset; +} + +static inline void *arena_get(struct arena const *arena, size_t offset) +{ + return arena->buffer + offset; +} + +int main(int argc, char * const argv[]) +{ + (void)argc; + (void)argv; + struct arena arena; + arena_create(&arena); + unsigned data[4] = {1u, 2u, 3u, 4u}; + for (size_t i = 0; i < 50000000lu; i++) { + size_t const offset = arena_add(&arena, data, sizeof(data)); + data[0] = (uintptr_t)arena_get(&arena, offset); + } + arena_destroy(&arena); +} diff --git a/arena-memstream.c b/arena-memstream.c new file mode 100644 index 0000000..64ca090 --- /dev/null +++ b/arena-memstream.c @@ -0,0 +1,55 @@ +#include <assert.h> +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + +struct arena { + FILE *stream; + char *buffer; + size_t offset; + size_t size; +}; + +void arena_create(struct arena *arena) +{ + *arena = (struct arena){open_memstream(&arena->buffer, &arena->size)}; +} + +void arena_destroy(struct arena *arena) +{ + fclose(arena->stream); + free(arena->buffer); + *arena = (struct arena){0}; +} + +size_t arena_add(struct arena *arena, void const *data, size_t const size) +{ + size_t const offset = arena->offset; + if (data) { + fwrite(data, 1, size, arena->stream); + } + arena->offset += size; + return offset; +} + +static inline void *arena_get(struct arena const *arena, size_t offset) +{ + fflush(arena->stream); + return arena->buffer + offset; +} + +int main(int argc, char * const argv[]) +{ + (void)argc; + (void)argv; + struct arena arena; + arena_create(&arena); + unsigned data[4] = {1u, 2u, 3u, 4u}; + for (size_t i = 0; i < 50000000lu; i++) { + size_t const offset = arena_add(&arena, data, sizeof(data)); + data[0] = (uintptr_t)arena_get(&arena, offset); + } + arena_destroy(&arena); +} |