From a2f0dba1245270b346e65391ee5e5e94807f2510 Mon Sep 17 00:00:00 2001 From: "Peter H. Froehlich" Date: Wed, 8 May 2019 01:08:00 +0200 Subject: Initial commit. --- .clang-format | 11 +++++ Makefile | 19 ++++++++ bench.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cached.c | 73 ++++++++++++++++++++++++++++ cached.h | 18 +++++++ 5 files changed, 274 insertions(+) create mode 100644 .clang-format create mode 100644 Makefile create mode 100644 bench.c create mode 100644 cached.c create mode 100644 cached.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1585e79 --- /dev/null +++ b/.clang-format @@ -0,0 +1,11 @@ +BasedOnStyle: LLVM +IndentWidth: 8 +UseTab: Always +BreakBeforeBraces: Linux +AllowShortIfStatementsOnASingleLine: false +IndentCaseLabels: false + +AlwaysBreakAfterReturnType: All +AlignAfterOpenBracket: DontAlign +ContinuationIndentWidth: 16 +SortIncludes: false diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0ff5c08 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +CFLAGS=-std=gnu11 -Wall -Wextra -Wpedantic -Og -g -D_DEFAULT_SOURCE \ + -fsanitize=undefined -fsanitize=address +LDFLAGS=-fsanitize=undefined -fsanitize=address + +ALL=bench + +all: $(ALL) + +bench: bench.o cached.o + +clean: + $(RM) $(ALL) *.o + +.PHONY: all check clean format + +check: + cppcheck --enable=all --std=c11 *.[ch] +format: + clang-format -i *.[ch] diff --git a/bench.c b/bench.c new file mode 100644 index 0000000..fb95c2e --- /dev/null +++ b/bench.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include + +#include "cached.h" + +#define UNUSED __attribute__((unused)) + +static sig_atomic_t running; + +static void +panic(const char *msg) +{ + fprintf(stderr, "panic: %s\n", msg); + exit(EXIT_FAILURE); +} + +static void +alarm_handler(int sig UNUSED, siginfo_t *info UNUSED, void *arg UNUSED) +{ + running = 0; +} + +static void +trap_signals(void) +{ + struct sigaction sa; + + sa.sa_sigaction = alarm_handler; + sa.sa_flags = SA_SIGINFO; + + if (sigaction(SIGALRM, &sa, NULL) < 0) { + panic("failed to setup signal handler"); + } +} + +static void +set_alarm(void) +{ + running = 1; + alarm(1); +} + +static size_t +bench_malloc(size_t allocs, size_t objsize) +{ + void *objs[allocs]; + size_t count = 0; + + while (running) { + for (size_t i = 0; i < allocs; i++) { + objs[i] = calloc(1, objsize); + count++; + } + for (size_t i = 0; i < allocs; i++) { + free(objs[i]); + } + } + + return count; +} + +static size_t +bench_ca_alloc(size_t allocs) +{ + void *objs[allocs]; + size_t count = 0; + + while (running) { + for (size_t i = 0; i < allocs; i++) { + objs[i] = ca_alloc(); + count++; + } + for (size_t i = 0; i < allocs; i++) { + ca_free(objs[i]); + } + } + + return count; +} + +static void +bench_four(void) +{ + if (ca_setup(256, 4096) < 0) { + panic("failed to setup cached allocator"); + } + + set_alarm(); + + size_t allocs = bench_ca_alloc(1024); + + printf("%-12s\t%9zu allocs/second\n", "huge_cache", allocs); + + ca_cleanup(); +} + +static void +bench_one(void) +{ + if (ca_setup(256, 1024) < 0) { + panic("failed to setup cached allocator"); + } + + set_alarm(); + + size_t allocs = bench_ca_alloc(1024); + + printf("%-12s\t%9zu allocs/second\n", "large_cache", allocs); + + ca_cleanup(); +} + +static void +bench_two(void) +{ + if (ca_setup(256, 16) < 0) { + panic("failed to setup cached allocator"); + } + + set_alarm(); + + size_t allocs = bench_ca_alloc(1024); + + printf("%-12s\t%9zu allocs/second\n", "small_cache", allocs); + + ca_cleanup(); +} + +static void +bench_three(void) +{ + set_alarm(); + + size_t allocs = bench_malloc(1024, 256); + + printf("%-12s\t%9zu allocs/second\n", "just_malloc", allocs); +} + +int +main(void) +{ + trap_signals(); + + bench_three(); + puts(""); + bench_two(); + bench_one(); + bench_four(); + + exit(EXIT_SUCCESS); +} diff --git a/cached.c b/cached.c new file mode 100644 index 0000000..8174cda --- /dev/null +++ b/cached.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#include "cached.h" + +static size_t object_size; +static size_t max_cached; +static size_t num_cached; +static void **cache; + +int +ca_setup(size_t osize, size_t csize) +{ + /* TODO allow osize == 0 following malloc? */ + if (osize == 0 || csize == 0) { + return -1; + } + + cache = calloc(csize, sizeof(*cache)); + if (cache == NULL) { + return -2; + } + + object_size = osize; + max_cached = csize; + num_cached = 0; + + return 0; +} + +void * +ca_alloc(void) +{ + assert(cache != NULL); + + if (num_cached > 0) { + void *object = cache[--num_cached]; + return object; + } + + return calloc(1, object_size); +} + +void +ca_free(void *object) +{ + assert(cache != NULL); + + if (object == NULL) { + /* free(3) also does nothing for NULL */ + return; + } + + if (num_cached < max_cached) { + cache[num_cached++] = object; + /* memset here to catch dangling references */ + memset(object, 0, object_size); + return; + } + + free(object); +} + +void +ca_cleanup(void) +{ + for (size_t i = 0; i < num_cached; i++) { + free(cache[i]); + } + free(cache); + cache = NULL; +} diff --git a/cached.h b/cached.h new file mode 100644 index 0000000..32ca61c --- /dev/null +++ b/cached.h @@ -0,0 +1,18 @@ +#pragma once + +#ifndef CACHED_H_ +#define CACHED_H_ + +int +ca_setup(size_t object_size, size_t cache_size); + +void * +ca_alloc(void); + +void +ca_free(void *object); + +void +ca_cleanup(void); + +#endif -- cgit 1.4.1-2-gfad0