summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2024-08-03 14:37:44 +0300
committerOxore <oxore@protonmail.com>2024-08-03 14:37:44 +0300
commit466ffe67cec1f2c460eea28a779a86cc659ddc24 (patch)
treef39bf3873cd8acbc13e97f99bad1522390d768ef
Initial commit
-rw-r--r--.gitignore2
-rw-r--r--Makefile4
-rw-r--r--Readme.md40
-rw-r--r--arena-malloc.c61
-rw-r--r--arena-memstream.c55
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);
+}